15 changed files with 6754 additions and 6668 deletions
@ -1,107 +1,111 @@ |
|||
<?php |
|||
if($_SERVER['SCRIPT_FILENAME'] == str_replace('\\', '/', __FILE__)) { |
|||
// You cannot request this file directly. |
|||
header('Location: ../', true, 302); |
|||
exit; |
|||
} |
|||
|
|||
/* |
|||
* Copyright (c) 2010-2012 Tinyboard Development Group |
|||
*/ |
|||
|
|||
if(realpath($_SERVER['SCRIPT_FILENAME']) == str_replace('\\', '/', __FILE__)) { |
|||
// You cannot request this file directly. |
|||
exit; |
|||
} |
|||
|
|||
class PreparedQueryDebug { |
|||
protected $query; |
|||
|
|||
class PreparedQueryDebug { |
|||
protected $query; |
|||
public function __construct($query) { |
|||
global $pdo; |
|||
$query = preg_replace("/[\n\t]+/", ' ', $query); |
|||
|
|||
public function __construct($query) { |
|||
global $pdo; |
|||
$query = preg_replace("/[\n\t]+/", ' ', $query); |
|||
|
|||
$this->query = $pdo->prepare($query); |
|||
} |
|||
public function __call($function, $args) { |
|||
global $config, $debug; |
|||
|
|||
if($config['debug'] && $function == 'execute') { |
|||
$start = microtime(true); |
|||
} |
|||
|
|||
$return = call_user_func_array(Array($this->query, $function), $args); |
|||
|
|||
if($config['debug'] && $function == 'execute') { |
|||
$time = round((microtime(true) - $start) * 1000, 2) . 'ms'; |
|||
|
|||
$debug['sql'][] = Array( |
|||
'query' => $this->query->queryString, |
|||
'rows' => $this->query->rowCount(), |
|||
'time' => '~' . $time |
|||
); |
|||
} |
|||
|
|||
return $return; |
|||
} |
|||
$this->query = $pdo->prepare($query); |
|||
} |
|||
|
|||
function sql_open() { |
|||
global $pdo, $config; |
|||
if($pdo) return true; |
|||
public function __call($function, $args) { |
|||
global $config, $debug; |
|||
|
|||
$dsn = $config['db']['type'] . ':host=' . $config['db']['server'] . ';dbname=' . $config['db']['database']; |
|||
if(!empty($config['db']['dsn'])) |
|||
$dsn .= ';' . $config['db']['dsn']; |
|||
try { |
|||
$options = Array(PDO::ATTR_TIMEOUT => $config['db']['timeout']); |
|||
$options = Array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'); |
|||
if($config['db']['persistent']) |
|||
$options[PDO::ATTR_PERSISTENT] = true; |
|||
return $pdo = new PDO($dsn, $config['db']['user'], $config['db']['password'], $options); |
|||
} catch(PDOException $e) { |
|||
$message = $e->getMessage(); |
|||
|
|||
// Remove any sensitive information |
|||
$message = str_replace($config['db']['user'], '<em>hidden</em>', $message); |
|||
$message = str_replace($config['db']['password'], '<em>hidden</em>', $message); |
|||
|
|||
// Print error |
|||
error('Database error: ' . $message); |
|||
if($config['debug'] && $function == 'execute') { |
|||
$start = microtime(true); |
|||
} |
|||
} |
|||
|
|||
function prepare($query) { |
|||
global $pdo, $debug, $config; |
|||
|
|||
sql_open(); |
|||
|
|||
if($config['debug']) |
|||
return new PreparedQueryDebug($query); |
|||
return $pdo->prepare($query); |
|||
} |
|||
|
|||
function query($query) { |
|||
global $pdo, $debug, $config; |
|||
$return = call_user_func_array(array($this->query, $function), $args); |
|||
|
|||
sql_open(); |
|||
|
|||
if($config['debug']) { |
|||
$start = microtime(true); |
|||
$query = $pdo->query($query); |
|||
if(!$query) |
|||
return false; |
|||
if($config['debug'] && $function == 'execute') { |
|||
$time = round((microtime(true) - $start) * 1000, 2) . 'ms'; |
|||
|
|||
$debug['sql'][] = Array( |
|||
'query' => $query->queryString, |
|||
'rows' => $query->rowCount(), |
|||
'query' => $this->query->queryString, |
|||
'rows' => $this->query->rowCount(), |
|||
'time' => '~' . $time |
|||
); |
|||
return $query; |
|||
} else { |
|||
return $pdo->query($query); |
|||
} |
|||
|
|||
return $return; |
|||
} |
|||
} |
|||
|
|||
function sql_open() { |
|||
global $pdo, $config; |
|||
if($pdo) return true; |
|||
|
|||
function db_error($PDOStatement=null) { |
|||
global $pdo; |
|||
if(isset($PDOStatement)) { |
|||
$err = $PDOStatement->errorInfo(); |
|||
return $err[2]; |
|||
} else { |
|||
$err = $pdo->errorInfo(); |
|||
return $err[2]; |
|||
} |
|||
$dsn = $config['db']['type'] . ':host=' . $config['db']['server'] . ';dbname=' . $config['db']['database']; |
|||
if(!empty($config['db']['dsn'])) |
|||
$dsn .= ';' . $config['db']['dsn']; |
|||
try { |
|||
$options = Array(PDO::ATTR_TIMEOUT => $config['db']['timeout']); |
|||
$options = Array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'); |
|||
if($config['db']['persistent']) |
|||
$options[PDO::ATTR_PERSISTENT] = true; |
|||
return $pdo = new PDO($dsn, $config['db']['user'], $config['db']['password'], $options); |
|||
} catch(PDOException $e) { |
|||
$message = $e->getMessage(); |
|||
|
|||
// Remove any sensitive information |
|||
$message = str_replace($config['db']['user'], '<em>hidden</em>', $message); |
|||
$message = str_replace($config['db']['password'], '<em>hidden</em>', $message); |
|||
|
|||
// Print error |
|||
error('Database error: ' . $message); |
|||
} |
|||
} |
|||
|
|||
function prepare($query) { |
|||
global $pdo, $debug, $config; |
|||
|
|||
sql_open(); |
|||
|
|||
if($config['debug']) |
|||
return new PreparedQueryDebug($query); |
|||
return $pdo->prepare($query); |
|||
} |
|||
|
|||
function query($query) { |
|||
global $pdo, $debug, $config; |
|||
|
|||
sql_open(); |
|||
|
|||
if($config['debug']) { |
|||
$start = microtime(true); |
|||
$query = $pdo->query($query); |
|||
if(!$query) |
|||
return false; |
|||
$time = round((microtime(true) - $start) * 1000, 2) . 'ms'; |
|||
$debug['sql'][] = Array( |
|||
'query' => $query->queryString, |
|||
'rows' => $query->rowCount(), |
|||
'time' => '~' . $time |
|||
); |
|||
return $query; |
|||
} else { |
|||
return $pdo->query($query); |
|||
} |
|||
} |
|||
|
|||
function db_error($PDOStatement=null) { |
|||
global $pdo; |
|||
if(isset($PDOStatement)) { |
|||
$err = $PDOStatement->errorInfo(); |
|||
return $err[2]; |
|||
} else { |
|||
$err = $pdo->errorInfo(); |
|||
return $err[2]; |
|||
} |
|||
?> |
|||
} |
|||
|
|||
|
@ -1,445 +1,441 @@ |
|||
<?php |
|||
if($_SERVER['SCRIPT_FILENAME'] == str_replace('\\', '/', __FILE__)) { |
|||
// You cannot request this file directly. |
|||
header('Location: ../', true, 302); |
|||
exit; |
|||
|
|||
/* |
|||
* Copyright (c) 2010-2012 Tinyboard Development Group |
|||
*/ |
|||
|
|||
if(realpath($_SERVER['SCRIPT_FILENAME']) == str_replace('\\', '/', __FILE__)) { |
|||
// You cannot request this file directly. |
|||
exit; |
|||
} |
|||
|
|||
/* |
|||
[email protected] |
|||
http://www.php.net/manual/en/function.filesize.php#100097 |
|||
*/ |
|||
function format_bytes($size) { |
|||
$units = array(' B', ' KB', ' MB', ' GB', ' TB'); |
|||
for ($i = 0; $size >= 1024 && $i < 4; $i++) $size /= 1024; |
|||
return round($size, 2).$units[$i]; |
|||
} |
|||
|
|||
function doBoardListPart($list, $root) { |
|||
global $config; |
|||
|
|||
$body = ''; |
|||
foreach($list as $board) { |
|||
if(is_array($board)) |
|||
$body .= ' [' . doBoardListPart($board, $root) . '] '; |
|||
else { |
|||
if(($key = array_search($board, $list)) && gettype($key) == 'string') { |
|||
$body .= ' <a href="' . $board . '">' . $key . '</a> /'; |
|||
} else { |
|||
$body .= ' <a href="' . $root . $board . '/' . $config['file_index'] . '">' . $board . '</a> /'; |
|||
} |
|||
} |
|||
} |
|||
$body = preg_replace('/\/$/', '', $body); |
|||
|
|||
/* |
|||
Stuff to help with the display. |
|||
*/ |
|||
return $body; |
|||
} |
|||
|
|||
function createBoardlist($mod=false) { |
|||
global $config; |
|||
|
|||
if(!isset($config['boards'])) return Array('top'=>'','bottom'=>''); |
|||
|
|||
/* |
|||
[email protected] |
|||
http://www.php.net/manual/en/function.filesize.php#100097 |
|||
*/ |
|||
function format_bytes($size) { |
|||
$units = array(' B', ' KB', ' MB', ' GB', ' TB'); |
|||
for ($i = 0; $size >= 1024 && $i < 4; $i++) $size /= 1024; |
|||
return round($size, 2).$units[$i]; |
|||
} |
|||
$body = doBoardListPart($config['boards'], $mod?'?/':$config['root']); |
|||
if(!preg_match('/\] $/', $body)) |
|||
$body = '[' . $body . ']'; |
|||
|
|||
function commaize($n) { |
|||
$n = strval($n); |
|||
return (intval($n) < 1000) ? $n : commaize(substr($n, 0, -3)) . ',' . substr($n, -3); |
|||
} |
|||
$body = trim($body); |
|||
|
|||
function doBoardListPart($list, $root) { |
|||
global $config; |
|||
|
|||
$body = ''; |
|||
foreach($list as $board) { |
|||
if(is_array($board)) |
|||
$body .= ' [' . doBoardListPart($board, $root) . '] '; |
|||
else { |
|||
if(($key = array_search($board, $list)) && gettype($key) == 'string') { |
|||
$body .= ' <a href="' . $board . '">' . $key . '</a> /'; |
|||
} else { |
|||
$body .= ' <a href="' . $root . $board . '/' . $config['file_index'] . '">' . $board . '</a> /'; |
|||
} |
|||
} |
|||
} |
|||
$body = preg_replace('/\/$/', '', $body); |
|||
|
|||
return $body; |
|||
} |
|||
return Array( |
|||
'top' => '<div class="boardlist">' . $body . '</div>', |
|||
'bottom' => '<div class="boardlist bottom">' . $body . '</div>' |
|||
); |
|||
} |
|||
|
|||
function error($message, $priority = true) { |
|||
global $board, $mod, $config; |
|||
|
|||
function createBoardlist($mod=false) { |
|||
global $config; |
|||
|
|||
if(!isset($config['boards'])) return Array('top'=>'','bottom'=>''); |
|||
|
|||
$body = doBoardListPart($config['boards'], $mod?'?/':$config['root']); |
|||
if(!preg_match('/\] $/', $body)) |
|||
$body = '[' . $body . ']'; |
|||
|
|||
$body = trim($body); |
|||
|
|||
return Array( |
|||
'top' => '<div class="boardlist">' . $body . '</div>', |
|||
'bottom' => '<div class="boardlist bottom">' . $body . '</div>' |
|||
); |
|||
if($config['syslog'] && $priority !== false) { |
|||
// Use LOG_NOTICE instead of LOG_ERR or LOG_WARNING because most error message are not significant. |
|||
_syslog($priority !== true ? $priority : LOG_NOTICE, $message); |
|||
} |
|||
|
|||
function error($message, $priority = true) { |
|||
global $board, $mod, $config; |
|||
|
|||
if($config['syslog'] && $priority !== false) { |
|||
// Use LOG_NOTICE instead of LOG_ERR or LOG_WARNING because most error message are not significant. |
|||
_syslog($priority !== true ? $priority : LOG_NOTICE, $message); |
|||
} |
|||
|
|||
if(defined('STDIN')) { |
|||
// Running from CLI |
|||
die('Error: ' . $message . "\n"); |
|||
} |
|||
|
|||
die(Element('page.html', Array( |
|||
'config'=>$config, |
|||
'title'=>'Error', |
|||
'subtitle'=>'An error has occured.', |
|||
'body'=>'<center>' . |
|||
'<h2>' . _($message) . '</h2>' . |
|||
(isset($board) ? |
|||
"<p><a href=\"" . $config['root'] . |
|||
($mod ? $config['file_mod'] . '?/' : '') . |
|||
$board['dir'] . $config['file_index'] . "\">Go back</a>.</p>" : '') . |
|||
'</center>' |
|||
))); |
|||
if(defined('STDIN')) { |
|||
// Running from CLI |
|||
die('Error: ' . $message . "\n"); |
|||
} |
|||
|
|||
function loginForm($error=false, $username=false, $redirect=false) { |
|||
global $config; |
|||
|
|||
die(Element('page.html', Array( |
|||
'index'=>$config['root'], |
|||
'title'=>_('Login'), |
|||
die(Element('page.html', Array( |
|||
'config'=>$config, |
|||
'title'=>'Error', |
|||
'subtitle'=>'An error has occured.', |
|||
'body'=>'<center>' . |
|||
'<h2>' . _($message) . '</h2>' . |
|||
(isset($board) ? |
|||
"<p><a href=\"" . $config['root'] . |
|||
($mod ? $config['file_mod'] . '?/' : '') . |
|||
$board['dir'] . $config['file_index'] . "\">Go back</a>.</p>" : '') . |
|||
'</center>' |
|||
))); |
|||
} |
|||
|
|||
function loginForm($error=false, $username=false, $redirect=false) { |
|||
global $config; |
|||
|
|||
die(Element('page.html', Array( |
|||
'index'=>$config['root'], |
|||
'title'=>_('Login'), |
|||
'config'=>$config, |
|||
'body'=>Element('login.html', Array( |
|||
'config'=>$config, |
|||
'body'=>Element('login.html', Array( |
|||
'config'=>$config, |
|||
'error'=>$error, |
|||
'username'=>utf8tohtml($username), |
|||
'redirect'=>$redirect |
|||
) |
|||
'error'=>$error, |
|||
'username'=>utf8tohtml($username), |
|||
'redirect'=>$redirect |
|||
) |
|||
))); |
|||
) |
|||
))); |
|||
} |
|||
|
|||
function pm_snippet($body, $len=null) { |
|||
global $config; |
|||
|
|||
if(!isset($len)) |
|||
$len = &$config['mod']['snippet_length']; |
|||
|
|||
// Replace line breaks with some whitespace |
|||
$body = str_replace('<br/>', ' ', $body); |
|||
|
|||
// Strip tags |
|||
$body = strip_tags($body); |
|||
|
|||
// Unescape HTML characters, to avoid splitting them in half |
|||
$body = html_entity_decode($body, ENT_COMPAT, 'UTF-8'); |
|||
|
|||
// calculate strlen() so we can add "..." after if needed |
|||
$strlen = mb_strlen($body); |
|||
|
|||
$body = substr($body, 0, $len); |
|||
|
|||
// Re-escape the characters. |
|||
return '<em>' . utf8tohtml($body) . ($strlen > $len ? '…' : '') . '</em>'; |
|||
} |
|||
|
|||
function capcode($cap) { |
|||
global $config; |
|||
|
|||
if(!$cap) |
|||
return false; |
|||
|
|||
$capcode = Array(); |
|||
if(isset($config['custom_capcode'][$cap])) { |
|||
if(is_array($config['custom_capcode'][$cap])) { |
|||
$capcode['cap'] = sprintf($config['custom_capcode'][$cap][0], $cap); |
|||
if(isset($config['custom_capcode'][$cap][1])) |
|||
$capcode['name'] = $config['custom_capcode'][$cap][1]; |
|||
if(isset($config['custom_capcode'][$cap][2])) |
|||
$capcode['trip'] = $config['custom_capcode'][$cap][2]; |
|||
} else { |
|||
$capcode['cap'] = sprintf($config['custom_capcode'][$cap], $cap); |
|||
} |
|||
} else { |
|||
$capcode['cap'] = sprintf($config['capcode'], $cap); |
|||
} |
|||
|
|||
function pm_snippet($body, $len=null) { |
|||
global $config; |
|||
|
|||
if(!isset($len)) |
|||
$len = &$config['mod']['snippet_length']; |
|||
|
|||
// Replace line breaks with some whitespace |
|||
$body = str_replace('<br/>', ' ', $body); |
|||
|
|||
// Strip tags |
|||
$body = strip_tags($body); |
|||
|
|||
// Unescape HTML characters, to avoid splitting them in half |
|||
$body = html_entity_decode($body, ENT_COMPAT, 'UTF-8'); |
|||
|
|||
// calculate strlen() so we can add "..." after if needed |
|||
$strlen = mb_strlen($body); |
|||
|
|||
$body = substr($body, 0, $len); |
|||
|
|||
// Re-escape the characters. |
|||
return '<em>' . utf8tohtml($body) . ($strlen > $len ? '…' : '') . '</em>'; |
|||
return $capcode; |
|||
} |
|||
|
|||
function truncate($body, $url, $max_lines = false, $max_chars = false) { |
|||
global $config; |
|||
|
|||
if($max_lines === false) |
|||
$max_lines = $config['body_truncate']; |
|||
if($max_chars === false) |
|||
$max_chars = $config['body_truncate_char']; |
|||
$original_body = $body; |
|||
|
|||
$lines = substr_count($body, '<br/>'); |
|||
|
|||
// Limit line count |
|||
if($lines > $max_lines) { |
|||
if(preg_match('/(((.*?)<br\/>){' . $max_lines . '})/', $body, $m)) |
|||
$body = $m[0]; |
|||
} |
|||
|
|||
function capcode($cap) { |
|||
global $config; |
|||
|
|||
if(!$cap) |
|||
return false; |
|||
$body = substr($body, 0, $max_chars); |
|||
|
|||
if($body != $original_body) { |
|||
// Remove any corrupt tags at the end |
|||
$body = preg_replace('/<([\w]+)?([^>]*)?$/', '', $body); |
|||
|
|||
$capcode = Array(); |
|||
if(isset($config['custom_capcode'][$cap])) { |
|||
if(is_array($config['custom_capcode'][$cap])) { |
|||
$capcode['cap'] = sprintf($config['custom_capcode'][$cap][0], $cap); |
|||
if(isset($config['custom_capcode'][$cap][1])) |
|||
$capcode['name'] = $config['custom_capcode'][$cap][1]; |
|||
if(isset($config['custom_capcode'][$cap][2])) |
|||
$capcode['trip'] = $config['custom_capcode'][$cap][2]; |
|||
} else { |
|||
$capcode['cap'] = sprintf($config['custom_capcode'][$cap], $cap); |
|||
// Open tags |
|||
if(preg_match_all('/<([\w]+)[^>]*>/', $body, $open_tags)) { |
|||
|
|||
$tags = Array(); |
|||
for($x=0;$x<count($open_tags[0]);$x++) { |
|||
if(!preg_match('/\/(\s+)?>$/', $open_tags[0][$x])) |
|||
$tags[] = $open_tags[1][$x]; |
|||
} |
|||
|
|||
// List successfully closed tags |
|||
if(preg_match_all('/(<\/([\w]+))>/', $body, $closed_tags)) { |
|||
for($x=0;$x<count($closed_tags[0]);$x++) { |
|||
unset($tags[array_search($closed_tags[2][$x], $tags)]); |
|||
} |
|||
} |
|||
|
|||
// remove broken HTML entity at the end (if existent) |
|||
$body = preg_replace('/&[^;]+$/', '', $body); |
|||
|
|||
// Close any open tags |
|||
foreach($tags as &$tag) { |
|||
$body .= "</{$tag}>"; |
|||
} |
|||
} else { |
|||
$capcode['cap'] = sprintf($config['capcode'], $cap); |
|||
// remove broken HTML entity at the end (if existent) |
|||
$body = preg_replace('/&[^;]+$/', '', $body); |
|||
} |
|||
|
|||
return $capcode; |
|||
$body .= '<span class="toolong">Post too long. Click <a href="' . $url . '">here</a> to view the full text.</span>'; |
|||
} |
|||
|
|||
function truncate($body, $url, $max_lines = false, $max_chars = false) { |
|||
return $body; |
|||
} |
|||
|
|||
function confirmLink($text, $title, $confirm, $href) { |
|||
global $config, $mod; |
|||
if($config['mod']['server-side_confirm']) |
|||
return '<a onclick="if(confirm(\'' . htmlentities(addslashes($confirm)) . '\')) document.location=\'?/' . htmlentities(addslashes($href)) . '\';return false;" title="' . htmlentities($title) . '" href="?/confirm/' . $href . '">' . $text . '</a>'; |
|||
else |
|||
return '<a onclick="return confirm(\'' . htmlentities(addslashes($confirm)) . '\')" title="' . htmlentities($title) . '" href="?/' . $href . '">' . $text . '</a>'; |
|||
} |
|||
|
|||
class Post { |
|||
public function __construct($id, $thread, $subject, $email, $name, $trip, $capcode, $body, $time, $thumb, $thumbx, $thumby, $file, $filex, $filey, $filesize, $filename, $ip, $embed, $root=null, $mod=false) { |
|||
global $config; |
|||
if(!isset($root)) |
|||
$root = &$config['root']; |
|||
|
|||
if($max_lines === false) |
|||
$max_lines = $config['body_truncate']; |
|||
if($max_chars === false) |
|||
$max_chars = $config['body_truncate_char']; |
|||
$original_body = $body; |
|||
$this->id = $id; |
|||
$this->thread = $thread; |
|||
$this->subject = utf8tohtml($subject); |
|||
$this->email = $email; |
|||
$this->name = utf8tohtml($name); |
|||
$this->trip = $trip; |
|||
$this->capcode = $capcode; |
|||
$this->body = $body; |
|||
$this->time = $time; |
|||
$this->thumb = $thumb; |
|||
$this->thumbx = $thumbx; |
|||
$this->thumby = $thumby; |
|||
$this->file = $file; |
|||
$this->filex = $filex; |
|||
$this->filey = $filey; |
|||
$this->filesize = $filesize; |
|||
$this->filename = $filename; |
|||
$this->ip = $ip; |
|||
$this->embed = $embed; |
|||
$this->root = $root; |
|||
$this->mod = $mod; |
|||
|
|||
$lines = substr_count($body, '<br/>'); |
|||
|
|||
// Limit line count |
|||
if($lines > $max_lines) { |
|||
if(preg_match('/(((.*?)<br\/>){' . $max_lines . '})/', $body, $m)) |
|||
$body = $m[0]; |
|||
} |
|||
if($this->mod) |
|||
// Fix internal links |
|||
// Very complicated regex |
|||
$this->body = preg_replace( |
|||
'/<a((([a-zA-Z]+="[^"]+")|[a-zA-Z]+=[a-zA-Z]+|\s)*)href="' . preg_quote($config['root'], '/') . '(' . sprintf(preg_quote($config['board_path'], '/'), '\w+') . ')/', |
|||
'<a $1href="?/$4', |
|||
$this->body |
|||
); |
|||
} |
|||
public function link($pre = '') { |
|||
global $config, $board; |
|||
|
|||
$body = substr($body, 0, $max_chars); |
|||
return $this->root . $board['dir'] . $config['dir']['res'] . sprintf($config['file_page'], $this->thread) . '#' . $pre . $this->id; |
|||
} |
|||
public function postControls() { |
|||
global $board, $config; |
|||
|
|||
if($body != $original_body) { |
|||
// Remove any corrupt tags at the end |
|||
$body = preg_replace('/<([\w]+)?([^>]*)?$/', '', $body); |
|||
$built = ''; |
|||
if($this->mod) { |
|||
// Mod controls (on posts) |
|||
|
|||
// Open tags |
|||
if(preg_match_all('/<([\w]+)[^>]*>/', $body, $open_tags)) { |
|||
|
|||
$tags = Array(); |
|||
for($x=0;$x<count($open_tags[0]);$x++) { |
|||
if(!preg_match('/\/(\s+)?>$/', $open_tags[0][$x])) |
|||
$tags[] = $open_tags[1][$x]; |
|||
} |
|||
|
|||
// List successfully closed tags |
|||
if(preg_match_all('/(<\/([\w]+))>/', $body, $closed_tags)) { |
|||
for($x=0;$x<count($closed_tags[0]);$x++) { |
|||
unset($tags[array_search($closed_tags[2][$x], $tags)]); |
|||
} |
|||
} |
|||
|
|||
// remove broken HTML entity at the end (if existent) |
|||
$body = preg_replace('/&[^;]+$/', '', $body); |
|||
|
|||
// Close any open tags |
|||
foreach($tags as &$tag) { |
|||
$body .= "</{$tag}>"; |
|||
} |
|||
} else { |
|||
// remove broken HTML entity at the end (if existent) |
|||
$body = preg_replace('/&[^;]+$/', '', $body); |
|||
} |
|||
// Delete |
|||
if(hasPermission($config['mod']['delete'], $board['uri'], $this->mod)) |
|||
$built .= ' ' . confirmLink($config['mod']['link_delete'], 'Delete', 'Are you sure you want to delete this?', $board['uri'] . '/delete/' . $this->id); |
|||
|
|||
// Delete all posts by IP |
|||
if(hasPermission($config['mod']['deletebyip'], $board['uri'], $this->mod)) |
|||
$built .= ' ' . confirmLink($config['mod']['link_deletebyip'], 'Delete all posts by IP', 'Are you sure you want to delete all posts by this IP address?', $board['uri'] . '/deletebyip/' . $this->id); |
|||
|
|||
// Delete all posts by IP (global) |
|||
if(hasPermission($config['mod']['deletebyip_global'], $board['uri'], $this->mod)) |
|||
$built .= ' ' . confirmLink($config['mod']['link_deletebyip_global'], 'Delete all posts by IP across all boards', 'Are you sure you want to delete all posts by this IP address, across all boards?', $board['uri'] . '/deletebyip/' . $this->id . '/global'); |
|||
|
|||
// Ban |
|||
if(hasPermission($config['mod']['ban'], $board['uri'], $this->mod)) |
|||
$built .= ' <a title="Ban" href="?/' . $board['uri'] . '/ban/' . $this->id . '">' . $config['mod']['link_ban'] . '</a>'; |
|||
|
|||
// Ban & Delete |
|||
if(hasPermission($config['mod']['bandelete'], $board['uri'], $this->mod)) |
|||
$built .= ' <a title="Ban & Delete" href="?/' . $board['uri'] . '/ban&delete/' . $this->id . '">' . $config['mod']['link_bandelete'] . '</a>'; |
|||
|
|||
$body .= '<span class="toolong">Post too long. Click <a href="' . $url . '">here</a> to view the full text.</span>'; |
|||
// Delete file (keep post) |
|||
if(!empty($this->file) && hasPermission($config['mod']['deletefile'], $board['uri'], $this->mod)) |
|||
$built .= ' <a title="Remove file" href="?/' . $board['uri'] . '/deletefile/' . $this->id . '">' . $config['mod']['link_deletefile'] . '</a>'; |
|||
|
|||
// Edit post |
|||
if(hasPermission($config['mod']['editpost'], $board['uri'], $this->mod)) |
|||
$built .= ' <a title="Edit post" href="?/' . $board['uri'] . '/edit/' . $this->id . '">' . $config['mod']['link_editpost'] . '</a>'; |
|||
|
|||
if(!empty($built)) |
|||
$built = '<span class="controls">' . $built . '</span>'; |
|||
} |
|||
|
|||
return $body; |
|||
return $built; |
|||
} |
|||
|
|||
function confirmLink($text, $title, $confirm, $href) { |
|||
global $config, $mod; |
|||
if($config['mod']['server-side_confirm']) |
|||
return '<a onclick="if(confirm(\'' . htmlentities(addslashes($confirm)) . '\')) document.location=\'?/' . htmlentities(addslashes($href)) . '\';return false;" title="' . htmlentities($title) . '" href="?/confirm/' . $href . '">' . $text . '</a>'; |
|||
else |
|||
return '<a onclick="return confirm(\'' . htmlentities(addslashes($confirm)) . '\')" title="' . htmlentities($title) . '" href="?/' . $href . '">' . $text . '</a>'; |
|||
public function build($index=false) { |
|||
global $board, $config; |
|||
|
|||
return Element('post_reply.html', Array('config' => $config, 'board' => $board, 'post' => &$this, 'index' => $index)); |
|||
} |
|||
|
|||
class Post { |
|||
public function __construct($id, $thread, $subject, $email, $name, $trip, $capcode, $body, $time, $thumb, $thumbx, $thumby, $file, $filex, $filey, $filesize, $filename, $ip, $embed, $root=null, $mod=false) { |
|||
global $config; |
|||
if(!isset($root)) $root = &$config['root']; |
|||
}; |
|||
|
|||
class Thread { |
|||
public function __construct($id, $subject, $email, $name, $trip, $capcode, $body, $time, $thumb, $thumbx, $thumby, $file, $filex, $filey, $filesize, $filename, $ip, $sticky, $locked, $bumplocked, $embed, $root=null, $mod=false, $hr=true) { |
|||
global $config; |
|||
if(!isset($root)) |
|||
$root = &$config['root']; |
|||
|
|||
$this->id = $id; |
|||
$this->subject = utf8tohtml($subject); |
|||
$this->email = $email; |
|||
$this->name = utf8tohtml($name); |
|||
$this->trip = $trip; |
|||
$this->capcode = $capcode; |
|||
$this->body = $body; |
|||
$this->time = $time; |
|||
$this->thumb = $thumb; |
|||
$this->thumbx = $thumbx; |
|||
$this->thumby = $thumby; |
|||
$this->file = $file; |
|||
$this->filex = $filex; |
|||
$this->filey = $filey; |
|||
$this->filesize = $filesize; |
|||
$this->filename = $filename; |
|||
$this->omitted = 0; |
|||
$this->omitted_images = 0; |
|||
$this->posts = Array(); |
|||
$this->ip = $ip; |
|||
$this->sticky = $sticky; |
|||
$this->locked = $locked; |
|||
$this->bumplocked = $bumplocked; |
|||
$this->embed = $embed; |
|||
$this->root = $root; |
|||
$this->mod = $mod; |
|||
$this->hr = $hr; |
|||
|
|||
if($this->mod) |
|||
// Fix internal links |
|||
// Very complicated regex |
|||
$this->body = preg_replace( |
|||
'/<a(([a-zA-Z]+="[^"]+")|[a-zA-Z]+=[a-zA-Z]+|\s)*href="' . preg_quote($config['root'], '/') . '(' . sprintf(preg_quote($config['board_path'], '/'), '\w+') . ')/', |
|||
'<a href="?/$3', |
|||
$this->body |
|||
); |
|||
} |
|||
public function link($pre = '') { |
|||
global $config, $board; |
|||
|
|||
return $this->root . $board['dir'] . $config['dir']['res'] . sprintf($config['file_page'], $this->id) . '#' . $pre . $this->id; |
|||
} |
|||
public function add(Post $post) { |
|||
$this->posts[] = $post; |
|||
} |
|||
public function postControls() { |
|||
global $board, $config; |
|||
|
|||
$built = ''; |
|||
if($this->mod) { |
|||
// Mod controls (on posts) |
|||
// Delete |
|||
if(hasPermission($config['mod']['delete'], $board['uri'], $this->mod)) |
|||
$built .= ' ' . confirmLink($config['mod']['link_delete'], 'Delete', 'Are you sure you want to delete this?', $board['uri'] . '/delete/' . $this->id); |
|||
|
|||
$this->id = $id; |
|||
$this->thread = $thread; |
|||
$this->subject = utf8tohtml($subject); |
|||
$this->email = $email; |
|||
$this->name = utf8tohtml($name); |
|||
$this->trip = $trip; |
|||
$this->capcode = $capcode; |
|||
$this->body = $body; |
|||
$this->time = $time; |
|||
$this->thumb = $thumb; |
|||
$this->thumbx = $thumbx; |
|||
$this->thumby = $thumby; |
|||
$this->file = $file; |
|||
$this->filex = $filex; |
|||
$this->filey = $filey; |
|||
$this->filesize = $filesize; |
|||
$this->filename = $filename; |
|||
$this->ip = $ip; |
|||
$this->embed = $embed; |
|||
$this->root = $root; |
|||
$this->mod = $mod; |
|||
// Delete all posts by IP |
|||
if(hasPermission($config['mod']['deletebyip'], $board['uri'], $this->mod)) |
|||
$built .= ' ' . confirmLink($config['mod']['link_deletebyip'], 'Delete all posts by IP', 'Are you sure you want to delete all posts by this IP address?', $board['uri'] . '/deletebyip/' . $this->id); |
|||
|
|||
if($this->mod) |
|||
// Fix internal links |
|||
// Very complicated regex |
|||
$this->body = preg_replace( |
|||
'/<a((([a-zA-Z]+="[^"]+")|[a-zA-Z]+=[a-zA-Z]+|\s)*)href="' . preg_quote($config['root'], '/') . '(' . sprintf(preg_quote($config['board_path'], '/'), '\w+') . ')/', |
|||
'<a $1href="?/$4', |
|||
$this->body |
|||
); |
|||
} |
|||
public function link($pre = '') { |
|||
global $config, $board; |
|||
// Delete all posts by IP (global) |
|||
if(hasPermission($config['mod']['deletebyip_global'], $board['uri'], $this->mod)) |
|||
$built .= ' ' . confirmLink($config['mod']['link_deletebyip_global'], 'Delete all posts by IP across all boards', 'Are you sure you want to delete all posts by this IP address, across all boards?', $board['uri'] . '/deletebyip/' . $this->id . '/global'); |
|||
|
|||
return $this->root . $board['dir'] . $config['dir']['res'] . sprintf($config['file_page'], $this->thread) . '#' . $pre . $this->id; |
|||
} |
|||
public function postControls() { |
|||
global $board, $config; |
|||
// Ban |
|||
if(hasPermission($config['mod']['ban'], $board['uri'], $this->mod)) |
|||
$built .= ' <a title="Ban" href="?/' . $board['uri'] . '/ban/' . $this->id . '">' . $config['mod']['link_ban'] . '</a>'; |
|||
|
|||
$built = ''; |
|||
if($this->mod) { |
|||
// Mod controls (on posts) |
|||
|
|||
// Delete |
|||
if(hasPermission($config['mod']['delete'], $board['uri'], $this->mod)) |
|||
$built .= ' ' . confirmLink($config['mod']['link_delete'], 'Delete', 'Are you sure you want to delete this?', $board['uri'] . '/delete/' . $this->id); |
|||
|
|||
// Delete all posts by IP |
|||
if(hasPermission($config['mod']['deletebyip'], $board['uri'], $this->mod)) |
|||
$built .= ' ' . confirmLink($config['mod']['link_deletebyip'], 'Delete all posts by IP', 'Are you sure you want to delete all posts by this IP address?', $board['uri'] . '/deletebyip/' . $this->id); |
|||
|
|||
// Delete all posts by IP (global) |
|||
if(hasPermission($config['mod']['deletebyip_global'], $board['uri'], $this->mod)) |
|||
$built .= ' ' . confirmLink($config['mod']['link_deletebyip_global'], 'Delete all posts by IP across all boards', 'Are you sure you want to delete all posts by this IP address, across all boards?', $board['uri'] . '/deletebyip/' . $this->id . '/global'); |
|||
|
|||
// Ban |
|||
if(hasPermission($config['mod']['ban'], $board['uri'], $this->mod)) |
|||
$built .= ' <a title="Ban" href="?/' . $board['uri'] . '/ban/' . $this->id . '">' . $config['mod']['link_ban'] . '</a>'; |
|||
|
|||
// Ban & Delete |
|||
if(hasPermission($config['mod']['bandelete'], $board['uri'], $this->mod)) |
|||
$built .= ' <a title="Ban & Delete" href="?/' . $board['uri'] . '/ban&delete/' . $this->id . '">' . $config['mod']['link_bandelete'] . '</a>'; |
|||
|
|||
// Delete file (keep post) |
|||
if(!empty($this->file) && hasPermission($config['mod']['deletefile'], $board['uri'], $this->mod)) |
|||
$built .= ' <a title="Remove file" href="?/' . $board['uri'] . '/deletefile/' . $this->id . '">' . $config['mod']['link_deletefile'] . '</a>'; |
|||
|
|||
// Edit post |
|||
if(hasPermission($config['mod']['editpost'], $board['uri'], $this->mod)) |
|||
$built .= ' <a title="Edit post" href="?/' . $board['uri'] . '/edit/' . $this->id . '">' . $config['mod']['link_editpost'] . '</a>'; |
|||
|
|||
if(!empty($built)) |
|||
$built = '<span class="controls">' . $built . '</span>'; |
|||
} |
|||
return $built; |
|||
} |
|||
|
|||
public function build($index=false) { |
|||
global $board, $config; |
|||
// Ban & Delete |
|||
if(hasPermission($config['mod']['bandelete'], $board['uri'], $this->mod)) |
|||
$built .= ' <a title="Ban & Delete" href="?/' . $board['uri'] . '/ban&delete/' . $this->id . '">' . $config['mod']['link_bandelete'] . '</a>'; |
|||
|
|||
return Element('post_reply.html', Array('config' => $config, 'board' => $board, 'post' => &$this, 'index' => $index)); |
|||
} |
|||
}; |
|||
|
|||
class Thread { |
|||
public function __construct($id, $subject, $email, $name, $trip, $capcode, $body, $time, $thumb, $thumbx, $thumby, $file, $filex, $filey, $filesize, $filename, $ip, $sticky, $locked, $bumplocked, $embed, $root=null, $mod=false, $hr=true) { |
|||
global $config; |
|||
if(!isset($root)) $root = &$config['root']; |
|||
// Delete file (keep post) |
|||
if(!empty($this->file) && $this->file != 'deleted' && hasPermission($config['mod']['deletefile'], $board['uri'], $this->mod)) |
|||
$built .= ' <a title="Remove file" href="?/' . $board['uri'] . '/deletefile/' . $this->id . '">' . $config['mod']['link_deletefile'] . '</a>'; |
|||
|
|||
$this->id = $id; |
|||
$this->subject = utf8tohtml($subject); |
|||
$this->email = $email; |
|||
$this->name = utf8tohtml($name); |
|||
$this->trip = $trip; |
|||
$this->capcode = $capcode; |
|||
$this->body = $body; |
|||
$this->time = $time; |
|||
$this->thumb = $thumb; |
|||
$this->thumbx = $thumbx; |
|||
$this->thumby = $thumby; |
|||
$this->file = $file; |
|||
$this->filex = $filex; |
|||
$this->filey = $filey; |
|||
$this->filesize = $filesize; |
|||
$this->filename = $filename; |
|||
$this->omitted = 0; |
|||
$this->omitted_images = 0; |
|||
$this->posts = Array(); |
|||
$this->ip = $ip; |
|||
$this->sticky = $sticky; |
|||
$this->locked = $locked; |
|||
$this->bumplocked = $bumplocked; |
|||
$this->embed = $embed; |
|||
$this->root = $root; |
|||
$this->mod = $mod; |
|||
$this->hr = $hr; |
|||
// Sticky |
|||
if(hasPermission($config['mod']['sticky'], $board['uri'], $this->mod)) |
|||
if($this->sticky) |
|||
$built .= ' <a title="Make thread not sticky" href="?/' . $board['uri'] . '/unsticky/' . $this->id . '">' . $config['mod']['link_desticky'] . '</a>'; |
|||
else |
|||
$built .= ' <a title="Make thread sticky" href="?/' . $board['uri'] . '/sticky/' . $this->id . '">' . $config['mod']['link_sticky'] . '</a>'; |
|||
|
|||
if($this->mod) |
|||
// Fix internal links |
|||
// Very complicated regex |
|||
$this->body = preg_replace( |
|||
'/<a(([a-zA-Z]+="[^"]+")|[a-zA-Z]+=[a-zA-Z]+|\s)*href="' . preg_quote($config['root'], '/') . '(' . sprintf(preg_quote($config['board_path'], '/'), '\w+') . ')/', |
|||
'<a href="?/$3', |
|||
$this->body |
|||
); |
|||
} |
|||
public function link($pre = '') { |
|||
global $config, $board; |
|||
if(hasPermission($config['mod']['bumplock'], $board['uri'], $this->mod)) |
|||
if($this->bumplocked) |
|||
$built .= ' <a title="Allow thread to be bumped" href="?/' . $board['uri'] . '/bumpunlock/' . $this->id . '">' . $config['mod']['link_bumpunlock'] . '</a>'; |
|||
else |
|||
$built .= ' <a title="Prevent thread from being bumped" href="?/' . $board['uri'] . '/bumplock/' . $this->id . '">' . $config['mod']['link_bumplock'] . '</a>'; |
|||
|
|||
return $this->root . $board['dir'] . $config['dir']['res'] . sprintf($config['file_page'], $this->id) . '#' . $pre . $this->id; |
|||
} |
|||
public function add(Post $post) { |
|||
$this->posts[] = $post; |
|||
} |
|||
public function postControls() { |
|||
global $board, $config; |
|||
// Lock |
|||
if(hasPermission($config['mod']['lock'], $board['uri'], $this->mod)) |
|||
if($this->locked) |
|||
$built .= ' <a title="Unlock thread" href="?/' . $board['uri'] . '/unlock/' . $this->id . '">' . $config['mod']['link_unlock'] . '</a>'; |
|||
else |
|||
$built .= ' <a title="Lock thread" href="?/' . $board['uri'] . '/lock/' . $this->id . '">' . $config['mod']['link_lock'] . '</a>'; |
|||
|
|||
$built = ''; |
|||
if($this->mod) { |
|||
// Mod controls (on posts) |
|||
// Delete |
|||
if(hasPermission($config['mod']['delete'], $board['uri'], $this->mod)) |
|||
$built .= ' ' . confirmLink($config['mod']['link_delete'], 'Delete', 'Are you sure you want to delete this?', $board['uri'] . '/delete/' . $this->id); |
|||
|
|||
// Delete all posts by IP |
|||
if(hasPermission($config['mod']['deletebyip'], $board['uri'], $this->mod)) |
|||
$built .= ' ' . confirmLink($config['mod']['link_deletebyip'], 'Delete all posts by IP', 'Are you sure you want to delete all posts by this IP address?', $board['uri'] . '/deletebyip/' . $this->id); |
|||
|
|||
// Delete all posts by IP (global) |
|||
if(hasPermission($config['mod']['deletebyip_global'], $board['uri'], $this->mod)) |
|||
$built .= ' ' . confirmLink($config['mod']['link_deletebyip_global'], 'Delete all posts by IP across all boards', 'Are you sure you want to delete all posts by this IP address, across all boards?', $board['uri'] . '/deletebyip/' . $this->id . '/global'); |
|||
|
|||
// Ban |
|||
if(hasPermission($config['mod']['ban'], $board['uri'], $this->mod)) |
|||
$built .= ' <a title="Ban" href="?/' . $board['uri'] . '/ban/' . $this->id . '">' . $config['mod']['link_ban'] . '</a>'; |
|||
|
|||
// Ban & Delete |
|||
if(hasPermission($config['mod']['bandelete'], $board['uri'], $this->mod)) |
|||
$built .= ' <a title="Ban & Delete" href="?/' . $board['uri'] . '/ban&delete/' . $this->id . '">' . $config['mod']['link_bandelete'] . '</a>'; |
|||
|
|||
// Delete file (keep post) |
|||
if(!empty($this->file) && $this->file != 'deleted' && hasPermission($config['mod']['deletefile'], $board['uri'], $this->mod)) |
|||
$built .= ' <a title="Remove file" href="?/' . $board['uri'] . '/deletefile/' . $this->id . '">' . $config['mod']['link_deletefile'] . '</a>'; |
|||
|
|||
// Sticky |
|||
if(hasPermission($config['mod']['sticky'], $board['uri'], $this->mod)) |
|||
if($this->sticky) |
|||
$built .= ' <a title="Make thread not sticky" href="?/' . $board['uri'] . '/unsticky/' . $this->id . '">' . $config['mod']['link_desticky'] . '</a>'; |
|||
else |
|||
$built .= ' <a title="Make thread sticky" href="?/' . $board['uri'] . '/sticky/' . $this->id . '">' . $config['mod']['link_sticky'] . '</a>'; |
|||
|
|||
if(hasPermission($config['mod']['bumplock'], $board['uri'], $this->mod)) |
|||
if($this->bumplocked) |
|||
$built .= ' <a title="Allow thread to be bumped" href="?/' . $board['uri'] . '/bumpunlock/' . $this->id . '">' . $config['mod']['link_bumpunlock'] . '</a>'; |
|||
else |
|||
$built .= ' <a title="Prevent thread from being bumped" href="?/' . $board['uri'] . '/bumplock/' . $this->id . '">' . $config['mod']['link_bumplock'] . '</a>'; |
|||
|
|||
// Lock |
|||
if(hasPermission($config['mod']['lock'], $board['uri'], $this->mod)) |
|||
if($this->locked) |
|||
$built .= ' <a title="Unlock thread" href="?/' . $board['uri'] . '/unlock/' . $this->id . '">' . $config['mod']['link_unlock'] . '</a>'; |
|||
else |
|||
$built .= ' <a title="Lock thread" href="?/' . $board['uri'] . '/lock/' . $this->id . '">' . $config['mod']['link_lock'] . '</a>'; |
|||
|
|||
if(hasPermission($config['mod']['move'], $board['uri'], $this->mod)) |
|||
$built .= ' <a title="Move thread to another board" href="?/' . $board['uri'] . '/move/' . $this->id . '">' . $config['mod']['link_move'] . '</a>'; |
|||
|
|||
// Edit post |
|||
if(hasPermission($config['mod']['editpost'], $board['uri'], $this->mod)) |
|||
$built .= ' <a title="Edit post" href="?/' . $board['uri'] . '/edit/' . $this->id . '">' . $config['mod']['link_editpost'] . '</a>'; |
|||
|
|||
if(!empty($built)) |
|||
$built = '<span class="controls op">' . $built . '</span>'; |
|||
} |
|||
return $built; |
|||
} |
|||
|
|||
public function ratio() { |
|||
return fraction($this->filex, $this->filey, ':'); |
|||
} |
|||
|
|||
public function build($index=false) { |
|||
global $board, $config, $debug; |
|||
if(hasPermission($config['mod']['move'], $board['uri'], $this->mod)) |
|||
$built .= ' <a title="Move thread to another board" href="?/' . $board['uri'] . '/move/' . $this->id . '">' . $config['mod']['link_move'] . '</a>'; |
|||
|
|||
$built = Element('post_thread.html', Array('config' => $config, 'board' => $board, 'post' => &$this, 'index' => $index)); |
|||
// Edit post |
|||
if(hasPermission($config['mod']['editpost'], $board['uri'], $this->mod)) |
|||
$built .= ' <a title="Edit post" href="?/' . $board['uri'] . '/edit/' . $this->id . '">' . $config['mod']['link_editpost'] . '</a>'; |
|||
|
|||
if(!$this->mod && $index && $config['cache']['enabled']) { |
|||
cache::set($this->cache_key($index), $built); |
|||
} |
|||
|
|||
return $built; |
|||
if(!empty($built)) |
|||
$built = '<span class="controls op">' . $built . '</span>'; |
|||
} |
|||
function cache_key($index) { |
|||
global $board; |
|||
|
|||
return 'thread_' . ($index ? 'index_' : '') . $board['uri'] . '_' . $this->id; |
|||
return $built; |
|||
} |
|||
|
|||
public function ratio() { |
|||
return fraction($this->filex, $this->filey, ':'); |
|||
} |
|||
|
|||
public function build($index=false) { |
|||
global $board, $config, $debug; |
|||
|
|||
$built = Element('post_thread.html', Array('config' => $config, 'board' => $board, 'post' => &$this, 'index' => $index)); |
|||
|
|||
if(!$this->mod && $index && $config['cache']['enabled']) { |
|||
cache::set($this->cache_key($index), $built); |
|||
} |
|||
}; |
|||
?> |
|||
|
|||
return $built; |
|||
} |
|||
function cache_key($index) { |
|||
global $board; |
|||
|
|||
return 'thread_' . ($index ? 'index_' : '') . $board['uri'] . '_' . $this->id; |
|||
} |
|||
}; |
|||
|
|||
|
File diff suppressed because it is too large
@ -1,488 +1,491 @@ |
|||
<?php |
|||
if($_SERVER['SCRIPT_FILENAME'] == str_replace('\\', '/', __FILE__)) { |
|||
// You cannot request this file directly. |
|||
header('Location: ../', true, 302); |
|||
exit; |
|||
} |
|||
|
|||
class Image { |
|||
public $src, $format, $image, $size; |
|||
public function __construct($src, $format = false) { |
|||
global $config; |
|||
|
|||
$this->src = $src; |
|||
$this->format = $format; |
|||
|
|||
if($config['thumb_method'] == 'imagick') { |
|||
$classname = 'ImageImagick'; |
|||
} elseif($config['thumb_method'] == 'convert') { |
|||
$classname = 'ImageConvert'; |
|||
} else { |
|||
$classname = 'Image' . strtoupper($this->format); |
|||
if(!class_exists($classname)) { |
|||
error('Unsupported file format: ' . $this->format); |
|||
} |
|||
} |
|||
|
|||
$this->image = new $classname($this); |
|||
if(!$this->image->valid()) { |
|||
$this->delete(); |
|||
error($config['error']['invalidimg']); |
|||
} |
|||
|
|||
$this->size = (object)Array('width' => $this->image->_width(), 'height' => $this->image->_height()); |
|||
if($this->size->width < 1 || $this->size->height < 1) { |
|||
$this->delete(); |
|||
error($config['error']['invalidimg']); |
|||
} |
|||
} |
|||
/* |
|||
* Copyright (c) 2010-2012 Tinyboard Development Group |
|||
*/ |
|||
|
|||
if(realpath($_SERVER['SCRIPT_FILENAME']) == str_replace('\\', '/', __FILE__)) { |
|||
// You cannot request this file directly. |
|||
exit; |
|||
} |
|||
|
|||
class Image { |
|||
public $src, $format, $image, $size; |
|||
public function __construct($src, $format = false) { |
|||
global $config; |
|||
|
|||
public function resize($extension, $max_width, $max_height) { |
|||
global $config; |
|||
|
|||
if($config['thumb_method'] == 'imagick') { |
|||
$classname = 'ImageImagick'; |
|||
} elseif($config['thumb_method'] == 'convert') { |
|||
$classname = 'ImageConvert'; |
|||
} else { |
|||
$classname = 'Image' . strtoupper($extension); |
|||
if(!class_exists($classname)) { |
|||
error('Unsupported file format: ' . $extension); |
|||
} |
|||
} |
|||
|
|||
$thumb = new $classname(false); |
|||
$thumb->src = $this->src; |
|||
$thumb->original_width = $this->size->width; |
|||
$thumb->original_height = $this->size->height; |
|||
|
|||
$x_ratio = $max_width / $this->size->width; |
|||
$y_ratio = $max_height / $this->size->height; |
|||
|
|||
if(($this->size->width <= $max_width) && ($this->size->height <= $max_height)) { |
|||
$width = $this->size->width; |
|||
$height = $this->size->height; |
|||
} elseif (($x_ratio * $this->size->height) < $max_height) { |
|||
$height = ceil($x_ratio * $this->size->height); |
|||
$width = $max_width; |
|||
} else { |
|||
$width = ceil($y_ratio * $this->size->width); |
|||
$height = $max_height; |
|||
$this->src = $src; |
|||
$this->format = $format; |
|||
|
|||
if($config['thumb_method'] == 'imagick') { |
|||
$classname = 'ImageImagick'; |
|||
} elseif($config['thumb_method'] == 'convert') { |
|||
$classname = 'ImageConvert'; |
|||
} else { |
|||
$classname = 'Image' . strtoupper($this->format); |
|||
if(!class_exists($classname)) { |
|||
error('Unsupported file format: ' . $this->format); |
|||
} |
|||
|
|||
$thumb->_resize($this->image->image, $width, $height); |
|||
return $thumb; |
|||
} |
|||
|
|||
public function to($dst) { |
|||
$this->image->to($dst); |
|||
$this->image = new $classname($this); |
|||
if(!$this->image->valid()) { |
|||
$this->delete(); |
|||
error($config['error']['invalidimg']); |
|||
} |
|||
|
|||
public function delete() { |
|||
file_unlink($this->src); |
|||
} |
|||
public function destroy() { |
|||
$this->image->_destroy(); |
|||
$this->size = (object)Array('width' => $this->image->_width(), 'height' => $this->image->_height()); |
|||
if($this->size->width < 1 || $this->size->height < 1) { |
|||
$this->delete(); |
|||
error($config['error']['invalidimg']); |
|||
} |
|||
} |
|||
|
|||
class ImageGD { |
|||
public function GD_create() { |
|||
$this->image = imagecreatetruecolor($this->width, $this->height); |
|||
} |
|||
public function GD_copyresampled() { |
|||
imagecopyresampled($this->image, $this->original, 0, 0, 0, 0, $this->width, $this->height, $this->original_width, $this->original_height); |
|||
public function resize($extension, $max_width, $max_height) { |
|||
global $config; |
|||
|
|||
if($config['thumb_method'] == 'imagick') { |
|||
$classname = 'ImageImagick'; |
|||
} elseif($config['thumb_method'] == 'convert') { |
|||
$classname = 'ImageConvert'; |
|||
} else { |
|||
$classname = 'Image' . strtoupper($extension); |
|||
if(!class_exists($classname)) { |
|||
error('Unsupported file format: ' . $extension); |
|||
} |
|||
} |
|||
public function GD_resize() { |
|||
$this->GD_create(); |
|||
$this->GD_copyresampled(); |
|||
|
|||
$thumb = new $classname(false); |
|||
$thumb->src = $this->src; |
|||
$thumb->original_width = $this->size->width; |
|||
$thumb->original_height = $this->size->height; |
|||
|
|||
$x_ratio = $max_width / $this->size->width; |
|||
$y_ratio = $max_height / $this->size->height; |
|||
|
|||
if(($this->size->width <= $max_width) && ($this->size->height <= $max_height)) { |
|||
$width = $this->size->width; |
|||
$height = $this->size->height; |
|||
} elseif (($x_ratio * $this->size->height) < $max_height) { |
|||
$height = ceil($x_ratio * $this->size->height); |
|||
$width = $max_width; |
|||
} else { |
|||
$width = ceil($y_ratio * $this->size->width); |
|||
$height = $max_height; |
|||
} |
|||
|
|||
$thumb->_resize($this->image->image, $width, $height); |
|||
return $thumb; |
|||
} |
|||
|
|||
class ImageBase extends ImageGD { |
|||
public $image, $src, $original, $original_width, $original_height, $width, $height; |
|||
public function valid() { |
|||
return (bool)$this->image; |
|||
} |
|||
public function to($dst) { |
|||
$this->image->to($dst); |
|||
} |
|||
|
|||
public function delete() { |
|||
file_unlink($this->src); |
|||
} |
|||
public function destroy() { |
|||
$this->image->_destroy(); |
|||
} |
|||
} |
|||
|
|||
class ImageGD { |
|||
public function GD_create() { |
|||
$this->image = imagecreatetruecolor($this->width, $this->height); |
|||
} |
|||
public function GD_copyresampled() { |
|||
imagecopyresampled($this->image, $this->original, 0, 0, 0, 0, $this->width, $this->height, $this->original_width, $this->original_height); |
|||
} |
|||
public function GD_resize() { |
|||
$this->GD_create(); |
|||
$this->GD_copyresampled(); |
|||
} |
|||
} |
|||
|
|||
class ImageBase extends ImageGD { |
|||
public $image, $src, $original, $original_width, $original_height, $width, $height; |
|||
public function valid() { |
|||
return (bool)$this->image; |
|||
} |
|||
|
|||
public function __construct($img) { |
|||
if(method_exists($this, 'init')) |
|||
$this->init(); |
|||
|
|||
public function __construct($img) { |
|||
if(method_exists($this, 'init')) |
|||
$this->init(); |
|||
|
|||
if($img !== false) { |
|||
$this->src = $img->src; |
|||
$this->from(); |
|||
} |
|||
if($img !== false) { |
|||
$this->src = $img->src; |
|||
$this->from(); |
|||
} |
|||
} |
|||
|
|||
public function _width() { |
|||
if(method_exists($this, 'width')) |
|||
return $this->width(); |
|||
// use default GD functions |
|||
return imagesx($this->image); |
|||
} |
|||
public function _height() { |
|||
if(method_exists($this, 'height')) |
|||
return $this->height(); |
|||
// use default GD functions |
|||
return imagesy($this->image); |
|||
} |
|||
public function _destroy() { |
|||
if(method_exists($this, 'destroy')) |
|||
return $this->destroy(); |
|||
// use default GD functions |
|||
return imagedestroy($this->image); |
|||
} |
|||
public function _resize($original, $width, $height) { |
|||
$this->original = &$original; |
|||
$this->width = $width; |
|||
$this->height = $height; |
|||
|
|||
public function _width() { |
|||
if(method_exists($this, 'width')) |
|||
return $this->width(); |
|||
// use default GD functions |
|||
return imagesx($this->image); |
|||
} |
|||
public function _height() { |
|||
if(method_exists($this, 'height')) |
|||
return $this->height(); |
|||
// use default GD functions |
|||
return imagesy($this->image); |
|||
} |
|||
public function _destroy() { |
|||
if(method_exists($this, 'destroy')) |
|||
return $this->destroy(); |
|||
if(method_exists($this, 'resize')) |
|||
$this->resize(); |
|||
else |
|||
// use default GD functions |
|||
return imagedestroy($this->image); |
|||
} |
|||
public function _resize($original, $width, $height) { |
|||
$this->original = &$original; |
|||
$this->width = $width; |
|||
$this->height = $height; |
|||
|
|||
if(method_exists($this, 'resize')) |
|||
$this->resize(); |
|||
else |
|||
// use default GD functions |
|||
$this->GD_resize(); |
|||
$this->GD_resize(); |
|||
} |
|||
} |
|||
|
|||
class ImageImagick extends ImageBase { |
|||
public function init() { |
|||
$this->image = new Imagick(); |
|||
$this->image->setBackgroundColor(new ImagickPixel('transparent')); |
|||
} |
|||
public function from() { |
|||
try { |
|||
$this->image->readImage($this->src); |
|||
} catch(ImagickException $e) { |
|||
// invalid image |
|||
$this->image = false; |
|||
} |
|||
} |
|||
|
|||
class ImageImagick extends ImageBase { |
|||
public function init() { |
|||
public function to($src) { |
|||
if(preg_match('/\.gif$/i', $src)) |
|||
$this->image->writeImages($src, true); |
|||
else |
|||
$this->image->writeImage($src); |
|||
} |
|||
public function width() { |
|||
return $this->image->getImageWidth(); |
|||
} |
|||
public function height() { |
|||
return $this->image->getImageHeight(); |
|||
} |
|||
public function destroy() { |
|||
return $this->image->destroy(); |
|||
} |
|||
public function resize() { |
|||
global $config; |
|||
|
|||
if(preg_match('/\.gif$/i', $this->src) && $config['thumb_ext'] == 'gif') { |
|||
$this->image = new Imagick(); |
|||
$this->image->setBackgroundColor(new ImagickPixel('transparent')); |
|||
} |
|||
public function from() { |
|||
try { |
|||
$this->image->readImage($this->src); |
|||
} catch(ImagickException $e) { |
|||
// invalid image |
|||
$this->image = false; |
|||
} |
|||
} |
|||
public function to($src) { |
|||
if(preg_match('/\.gif$/i', $src)) |
|||
$this->image->writeImages($src, true); |
|||
else |
|||
$this->image->writeImage($src); |
|||
} |
|||
public function width() { |
|||
return $this->image->getImageWidth(); |
|||
} |
|||
public function height() { |
|||
return $this->image->getImageHeight(); |
|||
} |
|||
public function destroy() { |
|||
return $this->image->destroy(); |
|||
} |
|||
public function resize() { |
|||
global $config; |
|||
$this->image->setFormat('gif'); |
|||
|
|||
if(preg_match('/\.gif$/i', $this->src) && $config['thumb_ext'] == 'gif') { |
|||
$this->image = new Imagick(); |
|||
$this->image->setFormat('gif'); |
|||
|
|||
$keep_frames = Array(); |
|||
for($i = 0; $i < $this->original->getNumberImages(); $i += floor($this->original->getNumberImages() / $config['thumb_keep_animation_frames'])) |
|||
$keep_frames[] = $i; |
|||
$keep_frames = Array(); |
|||
for($i = 0; $i < $this->original->getNumberImages(); $i += floor($this->original->getNumberImages() / $config['thumb_keep_animation_frames'])) |
|||
$keep_frames[] = $i; |
|||
|
|||
$i = 0; |
|||
$delay = 0; |
|||
foreach($this->original as $frame) { |
|||
$delay += $frame->getImageDelay(); |
|||
|
|||
$i = 0; |
|||
$delay = 0; |
|||
foreach($this->original as $frame) { |
|||
$delay += $frame->getImageDelay(); |
|||
//if($i < $config['thumb_keep_animation_frames']) { |
|||
if(in_array($i, $keep_frames)) { |
|||
// $frame->scaleImage($this->width, $this->height, false); |
|||
$frame->sampleImage($this->width, $this->height); |
|||
$frame->setImagePage($this->width, $this->height, 0, 0); |
|||
$frame->setImageDelay($delay); |
|||
$delay = 0; |
|||
|
|||
//if($i < $config['thumb_keep_animation_frames']) { |
|||
if(in_array($i, $keep_frames)) { |
|||
// $frame->scaleImage($this->width, $this->height, false); |
|||
$frame->sampleImage($this->width, $this->height); |
|||
$frame->setImagePage($this->width, $this->height, 0, 0); |
|||
$frame->setImageDelay($delay); |
|||
$delay = 0; |
|||
|
|||
$this->image->addImage($frame->getImage()); |
|||
} |
|||
$i++; |
|||
} |
|||
} else { |
|||
$this->image = clone $this->original; |
|||
$this->image->scaleImage($this->width, $this->height, false); |
|||
} |
|||
$this->image->addImage($frame->getImage()); |
|||
} |
|||
$i++; |
|||
} |
|||
} else { |
|||
$this->image = clone $this->original; |
|||
$this->image->scaleImage($this->width, $this->height, false); |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
class ImageConvert extends ImageBase { |
|||
public $width, $height, $temp; |
|||
|
|||
|
|||
class ImageConvert extends ImageBase { |
|||
public $width, $height, $temp; |
|||
public function init() { |
|||
global $config; |
|||
|
|||
public function init() { |
|||
global $config; |
|||
|
|||
$this->temp = false; |
|||
} |
|||
public function from() { |
|||
$size = trim(shell_exec('identify -format "%w %h" ' . escapeshellarg($this->src . '[0]'))); |
|||
if(preg_match('/^(\d+) (\d+)$/', $size, $m)) { |
|||
$this->width = $m[1]; |
|||
$this->height = $m[2]; |