2011-06-15 17:11:52 +00:00
< ? php
2012-04-11 16:49:22 +00:00
/*
2014-04-12 18:12:42 +00:00
* Copyright ( c ) 2010 - 2014 Tinyboard Development Group
2012-04-11 16:49:22 +00:00
*/
2021-06-30 01:10:12 +00:00
require_once 'inc/bootstrap.php' ;
2015-02-16 02:16:36 +00:00
2024-01-16 18:01:13 +00:00
/**
* Utility functions
*/
/**
* Get the md5 hash of the file .
*
2024-01-16 18:01:13 +00:00
* @ param [ type ] $config Instance configuration .
* @ param [ type ] $file File to do the md5 of .
2024-01-16 18:01:13 +00:00
* @ return string | false
*/
2024-01-16 18:01:13 +00:00
function md5_hash_of_file ( $config , $file )
{
2024-01-16 18:01:13 +00:00
$cmd = false ;
if ( $config [ 'bsd_md5' ]) {
$cmd = '/sbin/md5 -r' ;
}
if ( $config [ 'gnu_md5' ]) {
$cmd = 'md5sum' ;
}
if ( $cmd ) {
$output = shell_exec_error ( $cmd . " " . escapeshellarg ( $file ));
$output = explode ( ' ' , $output );
return $output [ 0 ];
} else {
return md5_file ( $file );
}
}
2024-01-16 18:01:13 +00:00
/**
* Strip the markup from the given string
*
2024-01-16 18:01:13 +00:00
* @ param string $post_body The body of the post .
2024-01-16 18:01:13 +00:00
* @ return string
*/
function strip_markup ( $post_body )
{
if ( mysql_version () >= 50503 ) {
2024-01-16 18:01:13 +00:00
// Assume we're using the utf8mb4 charset.
return $post_body ;
2024-01-16 18:01:13 +00:00
} else {
2024-01-16 18:01:13 +00:00
// MySQL's `utf8` charset only supports up to 3-byte symbols.
// Remove anything >= 0x010000.
2024-01-16 18:01:13 +00:00
$chars = preg_split ( '//u' , $post_body , - 1 , PREG_SPLIT_NO_EMPTY );
$res = '' ;
foreach ( $chars as $char ) {
$o = 0 ;
$ord = ordutf8 ( $char , $o );
if ( $ord >= 0x010000 )
continue ;
$res .= $char ;
}
return $res ;
}
}
2024-01-16 18:01:14 +00:00
/**
* Checks if the user at the remote ip passed the captcha .
*
* @ param string $secret Server side secret .
* @ param string $response User provided response .
* @ param string $remote_ip User ip .
* @ return bool Returns true if the use passed the captcha .
*/
function check_recaptcha ( $secret , $response , $remote_ip )
{
$resp = json_decode ( file_get_contents (
sprintf (
'https://www.google.com/recaptcha/api/siteverify?secret=%s&response=%s&remoteip=%s' ,
$secret ,
urlencode ( $response ),
$remote_ip
)
), true );
return !! $resp [ 'success' ];
}
/**
* Deletes the ( single ) captcha associated with the ip and code .
*
* @ param string $ip
* @ param string $code
* @ return bool Returns true on success .
*/
function db_delete_captcha ( $ip , $code )
{
$query = prepare ( 'DELETE FROM captchas WHERE ip=:ip AND code=:code LIMIT 1' );
$query -> bindValue ( ':ip' , $ip );
$query -> bindValue ( ':code' , $code );
$query -> execute ();
return $query -> rowCount () != 0 ;
}
/**
* Get the ( single ) thread with the given id in the given board .
*
* @ param string $board Board to search in . MUST ALREADY BE SANITIZED .
* @ param int $thread_id Id of the thread .
* @ return false | array Returns false if the thread does not exist . Otherwise , an array with the thread 's ' sticky ', ' locked ' ,
* 'cycle' , 'sage' , and 'slug' properties .
*/
function db_select_thread_with_attributes ( $board , $thread_id )
{
$query = prepare ( sprintf ( " SELECT `sticky`, `locked`, `cycle`, `sage`, `slug` FROM ``posts_%s`` WHERE `id` = :id AND `thread` IS NULL LIMIT 1 " , $board ));
$query -> bindValue ( ':id' , $thread_id , PDO :: PARAM_INT );
$query -> execute () or error ( db_error ());
$thread = $query -> fetch ( PDO :: FETCH_ASSOC );
if ( ! $thread ) {
return false ;
}
return $thread ;
}
/**
* Get the threads with the given id in the given board .
*
* @ param string $board Board to search in . MUST ALREADY BE SANITIZED .
* @ param int $thread_id Id of the thread .
* @ return false | array Returns false if no thread exists . Otherwise , an array of arrays with the threads 'id' , 'thread'
* and 'body_nomarkup' properties .
*/
function db_select_threads_minimal ( $board , $thread_id )
{
$query = prepare ( sprintf ( " SELECT `id`, `thread`, `body_nomarkup` FROM ``posts_%s`` WHERE `id` = :id " , $board ));
$query -> bindValue ( ':id' , $thread_id , PDO :: PARAM_INT );
$query -> execute () or error ( db_error ( $query ));
$threads = $query -> fetch ( PDO :: FETCH_ASSOC );
if ( ! $threads ) {
return false ;
}
return $threads ;
}
/**
* Inserts a new report .
*
* @ param string $ip Ip of the user sending the report .
2024-01-16 18:47:43 +00:00
* @ param string $board Board of the reported thread . MUST ALREADY BE SANITIZED .
* @ param int $post_id Post reported .
* @ param string $reason Reason of the report .
2024-01-16 18:01:14 +00:00
* @ return void
*/
function db_insert_report ( $ip , $board , $post_id , $reason )
{
$query = prepare ( " INSERT INTO ``reports`` VALUES (NULL, :time, :ip, :board, :post, :reason) " );
$query -> bindValue ( ':time' , time (), PDO :: PARAM_INT );
$query -> bindValue ( ':ip' , $ip , PDO :: PARAM_STR );
$query -> bindValue ( ':board' , $board , PDO :: PARAM_STR );
$query -> bindValue ( ':post' , $post_id , PDO :: PARAM_INT );
$query -> bindValue ( ':reason' , $reason , PDO :: PARAM_STR );
$query -> execute () or error ( db_error ( $query ));
}
2024-01-16 18:01:13 +00:00
/**
* Inserts a new ban appeal into the database .
*
* @ param int $ban_id Ban id .
* @ param string $appeal_message Appeal message .
* @ return void
*/
2024-01-16 18:01:14 +00:00
function db_insert_ban_appeal ( $ban_id , $appeal_message )
2024-01-16 18:01:13 +00:00
{
$query = prepare ( " INSERT INTO ``ban_appeals`` VALUES (NULL, :ban_id, :time, :message, 0) " );
$query -> bindValue ( ':ban_id' , $ban_id , PDO :: PARAM_INT );
$query -> bindValue ( ':time' , time (), PDO :: PARAM_INT );
$query -> bindValue ( ':message' , $appeal_message );
$query -> execute () or error ( db_error ( $query ));
}
2024-01-16 18:01:14 +00:00
/**
* Fetches the appeals to a ban .
*
* @ param int $ban_id MUST ALREADY BE SANITIZED .
* @ return array
*/
function db_select_ban_appeals ( $ban_id )
{
$query = query ( " SELECT `denied` FROM ``ban_appeals`` WHERE `ban_id` = $ban_id " ) or error ( db_error ());
return $query -> fetchAll ( PDO :: FETCH_COLUMN );
}
2024-01-16 18:01:13 +00:00
/**
* Method handling functions
*/
2016-08-14 14:24:17 +00:00
$dropped_post = false ;
2024-01-16 18:01:13 +00:00
function handle_nntpchan ()
{
2020-12-30 01:14:42 +00:00
global $config ;
if ( $_SERVER [ 'REMOTE_ADDR' ] != $config [ 'nntpchan' ][ 'trusted_peer' ]) {
error ( " NNTPChan: Forbidden. $_SERVER[REMOTE_ADDR] is not a trusted peer " );
}
$_POST = array ();
$_POST [ 'json_response' ] = true ;
$headers = json_encode ( $_GET );
2024-01-16 18:01:13 +00:00
if ( ! isset ( $_GET [ 'Message-Id' ])) {
if ( ! isset ( $_GET [ 'Message-ID' ])) {
2020-12-30 01:14:42 +00:00
error ( " NNTPChan: No message ID " );
2024-01-16 18:01:13 +00:00
} else {
$msgid = $_GET [ 'Message-ID' ];
2020-12-30 01:14:42 +00:00
}
2024-01-16 18:01:13 +00:00
} else {
$msgid = $_GET [ 'Message-Id' ];
2020-12-30 01:14:42 +00:00
}
$groups = preg_split ( " /, \ s*/ " , $_GET [ 'Newsgroups' ]);
if ( count ( $groups ) != 1 ) {
error ( " NNTPChan: Messages can go to only one newsgroup " );
}
$group = $groups [ 0 ];
if ( ! isset ( $config [ 'nntpchan' ][ 'dispatch' ][ $group ])) {
error ( " NNTPChan: We don't synchronize $group " );
}
$xboard = $config [ 'nntpchan' ][ 'dispatch' ][ $group ];
$ref = null ;
2024-01-16 18:01:13 +00:00
if ( isset ( $_GET [ 'References' ])) {
2020-12-30 01:14:42 +00:00
$refs = preg_split ( " /, \ s*/ " , $_GET [ 'References' ]);
if ( count ( $refs ) > 1 ) {
error ( " NNTPChan: We don't support multiple references " );
}
$ref = $refs [ 0 ];
$query = prepare ( " SELECT `board`,`id` FROM ``nntp_references`` WHERE `message_id` = :ref " );
$query -> bindValue ( ':ref' , $ref );
$query -> execute () or error ( db_error ( $query ));
$ary = $query -> fetchAll ( PDO :: FETCH_ASSOC );
if ( count ( $ary ) == 0 ) {
error ( " NNTPChan: We don't have $ref that $msgid references " );
}
$p_id = $ary [ 0 ][ 'id' ];
$p_board = $ary [ 0 ][ 'board' ];
if ( $p_board != $xboard ) {
error ( " NNTPChan: Cross board references not allowed. Tried to reference $p_board on $xboard " );
}
$_POST [ 'thread' ] = $p_id ;
}
$date = isset ( $_GET [ 'Date' ]) ? strtotime ( $_GET [ 'Date' ]) : time ();
list ( $ct ) = explode ( '; ' , $_GET [ 'Content-Type' ]);
$query = prepare ( " SELECT COUNT(*) AS `c` FROM ``nntp_references`` WHERE `message_id` = :msgid " );
$query -> bindValue ( " :msgid " , $msgid );
$query -> execute () or error ( db_error ( $query ));
$a = $query -> fetch ( PDO :: FETCH_ASSOC );
if ( $a [ 'c' ] > 0 ) {
error ( " NNTPChan: We already have this post. Post discarded. " );
}
if ( $ct == 'text/plain' ) {
$content = file_get_contents ( " php://input " );
2024-01-16 18:01:13 +00:00
} elseif ( $ct == 'multipart/mixed' || $ct == 'multipart/form-data' ) {
_syslog ( LOG_INFO , " MM: Files: " . print_r ( $GLOBALS , true )); // Debug
2020-12-30 01:14:42 +00:00
$content = '' ;
$newfiles = array ();
foreach ( $_FILES [ 'attachment' ][ 'error' ] as $id => $error ) {
if ( $_FILES [ 'attachment' ][ 'type' ][ $id ] == 'text/plain' ) {
$content .= file_get_contents ( $_FILES [ 'attachment' ][ 'tmp_name' ][ $id ]);
2024-01-16 18:01:13 +00:00
} elseif ( $_FILES [ 'attachment' ][ 'type' ][ $id ] == 'message/rfc822' ) {
// Signed message, ignore for now
} else {
// A real attachment :^)
2020-12-30 01:14:42 +00:00
$file = array ();
2024-01-16 18:01:13 +00:00
$file [ 'name' ] = $_FILES [ 'attachment' ][ 'name' ][ $id ];
$file [ 'type' ] = $_FILES [ 'attachment' ][ 'type' ][ $id ];
$file [ 'size' ] = $_FILES [ 'attachment' ][ 'size' ][ $id ];
2020-12-30 01:14:42 +00:00
$file [ 'tmp_name' ] = $_FILES [ 'attachment' ][ 'tmp_name' ][ $id ];
2024-01-16 18:01:13 +00:00
$file [ 'error' ] = $_FILES [ 'attachment' ][ 'error' ][ $id ];
2020-12-30 01:14:42 +00:00
$newfiles [ " file $id " ] = $file ;
}
}
$_FILES = $newfiles ;
2024-01-16 18:01:13 +00:00
} else {
2020-12-30 01:14:42 +00:00
error ( " NNTPChan: Wrong mime type: $ct " );
}
$_POST [ 'subject' ] = isset ( $_GET [ 'Subject' ]) ? ( $_GET [ 'Subject' ] == 'None' ? '' : $_GET [ 'Subject' ]) : '' ;
$_POST [ 'board' ] = $xboard ;
2024-01-16 18:01:13 +00:00
if ( isset ( $_GET [ 'From' ])) {
2020-12-30 01:14:42 +00:00
list ( $name , $mail ) = explode ( " < " , $_GET [ 'From' ], 2 );
$mail = preg_replace ( '/>\s+$/' , '' , $mail );
$_POST [ 'name' ] = $name ;
//$_POST['email'] = $mail;
$_POST [ 'email' ] = '' ;
}
2024-01-16 18:01:13 +00:00
if ( isset ( $_GET [ 'X_Sage' ])) {
2020-12-30 01:14:42 +00:00
$_POST [ 'email' ] = 'sage' ;
}
2024-01-16 18:01:13 +00:00
$content = preg_replace_callback ( '/>>([0-9a-fA-F]{6,})/' , function ( $id ) use ( $xboard ) {
2020-12-30 01:14:42 +00:00
$id = $id [ 1 ];
$query = prepare ( " SELECT `board`,`id` FROM ``nntp_references`` WHERE `message_id_digest` LIKE :rule " );
$idx = $id . " % " ;
$query -> bindValue ( ':rule' , $idx );
$query -> execute () or error ( db_error ( $query ));
2024-01-16 18:01:13 +00:00
2020-12-30 01:14:42 +00:00
$ary = $query -> fetchAll ( PDO :: FETCH_ASSOC );
if ( count ( $ary ) == 0 ) {
return " >>>> $id " ;
2024-01-16 18:01:13 +00:00
} else {
2020-12-30 01:14:42 +00:00
$ret = array ();
foreach ( $ary as $v ) {
if ( $v [ 'board' ] != $xboard ) {
2024-01-16 18:01:13 +00:00
$ret [] = " >>>/ " . $v [ 'board' ] . " / " . $v [ 'id' ];
} else {
$ret [] = " >> " . $v [ 'id' ];
2020-12-30 01:14:42 +00:00
}
}
return implode ( $ret , " , " );
}
}, $content );
$_POST [ 'body' ] = $content ;
$dropped_post = array (
'date' => $date ,
'board' => $xboard ,
'msgid' => $msgid ,
'headers' => $headers ,
'from_nntp' => true ,
);
2016-08-14 14:24:17 +00:00
}
2024-01-16 18:01:13 +00:00
function handle_delete ()
{
2020-12-30 01:14:42 +00:00
// Delete
2021-01-18 07:35:18 +00:00
global $config , $board , $mod ;
2024-01-16 18:01:13 +00:00
if ( ! isset ( $_POST [ 'board' ], $_POST [ 'password' ])) {
2020-12-30 01:14:42 +00:00
error ( $config [ 'error' ][ 'bot' ]);
2024-01-16 18:01:13 +00:00
}
2021-01-18 07:35:18 +00:00
check_login ( false );
$is_mod = !! $mod ;
if ( isset ( $_POST [ 'mod' ]) && $_POST [ 'mod' ] && ! $mod ) {
// Mismatched claims. (As stated below "Liar, you are not a mod.")
error ( $config [ 'error' ][ 'notamod' ]);
}
2020-12-30 01:14:42 +00:00
$password = & $_POST [ 'password' ];
2024-01-16 18:01:13 +00:00
if ( $password == '' ) {
2020-12-30 01:14:42 +00:00
error ( $config [ 'error' ][ 'invalidpassword' ]);
2024-01-16 18:01:13 +00:00
}
2020-12-30 01:14:42 +00:00
$delete = array ();
foreach ( $_POST as $post => $value ) {
if ( preg_match ( '/^delete_(\d+)$/' , $post , $m )) {
2024-01-16 18:01:13 +00:00
$delete [] = ( int ) $m [ 1 ];
2020-12-30 01:14:42 +00:00
}
}
2024-01-16 18:01:13 +00:00
2020-12-30 01:14:42 +00:00
checkDNSBL ();
2024-01-16 18:01:13 +00:00
2020-12-30 01:14:42 +00:00
// Check if board exists
2024-01-16 18:01:13 +00:00
if ( ! openBoard ( $_POST [ 'board' ])) {
2020-12-30 01:14:42 +00:00
error ( $config [ 'error' ][ 'noboard' ]);
2024-01-16 18:01:13 +00:00
}
2021-01-18 07:40:04 +00:00
// Check if mod has permission to delete posts in this board
2024-01-16 18:01:13 +00:00
if ( $is_mod && ! hasPermission ( $config [ 'mod' ][ 'delete' ], $board )) {
2021-01-18 07:40:04 +00:00
error ( $config [ 'error' ][ 'noaccess' ]);
2024-01-16 18:01:13 +00:00
}
2020-12-30 01:14:42 +00:00
// Check if banned
checkBan ( $board [ 'uri' ]);
2021-01-18 07:40:04 +00:00
// Check if deletion is enabled
2024-01-16 18:01:13 +00:00
if ( ! $is_mod && ! $config [ 'allow_delete' ]) {
2020-12-30 01:14:42 +00:00
error ( _ ( 'Post deletion is not allowed!' ));
2024-01-16 18:01:13 +00:00
}
if ( empty ( $delete )) {
2020-12-30 01:14:42 +00:00
error ( $config [ 'error' ][ 'nodelete' ]);
2024-01-16 18:01:13 +00:00
}
2020-12-30 01:14:42 +00:00
foreach ( $delete as & $id ) {
$query = prepare ( sprintf ( " SELECT `thread`, `time`,`password` FROM ``posts_%s`` WHERE `id` = :id " , $board [ 'uri' ]));
$query -> bindValue ( ':id' , $id , PDO :: PARAM_INT );
$query -> execute () or error ( db_error ( $query ));
2024-01-16 18:01:13 +00:00
2020-12-30 01:14:42 +00:00
if ( $post = $query -> fetch ( PDO :: FETCH_ASSOC )) {
$thread = false ;
if ( $config [ 'user_moderation' ] && $post [ 'thread' ]) {
$thread_query = prepare ( sprintf ( " SELECT `time`,`password` FROM ``posts_%s`` WHERE `id` = :id " , $board [ 'uri' ]));
$thread_query -> bindValue ( ':id' , $post [ 'thread' ], PDO :: PARAM_INT );
$thread_query -> execute () or error ( db_error ( $query ));
2024-01-16 18:01:13 +00:00
$thread = $thread_query -> fetch ( PDO :: FETCH_ASSOC );
2020-12-30 01:14:42 +00:00
}
2021-01-10 01:24:53 +00:00
if ( isset ( $config [ 'allow_thread_deletion' ]) && ! $config [ 'allow_thread_deletion' ] && ! $post [ 'thread' ]) {
error ( $config [ 'error' ][ 'nodeletethread' ]);
}
2024-01-16 18:01:13 +00:00
if (
$password != ''
&& $post [ 'password' ] != $password
2021-01-18 07:35:18 +00:00
&& ( ! $thread || $thread [ 'password' ] != $password )
2024-01-16 18:01:13 +00:00
&& ! $is_mod
) {
2020-12-30 01:14:42 +00:00
error ( $config [ 'error' ][ 'invalidpassword' ]);
2021-01-18 07:35:18 +00:00
}
2024-01-16 18:01:13 +00:00
2021-01-18 07:35:18 +00:00
if ( $post [ 'time' ] > time () - $config [ 'delete_time' ]) {
2020-12-30 01:14:42 +00:00
error ( sprintf ( $config [ 'error' ][ 'delete_too_soon' ], until ( $post [ 'time' ] + $config [ 'delete_time' ])));
}
2024-01-16 18:01:13 +00:00
2024-03-15 09:09:14 +00:00
$ip = $_SERVER [ 'REMOTE_ADDR' ];
2020-12-30 01:14:42 +00:00
if ( isset ( $_POST [ 'file' ])) {
// Delete just the file
deleteFile ( $id );
2024-03-15 09:09:14 +00:00
modLog ( " User at $ip deleted file from his own post # $id " );
2020-12-30 01:14:42 +00:00
} else {
// Delete entire post
deletePost ( $id );
2024-03-15 09:09:14 +00:00
modLog ( " User at $ip deleted his own post # $id " );
2020-12-30 01:14:42 +00:00
}
2024-01-16 18:01:13 +00:00
_syslog (
LOG_INFO ,
'Deleted post: ' .
'/' . $board [ 'dir' ] . $config [ 'dir' ][ 'res' ] . sprintf ( $config [ 'file_page' ], $post [ 'thread' ] ? $post [ 'thread' ] : $id ) . ( $post [ 'thread' ] ? '#' . $id : '' )
2020-12-30 01:14:42 +00:00
);
}
}
2024-01-16 18:01:13 +00:00
2020-12-30 01:14:42 +00:00
buildIndex ();
2024-01-16 18:01:13 +00:00
2020-12-30 01:14:42 +00:00
$root = $is_mod ? $config [ 'root' ] . $config [ 'file_mod' ] . '?/' : $config [ 'root' ];
if ( ! isset ( $_POST [ 'json_response' ])) {
2021-06-30 02:35:33 +00:00
// If only deleting a post in a thread, redirect to the current thread
header ( 'Location: ' . $root . $board [ 'dir' ] . ( $post [ 'thread' ] ? $config [ 'dir' ][ 'res' ] . sprintf ( $config [ 'file_page' ], $post [ 'thread' ]) : $config [ 'file_index' ]), true , $config [ 'redirect_http' ]);
2020-12-30 01:14:42 +00:00
} else {
header ( 'Content-Type: text/json' );
echo json_encode ( array ( 'success' => true ));
}
2015-03-31 07:17:22 +00:00
2024-01-16 18:01:13 +00:00
// We are already done, let's continue our heavy-lifting work in the background (if we run off FastCGI)
if ( function_exists ( 'fastcgi_finish_request' ))
@ fastcgi_finish_request ();
2015-03-31 07:17:22 +00:00
2020-12-30 01:14:42 +00:00
rebuildThemes ( 'post-delete' , $board [ 'uri' ]);
2019-02-26 00:48:01 +00:00
}
2024-01-16 18:01:13 +00:00
function handle_report ()
{
global $config , $board ;
2020-12-30 01:14:42 +00:00
if ( ! isset ( $_POST [ 'board' ], $_POST [ 'reason' ]))
error ( $config [ 'error' ][ 'bot' ]);
2024-01-16 18:01:13 +00:00
2020-12-30 01:14:42 +00:00
$report = array ();
foreach ( $_POST as $post => $value ) {
if ( preg_match ( '/^delete_(\d+)$/' , $post , $m )) {
2024-01-16 18:01:13 +00:00
$report [] = ( int ) $m [ 1 ];
2020-12-30 01:14:42 +00:00
}
}
2024-01-16 18:01:13 +00:00
2020-12-30 01:14:42 +00:00
checkDNSBL ();
2024-01-16 18:01:13 +00:00
2024-01-16 18:01:13 +00:00
// Check if board exists.
if ( ! openBoard ( $_POST [ 'board' ])) {
2020-12-30 01:14:42 +00:00
error ( $config [ 'error' ][ 'noboard' ]);
2024-01-16 18:01:13 +00:00
}
2024-01-16 18:01:13 +00:00
2024-01-16 18:01:13 +00:00
// Check if banned.
2020-12-30 01:14:42 +00:00
checkBan ( $board [ 'uri' ]);
2024-01-16 18:01:13 +00:00
if ( empty ( $report )) {
2020-12-30 01:14:42 +00:00
error ( $config [ 'error' ][ 'noreport' ]);
2024-01-16 18:01:13 +00:00
}
if ( strlen ( $_POST [ 'reason' ]) > $config [ 'report_max_length' ]) {
2021-07-24 10:47:50 +00:00
error ( $config [ 'error' ][ 'toolongreport' ]);
2024-01-16 18:01:13 +00:00
}
if ( count ( $report ) > $config [ 'report_limit' ]) {
2020-12-30 01:14:42 +00:00
error ( $config [ 'error' ][ 'toomanyreports' ]);
2024-01-16 18:01:13 +00:00
}
2020-12-30 01:14:42 +00:00
if ( $config [ 'report_captcha' ] && ! isset ( $_POST [ 'captcha_text' ], $_POST [ 'captcha_cookie' ])) {
error ( $config [ 'error' ][ 'bot' ]);
}
if ( $config [ 'report_captcha' ]) {
2024-01-16 18:01:14 +00:00
// What is this?
2020-12-30 01:14:42 +00:00
$resp = file_get_contents ( $config [ 'captcha' ][ 'provider_check' ] . " ? " . http_build_query ([
'mode' => 'check' ,
'text' => $_POST [ 'captcha_text' ],
'extra' => $config [ 'captcha' ][ 'extra' ],
'cookie' => $_POST [ 'captcha_cookie' ]
]));
if ( $resp !== '1' ) {
2024-01-16 18:01:13 +00:00
error ( $config [ 'error' ][ 'captcha' ]);
2020-12-30 01:14:42 +00:00
}
}
2024-01-16 18:01:13 +00:00
2020-12-30 01:14:42 +00:00
$reason = escape_markup_modifiers ( $_POST [ 'reason' ]);
markup ( $reason );
2024-01-16 18:01:13 +00:00
2021-01-09 21:54:30 +00:00
foreach ( $report as $id ) {
2024-01-16 18:01:14 +00:00
$thread = db_select_threads_minimal ( $board [ 'uri' ], $id );
2020-12-30 01:14:42 +00:00
2021-01-09 21:54:30 +00:00
$error = event ( 'report' , array ( 'ip' => $_SERVER [ 'REMOTE_ADDR' ], 'board' => $board [ 'uri' ], 'post' => $post , 'reason' => $reason , 'link' => link_for ( $thread )));
2020-12-30 01:14:42 +00:00
if ( $error ) {
error ( $error );
}
if ( $config [ 'syslog' ])
2024-01-16 18:01:13 +00:00
_syslog (
LOG_INFO ,
'Reported post: ' .
'/' . $board [ 'dir' ] . $config [ 'dir' ][ 'res' ] . link_for ( $thread ) . ( $thread [ 'thread' ] ? '#' . $id : '' ) .
' for "' . $reason . '"'
2020-12-30 01:14:42 +00:00
);
2024-01-16 18:01:14 +00:00
db_insert_report ( $_SERVER [ 'REMOTE_ADDR' ], $board [ 'uri' ], $id , $reason );
2024-01-16 18:01:13 +00:00
if ( $config [ 'slack' ]) {
function slack ( $message , $room = " reports " , $icon = " :no_entry_sign: " )
{
$room = ( $room ) ? $room : " reports " ;
$data = " payload= " . json_encode (
array (
" channel " => " # { $room } " ,
" text " => urlencode ( $message ),
" icon_emoji " => $icon
)
);
// You can get your webhook endpoint from your Slack settings
2024-03-15 09:08:34 +00:00
// For some reason using the configuration key doesn't work
2024-01-16 18:01:13 +00:00
$ch = curl_init ( $config [ 'slack_incoming_webhook_endpoint' ]);
curl_setopt ( $ch , CURLOPT_SSL_VERIFYPEER , false );
curl_setopt ( $ch , CURLOPT_CUSTOMREQUEST , " POST " );
curl_setopt ( $ch , CURLOPT_POSTFIELDS , $data );
curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , true );
$result = curl_exec ( $ch );
curl_close ( $ch );
return $result ;
}
$postcontent = mb_substr ( $thread [ 'body_nomarkup' ], 0 , 120 ) . '... _*(POST TRIMMED)*_' ;
$slackmessage = '<' . $config [ 'domain' ] . " /mod.php?/ " . $board [ 'dir' ] . $config [ 'dir' ][ 'res' ] . ( $thread [ 'thread' ] ? $thread [ 'thread' ] : $id ) . " .html " . ( $thread [ 'thread' ] ? '#' . $id : '' ) . '> \n ' . $reason . '\n ' . $postcontent . '\n' ;
$slackresult = slack ( $slackmessage , $config [ 'slack_channel' ]);
}
if ( isset ( $config [ 'matrix' ])) {
$reported_post_url = $config [ 'domain' ] . " /mod.php?/ " . $board [ 'dir' ] . $config [ 'dir' ][ 'res' ] . ( $thread [ 'thread' ] ? $thread [ 'thread' ] : $id ) . " .html " ;
$post_url = $config [ 'matrix' ][ 'host' ] . " /_matrix/client/r0/rooms/ " . $config [ 'matrix' ][ 'room_id' ] . " /send/m.room.message?access_token= " . $config [ 'matrix' ][ 'access_token' ];
2022-04-03 22:06:42 +00:00
$trimmed_post = strlen ( $thread [ 'body_nomarkup' ]) > $config [ 'matrix' ][ 'max_message_length' ] ? ' [...]' : '' ;
$postcontent = mb_substr ( $thread [ 'body_nomarkup' ], 0 , $config [ 'matrix' ][ 'max_message_length' ]) . $trimmed_post ;
2024-01-16 18:01:13 +00:00
$matrix_message = $reported_post_url . ( $thread [ 'thread' ] ? '#' . $id : '' ) . " \n Reason: \n " . $reason . " \n Post: \n " . $postcontent . " \n " ;
$post_data = json_encode (
array (
2022-04-03 22:06:42 +00:00
" msgtype " => " m.text " ,
" body " => $matrix_message
2024-01-16 18:01:13 +00:00
)
);
2022-04-03 22:06:42 +00:00
$ch = curl_init ( $post_url );
curl_setopt ( $ch , CURLOPT_POSTFIELDS , $post_data );
curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , true );
$postResult = curl_exec ( $ch );
curl_close ( $ch );
}
2020-12-30 01:14:42 +00:00
}
2024-01-16 18:01:13 +00:00
2020-12-30 01:14:42 +00:00
$is_mod = isset ( $_POST [ 'mod' ]) && $_POST [ 'mod' ];
$root = $is_mod ? $config [ 'root' ] . $config [ 'file_mod' ] . '?/' : $config [ 'root' ];
2024-01-16 18:01:13 +00:00
2020-12-30 01:14:42 +00:00
if ( ! isset ( $_POST [ 'json_response' ])) {
$index = $root . $board [ 'dir' ] . $config [ 'file_index' ];
2024-01-16 18:01:14 +00:00
//$reported_post = $root . $board['dir'] . $config['dir']['res'] . ($thread['thread'] ? $thread['thread'] : $id) . ".html" . ($thread['thread'] ? '#' . $id : '');
2020-12-30 01:14:42 +00:00
//header('Location: ' . $reported_post);
2024-01-16 18:01:13 +00:00
echo Element ( 'page.html' , array ( 'config' => $config , 'body' => '<div style="text-align:center"><a href="javascript:window.close()">[ ' . _ ( 'Close window' ) . " ]</a> <a href=' $index '>[ " . _ ( 'Return' ) . ' ]</a></div>' , 'title' => _ ( 'Report submitted!' )));
2020-12-30 01:14:42 +00:00
} else {
header ( 'Content-Type: text/json' );
echo json_encode ( array ( 'success' => true ));
}
2019-02-26 00:48:01 +00:00
}
2024-01-16 18:01:13 +00:00
function handle_post ()
{
global $config , $dropped_post , $board , $mod , $pdo ;
2020-12-30 01:14:42 +00:00
if ( ! isset ( $_POST [ 'body' ], $_POST [ 'board' ]) && ! $dropped_post ) {
error ( $config [ 'error' ][ 'bot' ]);
}
$post = array ( 'board' => $_POST [ 'board' ], 'files' => array ());
// Check if board exists
2024-01-16 18:01:13 +00:00
if ( ! openBoard ( $post [ 'board' ])) {
2020-12-30 01:14:42 +00:00
error ( $config [ 'error' ][ 'noboard' ]);
2024-01-16 18:01:13 +00:00
}
2020-12-30 01:14:42 +00:00
$board_locked_check = ( ! isset ( $_POST [ 'mod' ]) || ! $_POST [ 'mod' ])
2024-01-16 18:01:13 +00:00
&& ( $config [ 'board_locked' ] === true
|| ( is_array ( $config [ 'board_locked' ]) && in_array ( strtolower ( $_POST [ 'board' ]), $config [ 'board_locked' ])));
2020-12-30 01:14:42 +00:00
2024-01-16 18:01:13 +00:00
if ( $board_locked_check ) {
2020-12-30 01:14:42 +00:00
error ( " Board is locked " );
}
2024-01-16 18:01:13 +00:00
if ( ! isset ( $_POST [ 'name' ])) {
2020-12-30 01:14:42 +00:00
$_POST [ 'name' ] = $config [ 'anonymous' ];
2024-01-16 18:01:13 +00:00
}
if ( ! isset ( $_POST [ 'email' ])) {
2020-12-30 01:14:42 +00:00
$_POST [ 'email' ] = '' ;
2024-01-16 18:01:13 +00:00
}
if ( ! isset ( $_POST [ 'subject' ])) {
2020-12-30 01:14:42 +00:00
$_POST [ 'subject' ] = '' ;
2024-01-16 18:01:13 +00:00
}
2024-01-16 18:01:13 +00:00
if ( ! isset ( $_POST [ 'password' ])) {
2024-01-16 18:01:13 +00:00
$_POST [ 'password' ] = '' ;
2024-01-16 18:01:13 +00:00
}
2024-01-16 18:01:13 +00:00
2020-12-30 01:14:42 +00:00
if ( isset ( $_POST [ 'thread' ])) {
$post [ 'op' ] = false ;
$post [ 'thread' ] = round ( $_POST [ 'thread' ]);
} else {
$post [ 'op' ] = true ;
}
if ( ! $dropped_post ) {
2024-01-16 18:01:13 +00:00
// Check for CAPTCHA right after opening the board so the "return" link is in there.
2020-12-30 01:14:42 +00:00
if ( $config [ 'recaptcha' ]) {
2024-01-16 18:01:14 +00:00
if ( ! isset ( $_POST [ 'g-recaptcha-response' ])) {
2024-01-16 18:01:13 +00:00
error ( $config [ 'error' ][ 'bot' ]);
2024-01-16 18:01:14 +00:00
}
if ( ! check_recaptcha ( $config [ 'recaptcha_private' ], $_POST [ 'g-recaptcha-response' ], $_SERVER [ 'REMOTE_ADDR' ])) {
2020-12-30 01:14:42 +00:00
error ( $config [ 'error' ][ 'captcha' ]);
}
}
2023-09-10 23:17:39 +00:00
if ( isset ( $config [ 'simple_spam' ]) && $post [ 'op' ]) {
2024-01-16 18:01:13 +00:00
if ( ! isset ( $_POST [ 'simple_spam' ]) || $config [ 'simple_spam' ][ 'answer' ] != $_POST [ 'simple_spam' ]) {
2023-09-12 00:04:38 +00:00
error ( $config [ 'error' ][ 'simple_spam' ]);
2023-09-10 21:46:38 +00:00
}
}
2024-01-16 18:01:13 +00:00
if ( isset ( $config [ 'securimage' ]) && $config [ 'securimage' ]) {
if ( ! isset ( $_POST [ 'captcha' ])) {
2021-05-05 12:29:06 +00:00
error ( $config [ 'error' ][ 'securimage' ][ 'missing' ]);
}
2021-05-08 10:28:46 +00:00
2024-01-16 18:01:13 +00:00
if ( empty ( $_POST [ 'captcha' ])) {
2021-05-05 12:29:06 +00:00
error ( $config [ 'error' ][ 'securimage' ][ 'empty' ]);
}
2021-05-08 10:28:46 +00:00
2024-01-16 18:01:14 +00:00
if ( ! db_delete_captcha ( $_SERVER [ 'REMOTE_ADDR' ], $_POST [ 'captcha' ])) {
2021-05-05 12:29:06 +00:00
error ( $config [ 'error' ][ 'securimage' ][ 'bad' ]);
}
}
2020-12-30 01:14:42 +00:00
2024-01-16 18:01:13 +00:00
if (
! (( $post [ 'op' ] && $_POST [ 'post' ] == $config [ 'button_newtopic' ]) ||
( ! $post [ 'op' ] && $_POST [ 'post' ] == $config [ 'button_reply' ]))
) {
2020-12-30 01:14:42 +00:00
error ( $config [ 'error' ][ 'bot' ]);
}
// Check the referrer
2024-01-16 18:01:13 +00:00
if (
$config [ 'referer_match' ] !== false &&
( ! isset ( $_SERVER [ 'HTTP_REFERER' ]) || ! preg_match ( $config [ 'referer_match' ], rawurldecode ( $_SERVER [ 'HTTP_REFERER' ])))
) {
2020-12-30 01:14:42 +00:00
error ( $config [ 'error' ][ 'referer' ]);
}
checkDNSBL ();
2024-01-16 18:01:13 +00:00
2020-12-30 01:14:42 +00:00
// Check if banned
checkBan ( $board [ 'uri' ]);
if ( $post [ 'mod' ] = isset ( $_POST [ 'mod' ]) && $_POST [ 'mod' ]) {
check_login ( false );
if ( ! $mod ) {
2024-01-16 18:01:14 +00:00
// Liar. You're not a mod >:-[
2020-12-30 01:14:42 +00:00
error ( $config [ 'error' ][ 'notamod' ]);
}
2024-01-16 18:01:13 +00:00
2020-12-30 01:14:42 +00:00
$post [ 'sticky' ] = $post [ 'op' ] && isset ( $_POST [ 'sticky' ]);
$post [ 'locked' ] = $post [ 'op' ] && isset ( $_POST [ 'lock' ]);
$post [ 'raw' ] = isset ( $_POST [ 'raw' ]);
2024-01-16 18:01:13 +00:00
if ( $post [ 'sticky' ] && ! hasPermission ( $config [ 'mod' ][ 'sticky' ], $board [ 'uri' ])) {
2020-12-30 01:14:42 +00:00
error ( $config [ 'error' ][ 'noaccess' ]);
2024-01-16 18:01:13 +00:00
}
if ( $post [ 'locked' ] && ! hasPermission ( $config [ 'mod' ][ 'lock' ], $board [ 'uri' ])) {
2020-12-30 01:14:42 +00:00
error ( $config [ 'error' ][ 'noaccess' ]);
2024-01-16 18:01:13 +00:00
}
if ( $post [ 'raw' ] && ! hasPermission ( $config [ 'mod' ][ 'rawhtml' ], $board [ 'uri' ])) {
2020-12-30 01:14:42 +00:00
error ( $config [ 'error' ][ 'noaccess' ]);
2024-01-16 18:01:13 +00:00
}
2020-12-30 01:14:42 +00:00
}
if ( ! $post [ 'mod' ] && $config [ 'spam' ][ 'enabled' ] == true ) {
$post [ 'antispam_hash' ] = checkSpam (
2024-01-16 18:01:13 +00:00
array (
$board [ 'uri' ],
isset ( $post [ 'thread' ]) ? $post [ 'thread' ] : ( $config [ 'try_smarter' ] && isset ( $_POST [ 'page' ]) ? 0 - ( int ) $_POST [ 'page' ] : null )
)
2020-12-30 01:14:42 +00:00
);
//$post['antispam_hash'] = checkSpam();
if ( $post [ 'antispam_hash' ] === true ) {
error ( $config [ 'error' ][ 'spam' ]);
}
}
2024-01-16 18:01:13 +00:00
2020-12-30 01:14:42 +00:00
if ( $config [ 'robot_enable' ] && $config [ 'robot_mute' ]) {
checkMute ();
}
2024-01-16 18:01:13 +00:00
} else {
2020-12-30 01:14:42 +00:00
$mod = $post [ 'mod' ] = false ;
}
2024-01-16 18:01:13 +00:00
2024-01-16 18:01:14 +00:00
// Check if thread exists.
2020-12-30 01:14:42 +00:00
if ( ! $post [ 'op' ]) {
2024-01-16 18:01:14 +00:00
$thread = db_select_thread_with_attributes ( $board [ 'uri' ], $post [ 'thread' ]);
2024-01-16 18:01:13 +00:00
2024-01-16 18:01:14 +00:00
if ( $thread === false ) {
2020-12-30 01:14:42 +00:00
error ( $config [ 'error' ][ 'nonexistant' ]);
}
2024-01-16 18:01:13 +00:00
} else {
2020-12-30 01:14:42 +00:00
$thread = false ;
}
2024-01-16 18:01:13 +00:00
2020-12-30 01:14:42 +00:00
// Check for an embed field
if ( $config [ 'enable_embedding' ] && isset ( $_POST [ 'embed' ]) && ! empty ( $_POST [ 'embed' ])) {
// yep; validate it
$value = $_POST [ 'embed' ];
foreach ( $config [ 'embedding' ] as & $embed ) {
if ( preg_match ( $embed [ 0 ], $value )) {
// Valid link
$post [ 'embed' ] = $value ;
// This is bad, lol.
$post [ 'no_longer_require_an_image_for_op' ] = true ;
break ;
}
}
if ( ! isset ( $post [ 'embed' ])) {
error ( $config [ 'error' ][ 'invalid_embed' ]);
}
}
if ( ! hasPermission ( $config [ 'mod' ][ 'bypass_field_disable' ], $board [ 'uri' ])) {
2024-01-16 18:01:13 +00:00
if ( $config [ 'field_disable_name' ]) {
// "forced anonymous".
$_POST [ 'name' ] = $config [ 'anonymous' ];
}
if ( $config [ 'field_disable_email' ]) {
2020-12-30 01:14:42 +00:00
$_POST [ 'email' ] = '' ;
2024-01-16 18:01:13 +00:00
}
if ( $config [ 'field_disable_password' ]) {
2020-12-30 01:14:42 +00:00
$_POST [ 'password' ] = '' ;
2024-01-16 18:01:13 +00:00
}
if ( $config [ 'field_disable_subject' ] || ( ! $post [ 'op' ] && $config [ 'field_disable_reply_subject' ])) {
2020-12-30 01:14:42 +00:00
$_POST [ 'subject' ] = '' ;
2024-01-16 18:01:13 +00:00
}
2020-12-30 01:14:42 +00:00
}
2024-01-16 18:01:13 +00:00
// Convert multiple upload format to array of files. This makes the following code
// work the same whether we used the JS or HTML multiple file upload techniques.
if ( array_key_exists ( 'file_multiple' , $_FILES )) {
$file_array = $_FILES [ 'file_multiple' ];
$_FILES = [];
// If more than 0 files were uploaded
if ( ! empty ( $file_array [ 'tmp_name' ][ 0 ])) {
$i = 0 ;
$n = count ( $file_array [ 'tmp_name' ]);
while ( $i < $n ) {
$_FILES [ strval ( $i + 1 )] = array (
'name' => $file_array [ 'name' ][ $i ],
'tmp_name' => $file_array [ 'tmp_name' ][ $i ],
'type' => $file_array [ 'type' ][ $i ],
'error' => $file_array [ 'error' ][ $i ],
'size' => $file_array [ 'size' ][ $i ]
);
$i ++ ;
2020-12-30 01:14:42 +00:00
}
}
2024-01-16 18:01:13 +00:00
}
2022-02-12 02:34:46 +00:00
2020-12-30 01:14:42 +00:00
$post [ 'name' ] = $_POST [ 'name' ] != '' ? $_POST [ 'name' ] : $config [ 'anonymous' ];
$post [ 'subject' ] = $_POST [ 'subject' ];
$post [ 'email' ] = str_replace ( ' ' , '%20' , htmlspecialchars ( $_POST [ 'email' ]));
$post [ 'body' ] = $_POST [ 'body' ];
$post [ 'password' ] = $_POST [ 'password' ];
$post [ 'has_file' ] = ( ! isset ( $post [ 'embed' ]) && (( $post [ 'op' ] && ! isset ( $post [ 'no_longer_require_an_image_for_op' ]) && $config [ 'force_image_op' ]) || count ( $_FILES ) > 0 ));
2024-01-16 18:01:13 +00:00
2020-12-30 01:14:42 +00:00
if ( ! $dropped_post ) {
if ( ! ( $post [ 'has_file' ] || isset ( $post [ 'embed' ])) || (( $post [ 'op' ] && $config [ 'force_body_op' ]) || ( ! $post [ 'op' ] && $config [ 'force_body' ]))) {
$stripped_whitespace = preg_replace ( '/[\s]/u' , '' , $post [ 'body' ]);
if ( $stripped_whitespace == '' ) {
error ( $config [ 'error' ][ 'tooshort_body' ]);
}
}
2024-01-16 18:01:13 +00:00
2020-12-30 01:14:42 +00:00
if ( ! $post [ 'op' ]) {
// Check if thread is locked
// but allow mods to post
if ( $thread [ 'locked' ] && ! hasPermission ( $config [ 'mod' ][ 'postinlocked' ], $board [ 'uri' ])) {
error ( $config [ 'error' ][ 'locked' ]);
}
2024-01-16 18:01:13 +00:00
2020-12-30 01:14:42 +00:00
$numposts = numPosts ( $post [ 'thread' ]);
2024-01-16 18:01:13 +00:00
$replythreshold = isset ( $thread [ 'cycle' ]) && $thread [ 'cycle' ] ? $numposts [ 'replies' ] - 1 : $numposts [ 'replies' ];
$imagethreshold = isset ( $thread [ 'cycle' ]) && $thread [ 'cycle' ] ? $numposts [ 'images' ] - 1 : $numposts [ 'images' ];
2020-12-30 01:14:42 +00:00
if ( $config [ 'reply_hard_limit' ] != 0 && $config [ 'reply_hard_limit' ] <= $replythreshold ) {
error ( $config [ 'error' ][ 'reply_hard_limit' ]);
}
2024-01-16 18:01:13 +00:00
2020-12-30 01:14:42 +00:00
if ( $post [ 'has_file' ] && $config [ 'image_hard_limit' ] != 0 && $config [ 'image_hard_limit' ] <= $imagethreshold ) {
error ( $config [ 'error' ][ 'image_hard_limit' ]);
}
}
2024-01-16 18:01:13 +00:00
} else {
2020-12-30 01:14:42 +00:00
if ( ! $post [ 'op' ]) {
2024-01-16 18:01:13 +00:00
$numposts = numPosts ( $post [ 'thread' ]);
2020-12-30 01:14:42 +00:00
}
}
if ( $post [ 'has_file' ]) {
// Determine size sanity
$size = 0 ;
if ( $config [ 'multiimage_method' ] == 'split' ) {
foreach ( $_FILES as $key => $file ) {
$size += $file [ 'size' ];
}
} elseif ( $config [ 'multiimage_method' ] == 'each' ) {
foreach ( $_FILES as $key => $file ) {
if ( $file [ 'size' ] > $size ) {
$size = $file [ 'size' ];
}
}
} else {
error ( _ ( 'Unrecognized file size determination method.' ));
}
$max_size = $config [ 'max_filesize' ];
2024-01-16 18:01:13 +00:00
if ( array_key_exists ( 'board_specific' , $config )) {
if ( array_key_exists ( $board [ 'uri' ], $config [ 'board_specific' ])) {
if ( array_key_exists ( 'max_filesize' , $config [ 'board_specific' ][ $board [ 'uri' ]])) {
2020-12-30 01:14:42 +00:00
$max_size = $config [ 'board_specific' ][ $board [ 'uri' ]][ 'max_filesize' ];
}
}
}
if ( $size > $max_size )
2024-01-16 18:01:13 +00:00
error ( sprintf3 (
$config [ 'error' ][ 'filesize' ],
array (
'sz' => number_format ( $size ),
'filesz' => number_format ( $size ),
'maxsz' => number_format ( $config [ 'max_filesize' ])
)
));
2020-12-30 01:14:42 +00:00
$post [ 'filesize' ] = $size ;
}
$post [ 'capcode' ] = false ;
2024-01-16 18:01:13 +00:00
2020-12-30 01:14:42 +00:00
if ( $mod && preg_match ( '/^((.+) )?## (.+)$/' , $post [ 'name' ], $matches )) {
$name = $matches [ 2 ] != '' ? $matches [ 2 ] : $config [ 'anonymous' ];
$cap = $matches [ 3 ];
2024-01-16 18:01:13 +00:00
2020-12-30 01:14:42 +00:00
if ( isset ( $config [ 'mod' ][ 'capcode' ][ $mod [ 'type' ]])) {
2024-01-16 18:01:13 +00:00
if (
$config [ 'mod' ][ 'capcode' ][ $mod [ 'type' ]] === true ||
2020-12-30 01:14:42 +00:00
( is_array ( $config [ 'mod' ][ 'capcode' ][ $mod [ 'type' ]]) &&
in_array ( $cap , $config [ 'mod' ][ 'capcode' ][ $mod [ 'type' ]])
2024-01-16 18:01:13 +00:00
)
) {
2020-12-30 01:14:42 +00:00
$post [ 'capcode' ] = utf8tohtml ( $cap );
$post [ 'name' ] = $name ;
}
}
2024-01-16 18:01:14 +00:00
} elseif ( $config [ 'joke_capcode' ]) {
2020-12-30 01:14:42 +00:00
if ( strtolower ( $post [ 'email' ]) == 'joke' ) {
2024-01-16 18:01:13 +00:00
if ( isset ( $config [ 'joke_capcode_default' ])) {
2020-12-30 01:14:42 +00:00
$cap = $config [ 'joke_capcode_default' ];
2024-01-16 18:01:13 +00:00
} else {
2020-12-30 01:14:42 +00:00
$cap = " joke " ;
}
$post [ 'capcode' ] = utf8tohtml ( $cap );
$post [ 'email' ] = '' ;
}
}
2024-01-16 18:01:13 +00:00
2020-12-30 01:14:42 +00:00
$trip = generate_tripcode ( $post [ 'name' ]);
$post [ 'name' ] = $trip [ 0 ];
$post [ 'trip' ] = isset ( $trip [ 1 ]) ? $trip [ 1 ] : '' ; // XX: Dropped posts and tripcodes
2024-01-16 18:01:13 +00:00
2020-12-30 01:14:42 +00:00
$noko = false ;
if ( strtolower ( $post [ 'email' ]) == 'noko' ) {
$noko = true ;
$post [ 'email' ] = '' ;
2024-01-16 18:01:13 +00:00
} elseif ( strtolower ( $post [ 'email' ]) == 'nonoko' ) {
2020-12-30 01:14:42 +00:00
$noko = false ;
$post [ 'email' ] = '' ;
2024-01-16 18:01:13 +00:00
} else {
$noko = $config [ 'always_noko' ];
}
2020-12-30 01:14:42 +00:00
if ( $post [ 'has_file' ]) {
$i = 0 ;
foreach ( $_FILES as $key => $file ) {
if ( $file [ 'size' ] && $file [ 'tmp_name' ]) {
2024-01-16 18:01:13 +00:00
if ( ! in_array ( $file [ 'error' ], array ( UPLOAD_ERR_NO_FILE , UPLOAD_ERR_OK ))) {
error ( sprintf3 (
$config [ 'error' ][ 'phpfileserror' ],
array (
'index' => $i + 1 ,
'code' => $file [ 'error' ]
)
));
}
$post [ 'files' ][] = process_filenames ( $file , $board [ 'dir' ], ( sizeof ( $_FILES ) > 1 ), $i );
$i ++ ;
2020-12-30 01:14:42 +00:00
}
}
}
2024-01-16 18:01:13 +00:00
if ( empty ( $post [ 'files' ])) {
$post [ 'has_file' ] = false ;
}
2020-12-30 01:14:42 +00:00
if ( ! $dropped_post ) {
// Check for a file
if ( $post [ 'op' ] && ! isset ( $post [ 'no_longer_require_an_image_for_op' ])) {
if ( ! $post [ 'has_file' ] && $config [ 'force_image_op' ]) {
error ( $config [ 'error' ][ 'noimage' ]);
}
}
// Check for too many files
if ( sizeof ( $post [ 'files' ]) > $config [ 'max_images' ]) {
error ( $config [ 'error' ][ 'toomanyimages' ]);
}
}
if ( $config [ 'strip_combining_chars' ]) {
$post [ 'name' ] = strip_combining_chars ( $post [ 'name' ]);
$post [ 'email' ] = strip_combining_chars ( $post [ 'email' ]);
$post [ 'subject' ] = strip_combining_chars ( $post [ 'subject' ]);
$post [ 'body' ] = strip_combining_chars ( $post [ 'body' ]);
}
if ( ! $dropped_post ) {
// Check string lengths
if ( mb_strlen ( $post [ 'name' ]) > 35 ) {
2024-01-16 18:01:13 +00:00
error ( sprintf ( $config [ 'error' ][ 'toolong' ], 'name' ));
2020-12-30 01:14:42 +00:00
}
if ( mb_strlen ( $post [ 'email' ]) > 40 ) {
error ( sprintf ( $config [ 'error' ][ 'toolong' ], 'email' ));
}
if ( mb_strlen ( $post [ 'subject' ]) > 100 ) {
error ( sprintf ( $config [ 'error' ][ 'toolong' ], 'subject' ));
}
if ( ! $mod && mb_strlen ( $post [ 'body' ]) > $config [ 'max_body' ]) {
error ( $config [ 'error' ][ 'toolong_body' ]);
}
if ( ! $mod && mb_strlen ( $post [ 'body' ]) > 0 && ( mb_strlen ( $post [ 'body' ]) < $config [ 'min_body' ])) {
error ( $config [ 'error' ][ 'tooshort_body' ]);
}
if ( mb_strlen ( $post [ 'password' ]) > 20 ) {
error ( sprintf ( $config [ 'error' ][ 'toolong' ], 'password' ));
}
}
wordfilters ( $post [ 'body' ]);
2024-01-16 18:01:13 +00:00
2020-12-30 01:14:42 +00:00
$post [ 'body' ] = escape_markup_modifiers ( $post [ 'body' ]);
if ( $mod && isset ( $post [ 'raw' ]) && $post [ 'raw' ]) {
$post [ 'body' ] .= " \n <tinyboard raw html>1</tinyboard> " ;
}
2024-01-16 18:01:13 +00:00
2020-12-30 01:14:42 +00:00
if ( ! $dropped_post )
2024-01-16 18:01:13 +00:00
if (( $config [ 'country_flags' ] && ! $config [ 'allow_no_country' ]) || ( $config [ 'country_flags' ] && $config [ 'allow_no_country' ] && ! isset ( $_POST [ 'no_country' ]))) {
$gi = geoip_open ( 'inc/lib/geoip/GeoIPv6.dat' , GEOIP_STANDARD );
function ipv4to6 ( $ip )
{
if ( strpos ( $ip , ':' ) !== false ) {
2024-01-16 18:01:13 +00:00
if ( strpos ( $ip , '.' ) > 0 ) {
2024-01-16 18:01:13 +00:00
$ip = substr ( $ip , strrpos ( $ip , ':' ) + 1 );
2024-01-16 18:01:13 +00:00
} else {
// Native ipv6.
return $ip ;
}
2024-01-16 18:01:13 +00:00
}
$iparr = array_pad ( explode ( '.' , $ip ), 4 , 0 );
$part7 = base_convert (( $iparr [ 0 ] * 256 ) + $iparr [ 1 ], 10 , 16 );
$part8 = base_convert (( $iparr [ 2 ] * 256 ) + $iparr [ 3 ], 10 , 16 );
return '::ffff:' . $part7 . ':' . $part8 ;
}
if ( $country_code = geoip_country_code_by_addr_v6 ( $gi , ipv4to6 ( $_SERVER [ 'REMOTE_ADDR' ]))) {
2024-01-16 18:01:13 +00:00
if ( ! in_array ( strtolower ( $country_code ), array ( 'eu' , 'ap' , 'o1' , 'a1' , 'a2' ))) {
2024-01-16 18:01:13 +00:00
$post [ 'body' ] .= " \n <tinyboard flag> " . strtolower ( $country_code ) . " </tinyboard> " .
" \n <tinyboard flag alt> " . geoip_country_name_by_addr_v6 ( $gi , ipv4to6 ( $_SERVER [ 'REMOTE_ADDR' ])) . " </tinyboard> " ;
2024-01-16 18:01:13 +00:00
}
2020-12-30 01:14:42 +00:00
}
}
if ( $config [ 'user_flag' ] && isset ( $_POST [ 'user_flag' ]))
2024-01-16 18:01:13 +00:00
if ( ! empty ( $_POST [ 'user_flag' ])) {
$user_flag = $_POST [ 'user_flag' ];
2020-12-30 01:14:42 +00:00
2024-01-16 18:01:13 +00:00
if ( ! isset ( $config [ 'user_flags' ][ $user_flag ])) {
error ( _ ( 'Invalid flag selection!' ));
}
2020-12-30 01:14:42 +00:00
2024-01-16 18:01:13 +00:00
$flag_alt = isset ( $user_flag_alt ) ? $user_flag_alt : $config [ 'user_flags' ][ $user_flag ];
2020-12-30 01:14:42 +00:00
2024-01-16 18:01:13 +00:00
$post [ 'body' ] .= " \n <tinyboard flag> " . strtolower ( $user_flag ) . " </tinyboard> " .
" \n <tinyboard flag alt> " . $flag_alt . " </tinyboard> " ;
}
2020-12-30 01:14:42 +00:00
if ( $config [ 'allowed_tags' ] && $post [ 'op' ] && isset ( $_POST [ 'tag' ]) && isset ( $config [ 'allowed_tags' ][ $_POST [ 'tag' ]])) {
$post [ 'body' ] .= " \n <tinyboard tag> " . $_POST [ 'tag' ] . " </tinyboard> " ;
}
2024-01-16 18:01:13 +00:00
if ( ! $dropped_post ) {
2015-03-24 04:19:25 +00:00
if ( $config [ 'proxy_save' ] && isset ( $_SERVER [ 'HTTP_X_FORWARDED_FOR' ])) {
2024-01-16 18:01:13 +00:00
$proxy = preg_replace ( " /[^0-9a-fA-F.,: ]/ " , '' , $_SERVER [ 'HTTP_X_FORWARDED_FOR' ]);
$post [ 'body' ] .= " \n <tinyboard proxy> " . $proxy . " </tinyboard> " ;
}
2020-12-30 01:14:42 +00:00
}
2024-01-16 18:01:13 +00:00
$post [ 'body_nomarkup' ] = strip_markup ( $post [ 'body' ]);
2020-12-30 01:14:42 +00:00
$post [ 'tracked_cites' ] = markup ( $post [ 'body' ], true );
if ( $post [ 'has_file' ]) {
$allhashes = '' ;
foreach ( $post [ 'files' ] as $key => & $file ) {
if ( $post [ 'op' ] && $config [ 'allowed_ext_op' ]) {
if ( ! in_array ( $file [ 'extension' ], $config [ 'allowed_ext_op' ])) {
error ( $config [ 'error' ][ 'unknownext' ]);
}
} elseif ( ! in_array ( $file [ 'extension' ], $config [ 'allowed_ext' ]) && ! in_array ( $file [ 'extension' ], $config [ 'allowed_ext_files' ])) {
error ( $config [ 'error' ][ 'unknownext' ]);
}
2024-01-16 18:01:13 +00:00
2020-12-30 01:14:42 +00:00
$file [ 'is_an_image' ] = ! in_array ( $file [ 'extension' ], $config [ 'allowed_ext_files' ]);
2024-01-16 18:01:13 +00:00
2020-12-30 01:14:42 +00:00
// Truncate filename if it is too long
$file [ 'filename' ] = mb_substr ( $file [ 'filename' ], 0 , $config [ 'max_filename_len' ]);
2024-01-16 18:01:13 +00:00
2020-12-30 01:14:42 +00:00
$upload = $file [ 'tmp_name' ];
2024-01-16 18:01:13 +00:00
if ( ! is_readable ( $upload )) {
2020-12-30 01:14:42 +00:00
error ( $config [ 'error' ][ 'nomove' ]);
2024-01-16 18:01:13 +00:00
}
2020-12-30 01:14:42 +00:00
2024-01-16 18:01:13 +00:00
$hash = md5_hash_of_file ( $config , $upload );
2020-12-30 01:14:42 +00:00
$file [ 'hash' ] = $hash ;
$allhashes .= $hash ;
}
2024-01-16 18:01:13 +00:00
if ( count ( $post [ 'files' ]) == 1 ) {
2020-12-30 01:14:42 +00:00
$post [ 'filehash' ] = $hash ;
2024-01-16 18:01:13 +00:00
} else {
2020-12-30 01:14:42 +00:00
$post [ 'filehash' ] = md5 ( $allhashes );
}
}
if ( ! hasPermission ( $config [ 'mod' ][ 'bypass_filters' ], $board [ 'uri' ]) && ! $dropped_post ) {
require_once 'inc/filters.php' ;
do_filters ( $post );
}
if ( $post [ 'has_file' ]) {
foreach ( $post [ 'files' ] as $key => & $file ) {
2024-01-16 18:01:13 +00:00
if ( $file [ 'is_an_image' ]) {
if ( $config [ 'ie_mime_type_detection' ] !== false ) {
// Check IE MIME type detection XSS exploit
$buffer = file_get_contents ( $upload , null , null , null , 255 );
if ( preg_match ( $config [ 'ie_mime_type_detection' ], $buffer )) {
undoImage ( $post );
error ( $config [ 'error' ][ 'mime_exploit' ]);
}
2020-12-30 01:14:42 +00:00
}
2024-01-16 18:01:13 +00:00
require_once 'inc/image.php' ;
// find dimensions of an image using GD
if ( ! $size = @ getimagesize ( $file [ 'tmp_name' ])) {
error ( $config [ 'error' ][ 'invalidimg' ]);
}
if ( ! in_array ( $size [ 2 ], array ( IMAGETYPE_PNG , IMAGETYPE_GIF , IMAGETYPE_JPEG , IMAGETYPE_BMP ))) {
error ( $config [ 'error' ][ 'invalidimg' ]);
}
if ( $size [ 0 ] > $config [ 'max_width' ] || $size [ 1 ] > $config [ 'max_height' ]) {
error ( $config [ 'error' ][ 'maxsize' ]);
}
if ( $config [ 'convert_auto_orient' ] && ( $file [ 'extension' ] == 'jpg' || $file [ 'extension' ] == 'jpeg' )) {
// The following code corrects the image orientation.
// Currently only works with the 'convert' option selected but it could easily be expanded to work with the rest if you can be bothered.
if ( ! ( $config [ 'redraw_image' ] || (( $config [ 'strip_exif' ] && ! $config [ 'use_exiftool' ]) && ( $file [ 'extension' ] == 'jpg' || $file [ 'extension' ] == 'jpeg' )))) {
if ( in_array ( $config [ 'thumb_method' ], array ( 'convert' , 'convert+gifsicle' , 'gm' , 'gm+gifsicle' ))) {
$exif = @ exif_read_data ( $file [ 'tmp_name' ]);
$gm = in_array ( $config [ 'thumb_method' ], array ( 'gm' , 'gm+gifsicle' ));
if ( isset ( $exif [ 'Orientation' ]) && $exif [ 'Orientation' ] != 1 ) {
if ( $config [ 'convert_manual_orient' ]) {
$error = shell_exec_error (( $gm ? 'gm ' : '' ) . 'convert ' .
escapeshellarg ( $file [ 'tmp_name' ]) . ' ' .
ImageConvert :: jpeg_exif_orientation ( false , $exif ) . ' ' .
( $config [ 'strip_exif' ] ? '+profile "*"' : ( $config [ 'use_exiftool' ] ? '' : '+profile "*"' )
) . ' ' .
escapeshellarg ( $file [ 'tmp_name' ]));
if ( $config [ 'use_exiftool' ] && ! $config [ 'strip_exif' ]) {
if (
$exiftool_error = shell_exec_error (
'exiftool -overwrite_original -q -q -orientation=1 -n ' .
escapeshellarg ( $file [ 'tmp_name' ])
)
)
error ( _ ( 'exiftool failed!' ), null , $exiftool_error );
} else {
// TODO: Find another way to remove the Orientation tag from the EXIF profile
// without needing `exiftool`.
}
2020-12-30 01:14:42 +00:00
} else {
2024-01-16 18:01:13 +00:00
$error = shell_exec_error (( $gm ? 'gm ' : '' ) . 'convert ' .
2020-12-30 01:14:42 +00:00
escapeshellarg ( $file [ 'tmp_name' ]) . ' -auto-orient ' . escapeshellarg ( $upload ));
2024-01-16 18:01:13 +00:00
}
if ( $error ) {
error ( _ ( 'Could not auto-orient image!' ), null , $error );
}
$size = @ getimagesize ( $file [ 'tmp_name' ]);
if ( $config [ 'strip_exif' ]) {
$file [ 'exif_stripped' ] = true ;
}
2020-12-30 01:14:42 +00:00
}
}
}
}
2024-01-16 18:01:13 +00:00
// create image object
$image = new Image ( $file [ 'tmp_name' ], $file [ 'extension' ], $size );
if ( $image -> size -> width > $config [ 'max_width' ] || $image -> size -> height > $config [ 'max_height' ]) {
$image -> delete ();
2020-12-30 01:14:42 +00:00
2024-01-16 18:01:13 +00:00
error ( $config [ 'error' ][ 'maxsize' ]);
}
2020-12-30 01:14:42 +00:00
2024-01-16 18:01:13 +00:00
$file [ 'width' ] = $image -> size -> width ;
$file [ 'height' ] = $image -> size -> height ;
if ( $config [ 'spoiler_images' ] && isset ( $_POST [ 'spoiler' ])) {
$file [ 'thumb' ] = 'spoiler' ;
$size = @ getimagesize ( $config [ 'spoiler_image' ]);
$file [ 'thumbwidth' ] = $size [ 0 ];
$file [ 'thumbheight' ] = $size [ 1 ];
} elseif (
$config [ 'minimum_copy_resize' ] &&
$image -> size -> width <= $config [ 'thumb_width' ] &&
$image -> size -> height <= $config [ 'thumb_height' ] &&
$file [ 'extension' ] == ( $config [ 'thumb_ext' ] ? $config [ 'thumb_ext' ] : $file [ 'extension' ])
) {
// Copy, because there's nothing to resize
copy ( $file [ 'tmp_name' ], $file [ 'thumb' ]);
$file [ 'thumbwidth' ] = $image -> size -> width ;
$file [ 'thumbheight' ] = $image -> size -> height ;
} else {
$thumb = $image -> resize (
$config [ 'thumb_ext' ] ? $config [ 'thumb_ext' ] : $file [ 'extension' ],
$post [ 'op' ] ? $config [ 'thumb_op_width' ] : $config [ 'thumb_width' ],
$post [ 'op' ] ? $config [ 'thumb_op_height' ] : $config [ 'thumb_height' ]
);
$thumb -> to ( $file [ 'thumb' ]);
2020-12-30 01:14:42 +00:00
2024-01-16 18:01:13 +00:00
$file [ 'thumbwidth' ] = $thumb -> width ;
$file [ 'thumbheight' ] = $thumb -> height ;
$thumb -> _destroy ();
}
if ( $config [ 'redraw_image' ] || ( !@ $file [ 'exif_stripped' ] && $config [ 'strip_exif' ] && ( $file [ 'extension' ] == 'jpg' || $file [ 'extension' ] == 'jpeg' ))) {
if ( ! $config [ 'redraw_image' ] && $config [ 'use_exiftool' ]) {
if (
$error = shell_exec_error ( 'exiftool -overwrite_original -ignoreMinorErrors -q -q -all= ' .
escapeshellarg ( $file [ 'tmp_name' ]))
) {
error ( _ ( 'Could not strip EXIF metadata!' ), null , $error );
} else {
clearstatcache ( true , $file [ 'tmp_name' ]);
if (( $newfilesize = filesize ( $file [ 'tmp_name' ])) !== false ) {
$file [ 'size' ] = $newfilesize ;
}
}
2021-07-06 11:37:54 +00:00
} else {
2024-01-16 18:01:13 +00:00
$image -> to ( $file [ 'file' ]);
$dont_copy_file = true ;
2021-07-06 11:37:54 +00:00
}
2020-12-30 01:14:42 +00:00
}
2024-01-16 18:01:13 +00:00
$image -> destroy ();
} else {
if (
( $file [ 'extension' ] == " pdf " && $config [ 'pdf_file_thumbnail' ]) ||
( $file [ 'extension' ] == " djvu " && $config [ 'djvu_file_thumbnail' ])
) {
$path = $file [ 'thumb' ];
$error = shell_exec_error ( 'convert -size ' . $config [ 'thumb_width' ] . 'x' . $config [ 'thumb_height' ] . ' -thumbnail ' . $config [ 'thumb_width' ] . 'x' . $config [ 'thumb_height' ] . ' -background white -alpha remove ' .
escapeshellarg ( $file [ 'tmp_name' ] . '[0]' ) . ' ' .
escapeshellarg ( $file [ 'thumb' ]));
if ( $error ) {
$path = sprintf ( $config [ 'file_thumb' ], isset ( $config [ 'file_icons' ][ $file [ 'extension' ]]) ? $config [ 'file_icons' ][ $file [ 'extension' ]] : $config [ 'file_icons' ][ 'default' ]);
}
2020-12-30 01:14:42 +00:00
2024-01-16 18:01:13 +00:00
$file [ 'thumb' ] = basename ( $file [ 'thumb' ]);
$size = @ getimagesize ( $path );
$file [ 'thumbwidth' ] = $size [ 0 ];
$file [ 'thumbheight' ] = $size [ 1 ];
$file [ 'width' ] = $size [ 0 ];
$file [ 'height' ] = $size [ 1 ];
2020-12-30 01:14:42 +00:00
}
2024-03-15 09:08:34 +00:00
/* if (( $file [ 'extension' ] == " epub " && $config [ 'epub_file_thumbnail' ])){
2020-12-30 01:14:42 +00:00
$path = $file [ 'thumb' ];
// Open epub
// Get file list
// Check if cover file exists according to regex if it does use it
2024-03-15 09:08:34 +00:00
// Otherwise check if metadata file exists, and if does get rootfile and search for manifest for cover file name
2020-12-30 01:14:42 +00:00
// Otherwise Check if other image files exist and use them, based on criteria to pick the best one.
2024-03-15 09:08:34 +00:00
// Once we have filename extract said file from epub to file['thumb'] location.
2020-12-30 01:14:42 +00:00
$zip = new ZipArchive ();
if ( @ $zip -> open ( $path )){
$filename = " " ;
// Go looking for a file name, current implementation just uses regex but should fallback to
// getting all images and then choosing one.
2024-03-15 09:08:34 +00:00
for ( $i = 0 ; $i < $zip -> numFiles ; $i ++ ){
$stat = $zip -> statIndex ( $i );
2020-12-30 01:14:42 +00:00
$matches = array ();
if ( preg_match ( '/.*cover.*\.(jpg|jpeg|png)/' , $stat [ 'name' ], $matches )) {
$filename = $matches [ 0 ];
2024-03-15 09:08:34 +00:00
break ;
2020-12-30 01:14:42 +00:00
}
2024-03-15 09:08:34 +00:00
}
// We have a cover filename to extract.
2020-12-30 01:14:42 +00:00
if ( strlen ( $filename ) > 0 ){
//$zip->extractTo(dirname($file['thumb']), array($filename));
}
else {
$error = 1 ;
}
}
else {
$error = 1 ;
}
2024-03-15 09:08:34 +00:00
2020-12-30 01:14:42 +00:00
if ( $error ){
2024-03-15 09:08:34 +00:00
$path = sprintf ( $config [ 'file_thumb' ], isset ( $config [ 'file_icons' ][ $file [ 'extension' ]]) ? $config [ 'file_icons' ][ $file [ 'extension' ]] : $config [ 'file_icons' ][ 'default' ]);
2020-12-30 01:14:42 +00:00
}
$file [ 'thumb' ] = basename ( $file [ 'thumb' ]);
$size = @ getimagesize ( $path );
$file [ 'thumbwidth' ] = $size [ 0 ];
$file [ 'thumbheight' ] = $size [ 1 ];
$file [ 'width' ] = $size [ 0 ];
$file [ 'height' ] = $size [ 1 ];
2024-01-16 18:01:13 +00:00
} */ else if ( $file [ 'extension' ] == " txt " && $config [ 'txt_file_thumbnail' ]) {
$path = $file [ 'thumb' ];
$error = shell_exec_error ( 'convert -thumbnail x300 xc:white -pointsize 12 -fill black -annotate +15+15 ' .
escapeshellarg ( '@' . $file [ 'tmp_name' ]) . ' ' .
escapeshellarg ( $file [ 'thumb' ]));
if ( $error ) {
$path = sprintf ( $config [ 'file_thumb' ], isset ( $config [ 'file_icons' ][ $file [ 'extension' ]]) ? $config [ 'file_icons' ][ $file [ 'extension' ]] : $config [ 'file_icons' ][ 'default' ]);
}
2020-12-30 01:14:42 +00:00
2024-01-16 18:01:13 +00:00
$file [ 'thumb' ] = basename ( $file [ 'thumb' ]);
$size = @ getimagesize ( $path );
$file [ 'thumbwidth' ] = $size [ 0 ];
$file [ 'thumbheight' ] = $size [ 1 ];
$file [ 'width' ] = $size [ 0 ];
$file [ 'height' ] = $size [ 1 ];
} else if ( $file [ 'extension' ] == " svg " ) {
// Copy, because there's nothing to resize
$file [ 'thumb' ] = substr_replace ( $file [ 'thumb' ], $file [ 'extension' ], strrpos ( $file [ 'thumb' ], '.' ) + 1 );
copy ( $file [ 'tmp_name' ], $file [ 'thumb' ]);
$file [ 'thumbwidth' ] = $config [ 'thumb_width' ];
$file [ 'thumbheight' ] = $config [ 'thumb_height' ];
$file [ 'thumb' ] = basename ( $file [ 'thumb' ]);
} else {
// not an image
//copy($config['file_thumb'], $post['thumb']);
$file [ 'thumb' ] = 'file' ;
$size = @ getimagesize (
sprintf (
$config [ 'file_thumb' ],
isset ( $config [ 'file_icons' ][ $file [ 'extension' ]]) ?
$config [ 'file_icons' ][ $file [ 'extension' ]] : $config [ 'file_icons' ][ 'default' ]
)
);
$file [ 'thumbwidth' ] = $size [ 0 ];
$file [ 'thumbheight' ] = $size [ 1 ];
2020-12-30 01:14:42 +00:00
}
}
2024-01-16 18:01:13 +00:00
if ( $config [ 'tesseract_ocr' ] && $file [ 'thumb' ] != 'file' ) {
// Let's OCR it!
$fname = $file [ 'tmp_name' ];
2020-12-30 01:14:42 +00:00
2024-01-16 18:01:13 +00:00
if ( $file [ 'height' ] > 500 || $file [ 'width' ] > 500 ) {
$fname = $file [ 'thumb' ];
}
2020-12-30 01:14:42 +00:00
2024-01-16 18:01:13 +00:00
if ( $fname == 'spoiler' ) {
// We don't have that much CPU time, do we?
} else {
$tmpname = __DIR__ . " /tmp/tesseract/ " . rand ( 0 , 10000000 );
2020-12-30 01:14:42 +00:00
2024-01-16 18:01:13 +00:00
// Preprocess command is an ImageMagick b/w quantization
$error = shell_exec_error ( sprintf ( $config [ 'tesseract_preprocess_command' ], escapeshellarg ( $fname )) . " | " .
'tesseract stdin ' . escapeshellarg ( $tmpname ) . ' ' . $config [ 'tesseract_params' ]);
$tmpname .= " .txt " ;
2020-12-30 01:14:42 +00:00
2024-01-16 18:01:13 +00:00
$value = @ file_get_contents ( $tmpname );
@ unlink ( $tmpname );
2020-12-30 01:14:42 +00:00
2024-01-16 18:01:13 +00:00
if ( $value && trim ( $value )) {
// This one has an effect, that the body is appended to a post body. So you can write a correct
// spamfilter.
$post [ 'body_nomarkup' ] .= " <tinyboard ocr image $key > " . htmlspecialchars ( $value ) . " </tinyboard> " ;
}
2020-12-30 01:14:42 +00:00
}
}
2024-01-16 18:01:13 +00:00
if ( ! isset ( $dont_copy_file ) || ! $dont_copy_file ) {
if ( isset ( $file [ 'file_tmp' ])) {
if ( !@ rename ( $file [ 'tmp_name' ], $file [ 'file' ])) {
error ( $config [ 'error' ][ 'nomove' ]);
}
chmod ( $file [ 'file' ], 0644 );
} elseif ( !@ move_uploaded_file ( $file [ 'tmp_name' ], $file [ 'file' ])) {
2020-12-30 01:14:42 +00:00
error ( $config [ 'error' ][ 'nomove' ]);
2024-01-16 18:01:13 +00:00
}
2020-12-30 01:14:42 +00:00
}
}
if ( $config [ 'image_reject_repost' ]) {
if ( $p = getPostByHash ( $post [ 'filehash' ])) {
undoImage ( $post );
2024-01-16 18:01:13 +00:00
error (
sprintf (
$config [ 'error' ][ 'fileexists' ],
( $post [ 'mod' ] ? $config [ 'root' ] . $config [ 'file_mod' ] . '?/' : $config [ 'root' ]) .
( $board [ 'dir' ] . $config [ 'dir' ][ 'res' ] .
( $p [ 'thread' ] ?
$p [ 'thread' ] . '.html#' . $p [ 'id' ]
:
$p [ 'id' ] . '.html'
))
)
);
2020-12-30 01:14:42 +00:00
}
} else if ( ! $post [ 'op' ] && $config [ 'image_reject_repost_in_thread' ]) {
if ( $p = getPostByHashInThread ( $post [ 'filehash' ], $post [ 'thread' ])) {
undoImage ( $post );
2024-01-16 18:01:13 +00:00
error (
sprintf (
$config [ 'error' ][ 'fileexistsinthread' ],
( $post [ 'mod' ] ? $config [ 'root' ] . $config [ 'file_mod' ] . '?/' : $config [ 'root' ]) .
( $board [ 'dir' ] . $config [ 'dir' ][ 'res' ] .
( $p [ 'thread' ] ?
$p [ 'thread' ] . '.html#' . $p [ 'id' ]
:
$p [ 'id' ] . '.html'
))
)
);
2020-12-30 01:14:42 +00:00
}
}
}
// Do filters again if OCRing
if ( $config [ 'tesseract_ocr' ] && ! hasPermission ( $config [ 'mod' ][ 'bypass_filters' ], $board [ 'uri' ]) && ! $dropped_post ) {
do_filters ( $post );
}
if ( ! hasPermission ( $config [ 'mod' ][ 'postunoriginal' ], $board [ 'uri' ]) && $config [ 'robot_enable' ] && checkRobot ( $post [ 'body_nomarkup' ]) && ! $dropped_post ) {
undoImage ( $post );
if ( $config [ 'robot_mute' ]) {
error ( sprintf ( $config [ 'error' ][ 'muted' ], mute ()));
} else {
error ( $config [ 'error' ][ 'unoriginal' ]);
}
}
2024-01-16 18:01:13 +00:00
2020-12-30 01:14:42 +00:00
// Remove board directories before inserting them into the database.
if ( $post [ 'has_file' ]) {
foreach ( $post [ 'files' ] as $key => & $file ) {
$file [ 'file_path' ] = $file [ 'file' ];
$file [ 'thumb_path' ] = $file [ 'thumb' ];
$file [ 'file' ] = mb_substr ( $file [ 'file' ], mb_strlen ( $board [ 'dir' ] . $config [ 'dir' ][ 'img' ]));
2024-01-16 18:01:13 +00:00
if ( $file [ 'is_an_image' ] && $file [ 'thumb' ] != 'spoiler' ) {
2020-12-30 01:14:42 +00:00
$file [ 'thumb' ] = mb_substr ( $file [ 'thumb' ], mb_strlen ( $board [ 'dir' ] . $config [ 'dir' ][ 'thumb' ]));
2024-01-16 18:01:13 +00:00
}
2020-12-30 01:14:42 +00:00
}
}
2021-06-25 02:40:54 +00:00
// Custom /leftypol/ var to check if Tor
$tor = ( $_SERVER [ 'REMOTE_ADDR' ] == '127.0.0.1' );
2024-01-16 18:01:13 +00:00
$post = ( object ) $post ;
$post -> files = array_map ( function ( $a ) {
return ( object ) $a ;
}, $post -> files );
2020-12-30 01:14:42 +00:00
2021-06-25 02:40:54 +00:00
$error = event ( 'post' , $post , $tor );
2024-01-16 18:01:13 +00:00
$post -> files = array_map ( function ( $a ) {
return ( array ) $a ;
}, $post -> files );
2020-12-30 01:14:42 +00:00
if ( $error ) {
2024-01-16 18:01:13 +00:00
undoImage (( array ) $post );
2020-12-30 01:14:42 +00:00
error ( $error );
}
2024-01-16 18:01:13 +00:00
$post = ( array ) $post ;
2020-12-30 01:14:42 +00:00
if ( $post [ 'files' ]) {
$post [ 'files' ] = $post [ 'files' ];
}
$post [ 'num_files' ] = sizeof ( $post [ 'files' ]);
2024-01-16 18:01:13 +00:00
2020-12-30 01:14:42 +00:00
$post [ 'id' ] = $id = post ( $post );
$post [ 'slug' ] = slugify ( $post );
2024-01-16 18:01:13 +00:00
2020-12-30 01:14:42 +00:00
if ( $dropped_post && $dropped_post [ 'from_nntp' ]) {
2024-01-16 18:01:13 +00:00
$query = prepare ( " INSERT INTO ``nntp_references`` (`board`, `id`, `message_id`, `message_id_digest`, `own`, `headers`) VALUES " .
" (:board , :id , :message_id , :message_id_digest , false, :headers) " );
2020-12-30 01:14:42 +00:00
$query -> bindValue ( ':board' , $dropped_post [ 'board' ]);
$query -> bindValue ( ':id' , $id );
$query -> bindValue ( ':message_id' , $dropped_post [ 'msgid' ]);
$query -> bindValue ( ':message_id_digest' , sha1 ( $dropped_post [ 'msgid' ]));
$query -> bindValue ( ':headers' , $dropped_post [ 'headers' ]);
$query -> execute () or error ( db_error ( $query ));
} // ^^^^^ For inbound posts ^^^^^
elseif ( $config [ 'nntpchan' ][ 'enabled' ] && $config [ 'nntpchan' ][ 'group' ]) {
// vvvvv For outbound posts vvvvv
require_once ( 'inc/nntpchan/nntpchan.php' );
$msgid = gen_msgid ( $post [ 'board' ], $post [ 'id' ]);
list ( $headers , $files ) = post2nntp ( $post , $msgid );
$message = gen_nntp ( $headers , $files );
2024-01-16 18:01:13 +00:00
$query = prepare ( " INSERT INTO ``nntp_references`` (`board`, `id`, `message_id`, `message_id_digest`, `own`, `headers`) VALUES " .
" (:board , :id , :message_id , :message_id_digest , true , :headers) " );
2020-12-30 01:14:42 +00:00
$query -> bindValue ( ':board' , $post [ 'board' ]);
2024-01-16 18:01:13 +00:00
$query -> bindValue ( ':id' , $post [ 'id' ]);
$query -> bindValue ( ':message_id' , $msgid );
$query -> bindValue ( ':message_id_digest' , sha1 ( $msgid ));
$query -> bindValue ( ':headers' , json_encode ( $headers ));
$query -> execute () or error ( db_error ( $query ));
2016-08-14 22:56:06 +00:00
2020-12-30 01:14:42 +00:00
// Let's broadcast it!
nntp_publish ( $message , $msgid );
}
insertFloodPost ( $post );
// Handle cyclical threads
if ( ! $post [ 'op' ] && isset ( $thread [ 'cycle' ]) && $thread [ 'cycle' ]) {
// Query is a bit weird due to "This version of MariaDB doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'" (MariaDB Ver 15.1 Distrib 10.0.17-MariaDB, for Linux (x86_64))
$query = prepare ( sprintf ( 'DELETE FROM ``posts_%s`` WHERE `thread` = :thread AND `id` NOT IN (SELECT `id` FROM (SELECT `id` FROM ``posts_%s`` WHERE `thread` = :thread ORDER BY `id` DESC LIMIT :limit) i)' , $board [ 'uri' ], $board [ 'uri' ]));
$query -> bindValue ( ':thread' , $post [ 'thread' ]);
$query -> bindValue ( ':limit' , $config [ 'cycle_limit' ], PDO :: PARAM_INT );
$query -> execute () or error ( db_error ( $query ));
}
2024-01-16 18:01:13 +00:00
2020-12-30 01:14:42 +00:00
if ( isset ( $post [ 'antispam_hash' ])) {
incrementSpamHash ( $post [ 'antispam_hash' ]);
}
2024-01-16 18:01:13 +00:00
2020-12-30 01:14:42 +00:00
if ( isset ( $post [ 'tracked_cites' ]) && ! empty ( $post [ 'tracked_cites' ])) {
$insert_rows = array ();
foreach ( $post [ 'tracked_cites' ] as $cite ) {
$insert_rows [] = '(' .
2024-01-16 18:01:13 +00:00
$pdo -> quote ( $board [ 'uri' ]) . ', ' . ( int ) $id . ', ' .
$pdo -> quote ( $cite [ 0 ]) . ', ' . ( int ) $cite [ 1 ] . ')' ;
2020-12-30 01:14:42 +00:00
}
query ( 'INSERT INTO ``cites`` VALUES ' . implode ( ', ' , $insert_rows )) or error ( db_error ());
}
2021-01-18 03:31:06 +00:00
if ( ! $post [ 'op' ] && strtolower ( $post [ 'email' ]) != 'sage' && ! $thread [ 'sage' ] && ( $config [ 'reply_limit' ] == 0 || $numposts [ 'replies' ] < $config [ 'reply_limit' ])) {
2020-12-30 01:14:42 +00:00
bumpThread ( $post [ 'thread' ]);
}
if ( isset ( $_SERVER [ 'HTTP_REFERER' ])) {
// Tell Javascript that we posted successfully
2024-01-16 18:01:13 +00:00
if ( isset ( $_COOKIE [ $config [ 'cookies' ][ 'js' ]])) {
2020-12-30 01:14:42 +00:00
$js = json_decode ( $_COOKIE [ $config [ 'cookies' ][ 'js' ]]);
2024-01-16 18:01:13 +00:00
} else {
2020-12-30 01:14:42 +00:00
$js = ( object ) array ();
2024-01-16 18:01:13 +00:00
}
2020-12-30 01:14:42 +00:00
// Tell it to delete the cached post for referer
$js -> { $_SERVER [ 'HTTP_REFERER' ]} = true ;
// Encode and set cookie
setcookie ( $config [ 'cookies' ][ 'js' ], json_encode ( $js ), 0 , $config [ 'cookies' ][ 'jail' ] ? $config [ 'cookies' ][ 'path' ] : '/' , null , false , false );
}
2024-01-16 18:01:13 +00:00
2020-12-30 01:14:42 +00:00
$root = $post [ 'mod' ] ? $config [ 'root' ] . $config [ 'file_mod' ] . '?/' : $config [ 'root' ];
2024-01-16 18:01:13 +00:00
2020-12-30 01:14:42 +00:00
if ( $noko ) {
$redirect = $root . $board [ 'dir' ] . $config [ 'dir' ][ 'res' ] .
link_for ( $post , false , false , $thread ) . ( ! $post [ 'op' ] ? '#' . $id : '' );
2024-01-16 18:01:13 +00:00
2020-12-30 01:14:42 +00:00
if ( ! $post [ 'op' ] && isset ( $_SERVER [ 'HTTP_REFERER' ])) {
$regex = array (
'board' => str_replace ( '%s' , '(\w{1,8})' , preg_quote ( $config [ 'board_path' ], '/' )),
'page' => str_replace ( '%d' , '(\d+)' , preg_quote ( $config [ 'file_page' ], '/' )),
'page50' => '(' . str_replace ( '%d' , '(\d+)' , preg_quote ( $config [ 'file_page50' ], '/' )) . '|' .
2024-01-16 18:01:13 +00:00
str_replace ( array ( '%d' , '%s' ), array ( '(\d+)' , '[a-z0-9-]+' ), preg_quote ( $config [ 'file_page50_slug' ], '/' )) . ')' ,
2020-12-30 01:14:42 +00:00
'res' => preg_quote ( $config [ 'dir' ][ 'res' ], '/' ),
);
if ( preg_match ( '/\/' . $regex [ 'board' ] . $regex [ 'res' ] . $regex [ 'page50' ] . '([?&].*)?$/' , $_SERVER [ 'HTTP_REFERER' ])) {
$redirect = $root . $board [ 'dir' ] . $config [ 'dir' ][ 'res' ] .
link_for ( $post , true , false , $thread ) . ( ! $post [ 'op' ] ? '#' . $id : '' );
}
}
} else {
$redirect = $root . $board [ 'dir' ] . $config [ 'file_index' ];
}
buildThread ( $post [ 'op' ] ? $id : $post [ 'thread' ]);
2024-01-16 18:01:13 +00:00
if ( $config [ 'syslog' ]) {
2020-12-30 01:14:42 +00:00
_syslog ( LOG_INFO , 'New post: /' . $board [ 'dir' ] . $config [ 'dir' ][ 'res' ] .
link_for ( $post ) . ( ! $post [ 'op' ] ? '#' . $id : '' ));
2024-01-16 18:01:13 +00:00
}
if ( ! $post [ 'mod' ]) {
header ( 'X-Associated-Content: "' . $redirect . '"' );
}
2020-12-30 01:14:42 +00:00
if ( ! isset ( $_POST [ 'json_response' ])) {
header ( 'Location: ' . $redirect , true , $config [ 'redirect_http' ]);
} else {
header ( 'Content-Type: text/json; charset=utf-8' );
2024-01-16 18:01:13 +00:00
echo json_encode (
array (
'redirect' => $redirect ,
'noko' => $noko ,
'id' => $id
)
);
2020-12-30 01:14:42 +00:00
}
2024-01-16 18:01:13 +00:00
2022-01-17 08:12:13 +00:00
if ( $post [ 'op' ]) {
2020-12-30 01:14:42 +00:00
clean ( $id );
2024-01-16 18:01:13 +00:00
2022-01-17 08:12:13 +00:00
if ( $config [ 'try_smarter' ])
$build_pages = range ( 1 , $config [ 'max_pages' ]);
2022-01-17 12:14:04 +00:00
}
2024-01-16 18:01:13 +00:00
2022-01-17 12:14:04 +00:00
event ( 'post-after' , $post );
2024-01-16 18:01:13 +00:00
2022-01-17 12:14:04 +00:00
// If this is a new thread or the poster is returning to the index, let's build it before they redirect
2024-01-16 18:01:13 +00:00
if ( $post [ 'op' ] || ! $noko ) {
2022-01-17 12:14:04 +00:00
buildIndex ();
2024-01-16 18:01:13 +00:00
}
2022-01-17 12:14:04 +00:00
// We are already done, let's continue our heavy-lifting work in the background (if we run off FastCGI)
if ( function_exists ( 'fastcgi_finish_request' )) {
@ fastcgi_finish_request ();
}
2024-01-16 18:01:13 +00:00
if ( ! $post [ 'op' ] && $noko ) {
2022-01-17 08:12:13 +00:00
buildIndex ();
2024-01-16 18:01:13 +00:00
}
2020-12-30 01:14:42 +00:00
2022-01-17 12:14:04 +00:00
if ( $post [ 'op' ]) {
2020-12-30 01:14:42 +00:00
rebuildThemes ( 'post-thread' , $board [ 'uri' ]);
} else {
rebuildThemes ( 'post' , $board [ 'uri' ]);
}
2019-02-26 00:48:01 +00:00
}
2024-01-16 18:01:13 +00:00
function handle_appeal ()
{
2020-12-30 01:14:42 +00:00
global $config ;
2024-01-16 18:01:13 +00:00
if ( ! isset ( $_POST [ 'ban_id' ])) {
2020-12-30 01:14:42 +00:00
error ( $config [ 'error' ][ 'bot' ]);
2024-01-16 18:01:13 +00:00
}
2024-01-16 18:01:13 +00:00
2024-01-16 18:01:14 +00:00
// Doubles as sanitization against SQL injection.
2024-01-16 18:01:13 +00:00
$ban_id = ( int ) $_POST [ 'ban_id' ];
2020-12-30 01:14:42 +00:00
$bans = Bans :: find ( $_SERVER [ 'REMOTE_ADDR' ]);
foreach ( $bans as $_ban ) {
if ( $_ban [ 'id' ] == $ban_id ) {
$ban = $_ban ;
break ;
}
}
2024-01-16 18:01:13 +00:00
2020-12-30 01:14:42 +00:00
if ( ! isset ( $ban )) {
2021-07-24 12:47:56 +00:00
error ( $config [ 'error' ][ 'noban' ]);
2020-12-30 01:14:42 +00:00
}
2024-01-16 18:01:13 +00:00
2020-12-30 01:14:42 +00:00
if ( $ban [ 'expires' ] && $ban [ 'expires' ] - $ban [ 'created' ] <= $config [ 'ban_appeals_min_length' ]) {
2021-07-24 12:47:56 +00:00
error ( $config [ 'error' ][ 'tooshortban' ]);
2020-12-30 01:14:42 +00:00
}
2024-01-16 18:01:13 +00:00
2024-01-16 18:01:14 +00:00
$ban_appeals = db_select_ban_appeals ( $ban_id );
2024-01-16 18:01:13 +00:00
2020-12-30 01:14:42 +00:00
if ( count ( $ban_appeals ) >= $config [ 'ban_appeals_max' ]) {
2021-07-24 12:47:56 +00:00
error ( $config [ 'error' ][ 'toomanyappeals' ]);
2020-12-30 01:14:42 +00:00
}
2024-01-16 18:01:13 +00:00
2020-12-30 01:14:42 +00:00
foreach ( $ban_appeals as $is_denied ) {
2024-01-16 18:01:13 +00:00
if ( ! $is_denied ) {
2021-07-24 12:47:56 +00:00
error ( $config [ 'error' ][ 'pendingappeal' ]);
2024-01-16 18:01:13 +00:00
}
2021-07-24 12:47:56 +00:00
}
2024-01-16 18:01:13 +00:00
2021-07-24 12:47:56 +00:00
if ( strlen ( $_POST [ 'appeal' ]) > $config [ 'ban_appeal_max_chars' ]) {
error ( $config [ 'error' ][ 'toolongappeal' ]);
2020-12-30 01:14:42 +00:00
}
2024-01-16 18:01:13 +00:00
2024-01-16 18:01:13 +00:00
// Sanitize away eventual Cross Site Scripting funkyness.
$appeal_msg = htmlspecialchars ( $_POST [ 'appeal' ]);
2024-01-16 18:01:14 +00:00
db_insert_ban_appeal ( $ban_id , $appeal_msg );
2019-02-26 00:48:01 +00:00
2024-01-16 18:01:13 +00:00
displayBan ( $ban );
2019-02-26 00:48:01 +00:00
}
// Is it a post coming from NNTP? Let's extract it and pretend it's a normal post.
if ( isset ( $_GET [ 'Newsgroups' ])) {
2024-01-16 18:01:13 +00:00
if ( $config [ 'nntpchan' ][ 'enabled' ]) {
2020-12-30 01:14:42 +00:00
handle_nntpchan ();
2024-01-16 18:01:13 +00:00
} else {
2020-12-30 01:14:42 +00:00
error ( " NNTPChan: NNTPChan support is disabled " );
2024-01-16 18:01:13 +00:00
}
2019-02-26 00:48:01 +00:00
}
if ( isset ( $_POST [ 'delete' ])) {
2020-12-30 01:14:42 +00:00
handle_delete ();
2019-02-26 00:48:01 +00:00
} elseif ( isset ( $_POST [ 'report' ])) {
2020-12-30 01:14:42 +00:00
handle_report ();
2019-02-26 00:48:01 +00:00
} elseif ( isset ( $_POST [ 'post' ]) || $dropped_post ) {
2020-12-30 01:14:42 +00:00
handle_post ();
2019-02-26 00:48:01 +00:00
} elseif ( isset ( $_POST [ 'appeal' ])) {
2020-12-30 01:14:42 +00:00
handle_appeal ();
2012-04-11 16:49:22 +00:00
} else {
2020-12-30 01:14:42 +00:00
if ( ! file_exists ( $config [ 'has_installed' ])) {
header ( 'Location: install.php' , true , $config [ 'redirect_http' ]);
} else {
// They opened post.php in their browser manually.
error ( $config [ 'error' ][ 'nopost' ]);
}
2012-04-11 16:49:22 +00:00
}