diff --git a/inc/display.php b/inc/display.php index 6772e77d..c836247e 100644 --- a/inc/display.php +++ b/inc/display.php @@ -373,61 +373,11 @@ class Post { return $this->root . $board['dir'] . $config['dir']['res'] . sprintf($config['file_page'], $this->thread) . '#' . $pre . $this->id; } - 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 .= ' ' . secure_link_confirm($config['mod']['link_delete'], 'Delete', 'Are you sure you want to delete this?', $board['dir'] . 'delete/' . $this->id); - - // Delete all posts by IP - if (hasPermission($config['mod']['deletebyip'], $board['uri'], $this->mod)) - $built .= ' ' . secure_link_confirm($config['mod']['link_deletebyip'], 'Delete all posts by IP', 'Are you sure you want to delete all posts by this IP address?', $board['dir'] . 'deletebyip/' . $this->id); - - // Delete all posts by IP (global) - if (hasPermission($config['mod']['deletebyip_global'], $board['uri'], $this->mod)) - $built .= ' ' . secure_link_confirm($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['dir'] . 'deletebyip/' . $this->id . '/global'); - - // Ban - if (hasPermission($config['mod']['ban'], $board['uri'], $this->mod)) - $built .= ' ' . $config['mod']['link_ban'] . ''; - - // Ban & Delete - if (hasPermission($config['mod']['bandelete'], $board['uri'], $this->mod)) - $built .= ' ' . $config['mod']['link_bandelete'] . ''; - - // Delete file (keep post) - if (!empty($this->files) && hasPermission($config['mod']['deletefile'], $board['uri'], $this->mod)) - $built .= ' ' . secure_link_confirm($config['mod']['link_deletefile'], _('Delete file'), _('Are you sure you want to delete this file?'), $board['dir'] . 'deletefile/' . $this->id); - - // Spoiler file (keep post) - if (!empty($this->file) && $this->file != "deleted" && $this->file != null && $this->thumb != 'spoiler' && hasPermission($config['mod']['spoilerimage'], $board['uri'], $this->mod) && $config['spoiler_images']) - $built .= ' ' . secure_link_confirm($config['mod']['link_spoilerimage'], _('Spoiler File'), _('Are you sure you want to spoiler this file?'), $board['uri'] . '/spoiler/' . $this->id); - - // Move post - if (hasPermission($config['mod']['move'], $board['uri'], $this->mod) && $config['move_replies']) - $built .= ' ' . $config['mod']['link_move'] . ''; - - // Edit post - if (hasPermission($config['mod']['editpost'], $board['uri'], $this->mod)) - $built .= ' ' . $config['mod']['link_editpost'] . ''; - - - if (!empty($built)) - $built = '' . $built . ''; - } - return $built; - } - public function build($index=false) { global $board, $config; - return Element('post_reply.html', array('config' => $config, 'board' => $board, 'post' => &$this, 'index' => $index)); + return Element('post_reply.html', array('config' => $config, 'board' => $board, 'post' => &$this, 'index' => $index, 'mod' => $this->mod)); } }; @@ -484,73 +434,6 @@ class Thread { public function postCount() { return count($this->posts) + $this->omitted; } - 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 .= ' ' . secure_link_confirm($config['mod']['link_delete'], _('Delete'), _('Are you sure you want to delete this?'), $board['dir'] . 'delete/' . $this->id); - - // Delete all posts by IP - if (hasPermission($config['mod']['deletebyip'], $board['uri'], $this->mod)) - $built .= ' ' . secure_link_confirm($config['mod']['link_deletebyip'], _('Delete all posts by IP'), _('Are you sure you want to delete all posts by this IP address?'), $board['dir'] . 'deletebyip/' . $this->id); - - // Delete all posts by IP (global) - if (hasPermission($config['mod']['deletebyip_global'], $board['uri'], $this->mod)) - $built .= ' ' . secure_link_confirm($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['dir'] . 'deletebyip/' . $this->id . '/global'); - - // Ban - if (hasPermission($config['mod']['ban'], $board['uri'], $this->mod)) - $built .= ' ' . $config['mod']['link_ban'] . ''; - - // Ban & Delete - if (hasPermission($config['mod']['bandelete'], $board['uri'], $this->mod)) - $built .= ' ' . $config['mod']['link_bandelete'] . ''; - - // Delete file (keep post) - if (!empty($this->files) && $this->files[0]->file != 'deleted' && hasPermission($config['mod']['deletefile'], $board['uri'], $this->mod)) - $built .= ' ' . secure_link_confirm($config['mod']['link_deletefile'], _('Delete file'), _('Are you sure you want to delete this file?'), $board['dir'] . 'deletefile/' . $this->id); - - // Spoiler file (keep post) - if (!empty($this->file) && $this->file != "deleted" && $this->file != null && $this->thumb != 'spoiler' && hasPermission($config['mod']['spoilerimage'], $board['uri'], $this->mod) && $config['spoiler_images']) - $built .= ' ' . secure_link_confirm($config['mod']['link_spoilerimage'], _('Spoiler File'), _('Are you sure you want to spoiler this file?'), $board['uri'] . '/spoiler/' . $this->id); - - // Sticky - if (hasPermission($config['mod']['sticky'], $board['uri'], $this->mod)) - if ($this->sticky) - $built .= ' ' . $config['mod']['link_desticky'] . ''; - else - $built .= ' ' . $config['mod']['link_sticky'] . ''; - - if (hasPermission($config['mod']['bumplock'], $board['uri'], $this->mod)) - if ($this->sage) - $built .= ' ' . $config['mod']['link_bumpunlock'] . ''; - else - $built .= ' ' . $config['mod']['link_bumplock'] . ''; - - // Lock - if (hasPermission($config['mod']['lock'], $board['uri'], $this->mod)) - if ($this->locked) - $built .= ' ' . $config['mod']['link_unlock'] . ''; - else - $built .= ' ' . $config['mod']['link_lock'] . ''; - - if (hasPermission($config['mod']['move'], $board['uri'], $this->mod)) - $built .= ' ' . $config['mod']['link_move'] . ''; - - // Edit post - if (hasPermission($config['mod']['editpost'], $board['uri'], $this->mod)) - $built .= ' ' . $config['mod']['link_editpost'] . ''; - - if (!empty($built)) - $built = '' . $built . ''; - } - return $built; - } - public function build($index=false, $isnoko50=false) { global $board, $config, $debug; @@ -558,7 +441,7 @@ class Thread { event('show-thread', $this); - $built = Element('post_thread.html', array('config' => $config, 'board' => $board, 'post' => &$this, 'index' => $index, 'hasnoko50' => $hasnoko50, 'isnoko50' => $isnoko50)); + $built = Element('post_thread.html', array('config' => $config, 'board' => $board, 'post' => &$this, 'index' => $index, 'hasnoko50' => $hasnoko50, 'isnoko50' => $isnoko50, 'mod' => $this->mod)); return $built; } diff --git a/inc/functions.php b/inc/functions.php index 1db2b7f3..041e3733 100644 --- a/inc/functions.php +++ b/inc/functions.php @@ -952,36 +952,40 @@ function bumpThread($id) { } // Remove file from post -function deleteFile($id, $remove_entirely_if_already=true) { +function deleteFile($id, $remove_entirely_if_already=true, $file=null) { global $board, $config; - $query = prepare(sprintf("SELECT `thread`, `files` FROM ``posts_%s`` WHERE `id` = :id LIMIT 1", $board['uri'])); + $query = prepare(sprintf("SELECT `thread`, `files`, `num_files` FROM ``posts_%s`` WHERE `id` = :id LIMIT 1", $board['uri'])); $query->bindValue(':id', $id, PDO::PARAM_INT); $query->execute() or error(db_error($query)); if (!$post = $query->fetch(PDO::FETCH_ASSOC)) error($config['error']['invalidpost']); - $files = json_decode($post['files']); + $files = json_decode($post['files']); + $file_to_delete = $file !== false ? $files[(int)$file] : (object)array('file' => false); - if ($files[0]->file == 'deleted' && !$post['thread']) + if ($files[0]->file == 'deleted' && $post['num_files'] == 1 && !$post['thread']) return; // Can't delete OP's image completely. $query = prepare(sprintf("UPDATE ``posts_%s`` SET `files` = :file WHERE `id` = :id", $board['uri'])); - if ($files[0]->file == 'deleted' && $remove_entirely_if_already) { + if (($file && $file_to_delete->file == 'deleted') && $remove_entirely_if_already) { // Already deleted; remove file fully - $query->bindValue(':file', null, PDO::PARAM_NULL); + $files[$file] = null; } else { - foreach ($files as $i => $file) { - // Delete thumbnail - file_unlink($board['dir'] . $config['dir']['thumb'] . $file->thumb); + foreach ($files as $i => $f) { + if (($file !== false && $i == $file) || $file === null) { + // Delete thumbnail + file_unlink($board['dir'] . $config['dir']['thumb'] . $f->thumb); + unset($files[$i]->thumb); - // Delete file - file_unlink($board['dir'] . $config['dir']['img'] . $file->file); - } - - // Set file to 'deleted' - $query->bindValue(':file', '[{"file":"deleted"}]', PDO::PARAM_STR); + // Delete file + file_unlink($board['dir'] . $config['dir']['img'] . $f->file); + $files[$i]->file = 'deleted'; + } + } } + $query->bindValue(':file', json_encode($files), PDO::PARAM_STR); + $query->bindValue(':id', $id, PDO::PARAM_INT); $query->execute() or error(db_error($query)); @@ -1052,8 +1056,10 @@ function deletePost($id, $error_if_doesnt_exist=true, $rebuild_after=true) { if ($post['files']) { // Delete file foreach (json_decode($post['files']) as $i => $f) { - file_unlink($board['dir'] . $config['dir']['img'] . $f->file); - file_unlink($board['dir'] . $config['dir']['thumb'] . $f->thumb); + if ($f->file !== 'deleted') { + file_unlink($board['dir'] . $config['dir']['img'] . $f->file); + file_unlink($board['dir'] . $config['dir']['thumb'] . $f->thumb); + } } } @@ -1195,7 +1201,7 @@ function index($page, $mod=false) { 'post_url' => $config['post_url'], 'config' => $config, 'boardlist' => createBoardlist($mod), - 'threads' => $threads + 'threads' => $threads, ); } diff --git a/inc/lib/Twig/Extensions/Extension/Tinyboard.php b/inc/lib/Twig/Extensions/Extension/Tinyboard.php index 4063bfd4..960bb844 100644 --- a/inc/lib/Twig/Extensions/Extension/Tinyboard.php +++ b/inc/lib/Twig/Extensions/Extension/Tinyboard.php @@ -42,7 +42,9 @@ class Twig_Extensions_Extension_Tinyboard extends Twig_Extension new Twig_SimpleFunction('timezone', 'twig_timezone_function'), new Twig_SimpleFunction('hiddenInputs', 'hiddenInputs'), new Twig_SimpleFunction('hiddenInputsHash', 'hiddenInputsHash'), - new Twig_SimpleFunction('ratio', 'twig_ratio_function') + new Twig_SimpleFunction('ratio', 'twig_ratio_function'), + new Twig_SimpleFunction('secure_link_confirm', 'twig_secure_link_confirm'), + new Twig_SimpleFunction('secure_link', 'twig_secure_link') ); } @@ -104,3 +106,11 @@ function twig_truncate_filter($value, $length = 30, $preserve = false, $separato function twig_ratio_function($w, $h) { return fraction($w, $h, ':'); } +function twig_secure_link_confirm($text, $title, $confirm_message, $href) { + global $config; + + return '' . $text . ''; +} +function twig_secure_link($href) { + return $href . '/' . make_secure_link_token($href); +} diff --git a/inc/mod/pages.php b/inc/mod/pages.php index 713a9358..0ddffd30 100644 --- a/inc/mod/pages.php +++ b/inc/mod/pages.php @@ -1519,7 +1519,7 @@ function mod_delete($board, $post) { header('Location: ?/' . sprintf($config['board_path'], $board) . $config['file_index'], true, $config['redirect_http']); } -function mod_deletefile($board, $post) { +function mod_deletefile($board, $post, $file) { global $config, $mod; if (!openBoard($board)) @@ -1529,7 +1529,7 @@ function mod_deletefile($board, $post) { error($config['error']['noaccess']); // Delete file - deleteFile($post); + deleteFile($post, TRUE, $file); // Record the action modLog("Deleted file from post #{$post}"); @@ -1542,7 +1542,7 @@ function mod_deletefile($board, $post) { header('Location: ?/' . sprintf($config['board_path'], $board) . $config['file_index'], true, $config['redirect_http']); } -function mod_spoiler_image($board, $post) { +function mod_spoiler_image($board, $post, $file) { global $config, $mod; if (!openBoard($board)) @@ -1551,19 +1551,21 @@ function mod_spoiler_image($board, $post) { if (!hasPermission($config['mod']['spoilerimage'], $board)) error($config['error']['noaccess']); - // Delete file - $query = prepare(sprintf("SELECT `thumb`, `thread` FROM ``posts_%s`` WHERE id = :id", $board)); + // Delete file thumbnail + $query = prepare(sprintf("SELECT `files`, `thread` FROM ``posts_%s`` WHERE id = :id", $board)); $query->bindValue(':id', $post, PDO::PARAM_INT); $query->execute() or error(db_error($query)); $result = $query->fetch(PDO::FETCH_ASSOC); + $files = json_decode($result['files']); - file_unlink($board . '/' . $config['dir']['thumb'] . $result['thumb']); - + file_unlink($board . '/' . $config['dir']['thumb'] . $files[$file]->thumb); + $files[$file]->thumb = 'spoiler'; + $files[$file]->thumbheight = 128; + $files[$file]->thumbwidth = 128; + // Make thumbnail spoiler - $query = prepare(sprintf("UPDATE ``posts_%s`` SET `thumb` = :thumb, `thumbwidth` = :thumbwidth, `thumbheight` = :thumbheight WHERE `id` = :id", $board)); - $query->bindValue(':thumb', "spoiler"); - $query->bindValue(':thumbwidth', 128, PDO::PARAM_INT); - $query->bindValue(':thumbheight', 128, PDO::PARAM_INT); + $query = prepare(sprintf("UPDATE ``posts_%s`` SET `files` = :files WHERE `id` = :id", $board)); + $query->bindValue(':files', json_encode($files)); $query->bindValue(':id', $post, PDO::PARAM_INT); $query->execute() or error(db_error($query)); diff --git a/mod.php b/mod.php index 51b85f1a..5428e84d 100644 --- a/mod.php +++ b/mod.php @@ -76,8 +76,8 @@ $pages = array( '/(\%b)/move_reply/(\d+)' => 'secure_POST move_reply', // move reply '/(\%b)/edit(_raw)?/(\d+)' => 'secure_POST edit_post', // edit post '/(\%b)/delete/(\d+)' => 'secure delete', // delete post - '/(\%b)/deletefile/(\d+)' => 'secure deletefile', // delete file from post - '/(\%b+)/spoiler/(\d+)' => 'secure spoiler_image', // spoiler file + '/(\%b)/deletefile/(\d+)/(\d+)' => 'secure deletefile', // delete file from post + '/(\%b+)/spoiler/(\d+)/(\d+)' => 'secure spoiler_image', // spoiler file '/(\%b)/deletebyip/(\d+)(/global)?' => 'secure deletebyip', // delete all posts by IP address '/(\%b)/(un)?lock/(\d+)' => 'secure lock', // lock thread '/(\%b)/(un)?sticky/(\d+)' => 'secure sticky', // sticky thread diff --git a/templates/post/file_controls.html b/templates/post/file_controls.html new file mode 100644 index 00000000..6855a293 --- /dev/null +++ b/templates/post/file_controls.html @@ -0,0 +1,10 @@ +{% if post.files and mod %} + +{% if file.file != 'deleted' and mod|hasPermission(config.mod.deletefile, board.uri) %} +{{ secure_link_confirm(config.mod.link_deletefile, 'Delete file'|trans, 'Are you sure you want to delete this file?'|trans, board.dir ~ 'deletefile/' ~ post.id ~ '/' ~ loop.index0 ) }} +{% endif %} +{% if file.file and file.file != 'deleted' and file.thumb != 'spoiler' and mod|hasPermission(config.mod.spoilerimage, board.uri) %} +{{ secure_link_confirm(config.mod.link_spoilerimage, 'Spoiler file'|trans, 'Are you sure you want to spoiler this file?'|trans, board.dir ~ 'spoiler/' ~ post.id ~ '/' ~ loop.index0 ) }} +{% endif %} + +{% endif %} diff --git a/templates/post/fileinfo.html b/templates/post/fileinfo.html index add7fd0c..dcbb249d 100644 --- a/templates/post/fileinfo.html +++ b/templates/post/fileinfo.html @@ -29,7 +29,7 @@ {% endif %} {% include "post/image_identification.html" %} ) -
+ {% include "post/file_controls.html" %} {% include "post/image.html" with {'post':file} %} {% endif %} diff --git a/templates/post/post_controls.html b/templates/post/post_controls.html new file mode 100644 index 00000000..78ee5842 --- /dev/null +++ b/templates/post/post_controls.html @@ -0,0 +1,57 @@ +{% if mod %} + + +{% if mod|hasPermission(config.mod.delete, board.uri) %} + {{ secure_link_confirm(config.mod.link_delete, 'Delete'|trans, 'Are you sure you want to delete this?'|trans, board.dir ~ 'delete/' ~ post.id) }} +{% endif %} +{% if mod|hasPermission(config.mod.deletebyip, board.uri) %} + {{ secure_link_confirm(config.mod.link_deletebyip, 'Delete all posts by IP'|trans, 'Are you sure you want to delete all posts by this IP address?'|trans, board.dir ~ 'deletebyip/' ~ post.id) }} +{% endif %} +{% if mod|hasPermission(config.mod.deletebyip_global, board.uri) %} + {{ secure_link_confirm(config.mod.link_deletebyip_global, 'Delete all posts by IP across all boards'|trans, 'Are you sure you want to delete all posts by this IP address, across all boards?'|trans, board.dir ~ 'deletebyip/' ~ post.id ~ '/global') }} +{% endif %} +{% if mod|hasPermission(config.mod.ban, board.uri) %} + {{ config.mod.link_ban }} +{% endif %} +{% if mod|hasPermission(config.mod.bandelete, board.uri) %} + {{ config.mod.link_bandelete }} +{% endif %} + +{% if not post.thread %} +{% if mod|hasPermission(config.mod.sticky, board.uri) %} + {% if post.sticky %} + {{ config.mod.link_desticky }} + {% else %} + {{ config.mod.link_sticky }} + {% endif %} +{% endif %} +{% if mod|hasPermission(config.mod.bumplock, board.uri) %} + {% if post.sage %} + {{ config.mod.link_bumpunlock }} + {% else %} + {{ config.mod.link_bumplock }} + {% endif %} +{% endif %} +{% if mod|hasPermission(config.mod.lock, board.uri) %} + {% if post.locked %} + {{ config.mod.link_unlock }} + {% else %} + {{ config.mod.link_lock }} + {% endif %} +{% endif %} + +{% endif %} + +{% if mod|hasPermission(config.mod.move, board.uri) %} + {% if not post.thread %} + {{ config.mod.link_move }} + {% else %} + {{ config.mod.link_move }} + {% endif %} +{% if mod|hasPermission(config.mod.editpost, board.uri) %} + {{ config.mod.link_editpost }} +{% endif %} +{% endif %} + + +{% endif %} diff --git a/templates/post_reply.html b/templates/post_reply.html index 3d860872..8ef3c1e8 100644 --- a/templates/post_reply.html +++ b/templates/post_reply.html @@ -17,8 +17,8 @@ {{ post.id }} - {% include 'post/fileinfo.html' %} - {{ post.postControls }} + {% include 'post/fileinfo.html' %} + {% include 'post/post_controls.html' %}