mirror of
https://github.com/vichan-devel/vichan.git
synced 2024-11-27 17:00:52 +01:00
multiimage posting
This commit is contained in:
parent
7a04150b04
commit
c483e1258c
49
inc/api.php
49
inc/api.php
@ -26,12 +26,6 @@ class Api {
|
||||
'trip' => 'trip',
|
||||
'capcode' => 'capcode',
|
||||
'time' => 'time',
|
||||
'thumbheight' => 'tn_w',
|
||||
'thumbwidth' => 'tn_h',
|
||||
'fileheight' => 'w',
|
||||
'filewidth' => 'h',
|
||||
'filesize' => 'fsize',
|
||||
'filename' => 'filename',
|
||||
'omitted' => 'omitted_posts',
|
||||
'omitted_images' => 'omitted_images',
|
||||
'replies' => 'replies',
|
||||
@ -46,6 +40,15 @@ class Api {
|
||||
'bump' => 'last_modified'
|
||||
);
|
||||
|
||||
$this->fileFields = array(
|
||||
'thumbheight' => 'tn_w',
|
||||
'thumbwidth' => 'tn_h',
|
||||
'height' => 'w',
|
||||
'width' => 'h',
|
||||
'size' => 'fsize',
|
||||
'file' => 'filename',
|
||||
);
|
||||
|
||||
if (isset($config['api']['extra_fields']) && gettype($config['api']['extra_fields']) == 'array'){
|
||||
$this->postFields = array_merge($this->postFields, $config['api']['extra_fields']);
|
||||
}
|
||||
@ -67,31 +70,27 @@ class Api {
|
||||
'last_modified' => 1
|
||||
);
|
||||
|
||||
private function translatePost($post, $threadsPage = false) {
|
||||
$apiPost = array();
|
||||
$fields = $threadsPage ? $this->threadsPageFields : $this->postFields;
|
||||
private function translateFields($fields, $object, &$apiPost) {
|
||||
foreach ($fields as $local => $translated) {
|
||||
if (!isset($post->$local))
|
||||
if (!isset($object->$local))
|
||||
continue;
|
||||
|
||||
$toInt = isset(self::$ints[$translated]);
|
||||
$val = $post->$local;
|
||||
$val = $object->$local;
|
||||
if ($val !== null && $val !== '') {
|
||||
$apiPost[$translated] = $toInt ? (int) $val : $val;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private function translatePost($post, $threadsPage = false) {
|
||||
$apiPost = array();
|
||||
$fields = $threadsPage ? $this->threadsPageFields : $this->postFields;
|
||||
$this->translateFields($fields, $post, $apiPost);
|
||||
|
||||
if ($threadsPage) return $apiPost;
|
||||
|
||||
if (isset($post->filename)) {
|
||||
$dotPos = strrpos($post->filename, '.');
|
||||
$apiPost['filename'] = substr($post->filename, 0, $dotPos);
|
||||
$apiPost['ext'] = substr($post->filename, $dotPos);
|
||||
$dotPos = strrpos($post->file, '.');
|
||||
$apiPost['tim'] = substr($post->file, 0, $dotPos);
|
||||
}
|
||||
|
||||
// Handle country field
|
||||
if (isset($post->body_nomarkup) && $this->config['country_flags']) {
|
||||
$modifiers = extract_modifiers($post->body_nomarkup);
|
||||
@ -104,6 +103,18 @@ class Api {
|
||||
}
|
||||
}
|
||||
|
||||
// Handle files
|
||||
// Note: 4chan only supports one file, so only the first file is taken into account for 4chan-compatible API.
|
||||
if (isset($post->files) && $post->files && !$threadsPage) {
|
||||
$file = $post->files[0];
|
||||
$this->translateFields($this->fileFields, $file, $apiPost);
|
||||
$dotPos = strrpos($file->file, '.');
|
||||
$apiPost['filename'] = substr($file->file, 0, $dotPos);
|
||||
$apiPost['ext'] = substr($file->file, $dotPos);
|
||||
$dotPos = strrpos($file->file, '.');
|
||||
$apiPost['tim'] = substr($file->file, 0, $dotPos);
|
||||
}
|
||||
|
||||
return $apiPost;
|
||||
}
|
||||
|
||||
|
@ -607,6 +607,17 @@
|
||||
* Image settings
|
||||
* ====================
|
||||
*/
|
||||
// Maximum number of images allowed. Increasing this number enabled multi image.
|
||||
// If you make it more than 1, make sure to enable the below script for the post form to change.
|
||||
// $config['additional_javascript'][] = 'js/multi_image.js';
|
||||
$config['max_images'] = 1;
|
||||
|
||||
// Method to use for determing the max filesize.
|
||||
// "split" means that your max filesize is split between the images. For example, if your max filesize
|
||||
// is 2MB, the filesizes of all files must add up to 2MB for it to work.
|
||||
// "each" means that each file can be 2MB, so if your max_images is 3, each post could contain 6MB of
|
||||
// images. "split" is recommended.
|
||||
$config['multiimage_method'] = 'split';
|
||||
|
||||
// For resizing, maximum thumbnail dimensions.
|
||||
$config['thumb_width'] = 255;
|
||||
@ -628,22 +639,22 @@
|
||||
/*
|
||||
* Thumbnailing method:
|
||||
*
|
||||
* 'gd' PHP GD (default). Only handles the most basic image formats (GIF, JPEG, PNG).
|
||||
* GD is a prerequisite for Tinyboard no matter what method you choose.
|
||||
* 'gd' PHP GD (default). Only handles the most basic image formats (GIF, JPEG, PNG).
|
||||
* GD is a prerequisite for Tinyboard no matter what method you choose.
|
||||
*
|
||||
* 'imagick' PHP's ImageMagick bindings. Fast and efficient, supporting many image formats.
|
||||
* A few minor bugs. http://pecl.php.net/package/imagick
|
||||
* 'imagick' PHP's ImageMagick bindings. Fast and efficient, supporting many image formats.
|
||||
* A few minor bugs. http://pecl.php.net/package/imagick
|
||||
*
|
||||
* 'convert' The command line version of ImageMagick (`convert`). Fixes most of the bugs in
|
||||
* PHP Imagick. `convert` produces the best still thumbnails and is highly recommended.
|
||||
* 'convert' The command line version of ImageMagick (`convert`). Fixes most of the bugs in
|
||||
* PHP Imagick. `convert` produces the best still thumbnails and is highly recommended.
|
||||
*
|
||||
* 'gm' GraphicsMagick (`gm`) is a fork of ImageMagick with many improvements. It is more
|
||||
* efficient and gets thumbnailing done using fewer resources.
|
||||
* 'gm' GraphicsMagick (`gm`) is a fork of ImageMagick with many improvements. It is more
|
||||
* efficient and gets thumbnailing done using fewer resources.
|
||||
*
|
||||
* 'convert+gifscale'
|
||||
* OR 'gm+gifsicle' Same as above, with the exception of using `gifsicle` (command line application)
|
||||
* instead of `convert` for resizing GIFs. It's faster and resulting animated
|
||||
* thumbnails have less artifacts than if resized with ImageMagick.
|
||||
* OR 'gm+gifsicle' Same as above, with the exception of using `gifsicle` (command line application)
|
||||
* instead of `convert` for resizing GIFs. It's faster and resulting animated
|
||||
* thumbnails have less artifacts than if resized with ImageMagick.
|
||||
*/
|
||||
$config['thumb_method'] = 'gd';
|
||||
// $config['thumb_method'] = 'convert';
|
||||
@ -693,7 +704,7 @@
|
||||
|
||||
// An alternative function for generating image filenames, instead of the default UNIX timestamp.
|
||||
// $config['filename_func'] = function($post) {
|
||||
// return sprintf("%s", time() . substr(microtime(), 2, 3));
|
||||
// return sprintf("%s", time() . substr(microtime(), 2, 3));
|
||||
// };
|
||||
|
||||
// Thumbnail to use for the non-image file uploads.
|
||||
@ -986,6 +997,7 @@
|
||||
$config['error']['toolong_body'] = _('The body was too long.');
|
||||
$config['error']['tooshort_body'] = _('The body was too short or empty.');
|
||||
$config['error']['noimage'] = _('You must upload an image.');
|
||||
$config['error']['toomanyimages'] = _('You have attempted to upload too many images!');
|
||||
$config['error']['nomove'] = _('The server failed to handle your upload.');
|
||||
$config['error']['fileext'] = _('Unsupported image format.');
|
||||
$config['error']['noboard'] = _('Invalid board!');
|
||||
@ -1444,16 +1456,16 @@
|
||||
$config['search']['enable'] = false;
|
||||
|
||||
// Maximal number of queries per IP address per minutes
|
||||
$config['search']['queries_per_minutes'] = Array(15, 2);
|
||||
$config['search']['queries_per_minutes'] = Array(15, 2);
|
||||
|
||||
// Global maximal number of queries per minutes
|
||||
$config['search']['queries_per_minutes_all'] = Array(50, 2);
|
||||
$config['search']['queries_per_minutes_all'] = Array(50, 2);
|
||||
|
||||
// Limit of search results
|
||||
$config['search']['search_limit'] = 100;
|
||||
$config['search']['search_limit'] = 100;
|
||||
|
||||
// Boards for searching
|
||||
//$config['search']['boards'] = array('a', 'b', 'c', 'd', 'e');
|
||||
//$config['search']['boards'] = array('a', 'b', 'c', 'd', 'e');
|
||||
|
||||
/*
|
||||
* ====================
|
||||
|
@ -94,7 +94,7 @@ function error($message, $priority = true, $debug_stuff = false) {
|
||||
|
||||
// Return the bad request header, necessary for AJAX posts
|
||||
// czaks: is it really so? the ajax errors only work when this is commented out
|
||||
// better yet use it when ajax is disabled
|
||||
// better yet use it when ajax is disabled
|
||||
if (!isset ($_POST['json_response'])) {
|
||||
header($_SERVER['SERVER_PROTOCOL'] . ' 400 Bad Request');
|
||||
}
|
||||
@ -339,6 +339,9 @@ class Post {
|
||||
$this->{$key} = $value;
|
||||
}
|
||||
|
||||
if (isset($this->files))
|
||||
$this->files = json_decode($this->files);
|
||||
|
||||
$this->subject = utf8tohtml($this->subject);
|
||||
$this->name = utf8tohtml($this->name);
|
||||
$this->mod = $mod;
|
||||
@ -396,7 +399,7 @@ class Post {
|
||||
$built .= ' <a title="'._('Ban & Delete').'" href="?/' . $board['dir'] . '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))
|
||||
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)
|
||||
@ -418,9 +421,6 @@ class Post {
|
||||
return $built;
|
||||
}
|
||||
|
||||
public function ratio() {
|
||||
return fraction($this->filewidth, $this->fileheight, ':');
|
||||
}
|
||||
|
||||
public function build($index=false) {
|
||||
global $board, $config;
|
||||
@ -439,6 +439,9 @@ class Thread {
|
||||
$this->{$key} = $value;
|
||||
}
|
||||
|
||||
if (isset($this->files))
|
||||
$this->files = json_decode($this->files);
|
||||
|
||||
$this->subject = utf8tohtml($this->subject);
|
||||
$this->name = utf8tohtml($this->name);
|
||||
$this->mod = $mod;
|
||||
@ -477,7 +480,7 @@ class Thread {
|
||||
$this->posts[] = $post;
|
||||
}
|
||||
public function postCount() {
|
||||
return count($this->posts) + $this->omitted;
|
||||
return count($this->posts) + $this->omitted;
|
||||
}
|
||||
public function postControls() {
|
||||
global $board, $config;
|
||||
@ -506,7 +509,7 @@ class Thread {
|
||||
$built .= ' <a title="'._('Ban & Delete').'" href="?/' . $board['dir'] . '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))
|
||||
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)
|
||||
@ -546,10 +549,6 @@ class Thread {
|
||||
return $built;
|
||||
}
|
||||
|
||||
public function ratio() {
|
||||
return fraction($this->filewidth, $this->fileheight, ':');
|
||||
}
|
||||
|
||||
public function build($index=false, $isnoko50=false) {
|
||||
global $board, $config, $debug;
|
||||
|
||||
|
@ -96,9 +96,9 @@ function loadConfig() {
|
||||
|
||||
$configstr = file_get_contents('inc/instance-config.php');
|
||||
|
||||
if (isset($board['dir']) && file_exists($board['dir'] . '/config.php')) {
|
||||
$configstr .= file_get_contents($board['dir'] . '/config.php');
|
||||
}
|
||||
if (isset($board['dir']) && file_exists($board['dir'] . '/config.php')) {
|
||||
$configstr .= file_get_contents($board['dir'] . '/config.php');
|
||||
}
|
||||
$matches = array();
|
||||
preg_match_all('/[^\/*#]\$config\s*\[\s*[\'"]locale[\'"]\s*\]\s*=\s*([\'"])(.*?)\1/', $configstr, $matches);
|
||||
if ($matches && isset ($matches[2]) && $matches[2]) {
|
||||
@ -859,7 +859,7 @@ function insertFloodPost(array $post) {
|
||||
|
||||
function post(array $post) {
|
||||
global $pdo, $board;
|
||||
$query = prepare(sprintf("INSERT INTO ``posts_%s`` VALUES ( NULL, :thread, :subject, :email, :name, :trip, :capcode, :body, :body_nomarkup, :time, :time, :thumb, :thumbwidth, :thumbheight, :file, :width, :height, :filesize, :filename, :filehash, :password, :ip, :sticky, :locked, 0, :embed)", $board['uri']));
|
||||
$query = prepare(sprintf("INSERT INTO ``posts_%s`` VALUES ( NULL, :thread, :subject, :email, :name, :trip, :capcode, :body, :body_nomarkup, :time, :time, :files, :num_files, :filehash, :password, :ip, :sticky, :locked, 0, :embed)", $board['uri']));
|
||||
|
||||
// Basic stuff
|
||||
if (!empty($post['subject'])) {
|
||||
@ -919,31 +919,12 @@ function post(array $post) {
|
||||
}
|
||||
|
||||
if ($post['has_file']) {
|
||||
$query->bindValue(':thumb', $post['thumb']);
|
||||
$query->bindValue(':thumbwidth', $post['thumbwidth'], PDO::PARAM_INT);
|
||||
$query->bindValue(':thumbheight', $post['thumbheight'], PDO::PARAM_INT);
|
||||
$query->bindValue(':file', $post['file']);
|
||||
|
||||
if (isset($post['width'], $post['height'])) {
|
||||
$query->bindValue(':width', $post['width'], PDO::PARAM_INT);
|
||||
$query->bindValue(':height', $post['height'], PDO::PARAM_INT);
|
||||
} else {
|
||||
$query->bindValue(':width', null, PDO::PARAM_NULL);
|
||||
$query->bindValue(':height', null, PDO::PARAM_NULL);
|
||||
}
|
||||
|
||||
$query->bindValue(':filesize', $post['filesize'], PDO::PARAM_INT);
|
||||
$query->bindValue(':filename', $post['filename']);
|
||||
$query->bindValue(':files', json_encode($post['files']));
|
||||
$query->bindValue(':num_files', $post['num_files']);
|
||||
$query->bindValue(':filehash', $post['filehash']);
|
||||
} else {
|
||||
$query->bindValue(':thumb', null, PDO::PARAM_NULL);
|
||||
$query->bindValue(':thumbwidth', null, PDO::PARAM_NULL);
|
||||
$query->bindValue(':thumbheight', null, PDO::PARAM_NULL);
|
||||
$query->bindValue(':file', null, PDO::PARAM_NULL);
|
||||
$query->bindValue(':width', null, PDO::PARAM_NULL);
|
||||
$query->bindValue(':height', null, PDO::PARAM_NULL);
|
||||
$query->bindValue(':filesize', null, PDO::PARAM_NULL);
|
||||
$query->bindValue(':filename', null, PDO::PARAM_NULL);
|
||||
$query->bindValue(':files', null, PDO::PARAM_NULL);
|
||||
$query->bindValue(':num_files', 0);
|
||||
$query->bindValue(':filehash', null, PDO::PARAM_NULL);
|
||||
}
|
||||
|
||||
@ -974,28 +955,31 @@ function bumpThread($id) {
|
||||
function deleteFile($id, $remove_entirely_if_already=true) {
|
||||
global $board, $config;
|
||||
|
||||
$query = prepare(sprintf("SELECT `thread`,`thumb`,`file` FROM ``posts_%s`` WHERE `id` = :id LIMIT 1", $board['uri']));
|
||||
$query = prepare(sprintf("SELECT `thread`, `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']);
|
||||
|
||||
if ($post['file'] == 'deleted' && !$post['thread'])
|
||||
if ($files[0]->file == 'deleted' && !$post['thread'])
|
||||
return; // Can't delete OP's image completely.
|
||||
|
||||
$query = prepare(sprintf("UPDATE ``posts_%s`` SET `thumb` = NULL, `thumbwidth` = NULL, `thumbheight` = NULL, `filewidth` = NULL, `fileheight` = NULL, `filesize` = NULL, `filename` = NULL, `filehash` = NULL, `file` = :file WHERE `id` = :id", $board['uri']));
|
||||
if ($post['file'] == 'deleted' && $remove_entirely_if_already) {
|
||||
$query = prepare(sprintf("UPDATE ``posts_%s`` SET `files` = :file WHERE `id` = :id", $board['uri']));
|
||||
if ($files[0]->file == 'deleted' && $remove_entirely_if_already) {
|
||||
// Already deleted; remove file fully
|
||||
$query->bindValue(':file', null, PDO::PARAM_NULL);
|
||||
} else {
|
||||
// Delete thumbnail
|
||||
file_unlink($board['dir'] . $config['dir']['thumb'] . $post['thumb']);
|
||||
foreach ($files as $i => $file) {
|
||||
// Delete thumbnail
|
||||
file_unlink($board['dir'] . $config['dir']['thumb'] . $file->thumb);
|
||||
|
||||
// Delete file
|
||||
file_unlink($board['dir'] . $config['dir']['img'] . $post['file']);
|
||||
// Delete file
|
||||
file_unlink($board['dir'] . $config['dir']['img'] . $file->file);
|
||||
}
|
||||
|
||||
// Set file to 'deleted'
|
||||
$query->bindValue(':file', 'deleted', PDO::PARAM_INT);
|
||||
$query->bindValue(':file', '[{"file":"deleted"}]', PDO::PARAM_STR);
|
||||
}
|
||||
|
||||
$query->bindValue(':id', $id, PDO::PARAM_INT);
|
||||
@ -1035,7 +1019,7 @@ function deletePost($id, $error_if_doesnt_exist=true, $rebuild_after=true) {
|
||||
global $board, $config;
|
||||
|
||||
// Select post and replies (if thread) in one query
|
||||
$query = prepare(sprintf("SELECT `id`,`thread`,`thumb`,`file` FROM ``posts_%s`` WHERE `id` = :id OR `thread` = :id", $board['uri']));
|
||||
$query = prepare(sprintf("SELECT `id`,`thread`,`files` FROM ``posts_%s`` WHERE `id` = :id OR `thread` = :id", $board['uri']));
|
||||
$query->bindValue(':id', $id, PDO::PARAM_INT);
|
||||
$query->execute() or error(db_error($query));
|
||||
|
||||
@ -1065,13 +1049,12 @@ function deletePost($id, $error_if_doesnt_exist=true, $rebuild_after=true) {
|
||||
// Rebuild thread
|
||||
$rebuild = &$post['thread'];
|
||||
}
|
||||
if ($post['thumb']) {
|
||||
// Delete thumbnail
|
||||
file_unlink($board['dir'] . $config['dir']['thumb'] . $post['thumb']);
|
||||
}
|
||||
if ($post['file']) {
|
||||
if ($post['files']) {
|
||||
// Delete file
|
||||
file_unlink($board['dir'] . $config['dir']['img'] . $post['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);
|
||||
}
|
||||
}
|
||||
|
||||
$ids[] = (int)$post['id'];
|
||||
@ -1188,8 +1171,8 @@ function index($page, $mod=false) {
|
||||
|
||||
$num_images = 0;
|
||||
foreach ($replies as $po) {
|
||||
if ($po['file'])
|
||||
$num_images++;
|
||||
if ($po['num_files'])
|
||||
$num_images+=$po['num_files'];
|
||||
|
||||
$thread->add(new Post($po, $mod ? '?/' : $config['root'], $mod));
|
||||
}
|
||||
@ -1347,7 +1330,7 @@ function checkRobot($body) {
|
||||
// Returns an associative array with 'replies' and 'images' keys
|
||||
function numPosts($id) {
|
||||
global $board;
|
||||
$query = prepare(sprintf("SELECT COUNT(*) AS `replies`, COUNT(NULLIF(`file`, 0)) AS `images` FROM ``posts_%s`` WHERE `thread` = :thread", $board['uri'], $board['uri']));
|
||||
$query = prepare(sprintf("SELECT COUNT(*) AS `replies`, SUM(`num_files`) AS `images` FROM ``posts_%s`` WHERE `thread` = :thread", $board['uri'], $board['uri']));
|
||||
$query->bindValue(':thread', $id, PDO::PARAM_INT);
|
||||
$query->execute() or error(db_error($query));
|
||||
|
||||
@ -1905,7 +1888,7 @@ function markup(&$body, $track_cites = false) {
|
||||
}
|
||||
|
||||
// replace tabs with 8 spaces
|
||||
$body = str_replace("\t", ' ', $body);
|
||||
$body = str_replace("\t", ' ', $body);
|
||||
|
||||
return $tracked_cites;
|
||||
}
|
||||
@ -2232,13 +2215,15 @@ function getPostByHashInThread($hash, $thread) {
|
||||
}
|
||||
|
||||
function undoImage(array $post) {
|
||||
if (!$post['has_file'])
|
||||
if (!$post['has_file'] || !isset($post['files']))
|
||||
return;
|
||||
|
||||
if (isset($post['file_path']))
|
||||
file_unlink($post['file_path']);
|
||||
if (isset($post['thumb_path']))
|
||||
file_unlink($post['thumb_path']);
|
||||
foreach ($post['files'] as $key => $file) {
|
||||
if (isset($file['file_path']))
|
||||
file_unlink($file['file_path']);
|
||||
if (isset($file['thumb_path']))
|
||||
file_unlink($file['thumb_path']);
|
||||
}
|
||||
}
|
||||
|
||||
function rDNS($ip_addr) {
|
||||
|
@ -25,7 +25,7 @@ class Twig_Extensions_Extension_Tinyboard extends Twig_Extension
|
||||
new Twig_SimpleFilter('until', 'until'),
|
||||
new Twig_SimpleFilter('push', 'twig_push_filter'),
|
||||
new Twig_SimpleFilter('bidi_cleanup', 'bidi_cleanup'),
|
||||
new Twig_SimpleFilter('addslashes', 'addslashes')
|
||||
new Twig_SimpleFilter('addslashes', 'addslashes'),
|
||||
);
|
||||
}
|
||||
|
||||
@ -42,6 +42,7 @@ 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')
|
||||
);
|
||||
}
|
||||
|
||||
@ -100,3 +101,6 @@ function twig_truncate_filter($value, $length = 30, $preserve = false, $separato
|
||||
return $value;
|
||||
}
|
||||
|
||||
function twig_ratio_function($w, $h) {
|
||||
return fraction($w, $h, ':');
|
||||
}
|
||||
|
23
install.php
23
install.php
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
// Installation/upgrade file
|
||||
define('VERSION', '4.4.98');
|
||||
define('VERSION', '4.9.90');
|
||||
|
||||
require 'inc/functions.php';
|
||||
|
||||
@ -260,7 +260,7 @@ if (file_exists($config['has_installed'])) {
|
||||
$_query->execute() or error(db_error($_query));
|
||||
}
|
||||
}
|
||||
case 'v0.9.6-dev-9':
|
||||
case 'v0.9.6-dev-9':
|
||||
case 'v0.9.6-dev-9 + <a href="https://github.com/vichan-devel/Tinyboard/">vichan-devel-4.0.3</a>':
|
||||
case 'v0.9.6-dev-9 + <a href="https://github.com/vichan-devel/Tinyboard/">vichan-devel-4.0.4-gold</a>':
|
||||
case 'v0.9.6-dev-9 + <a href="https://github.com/vichan-devel/Tinyboard/">vichan-devel-4.0.5-gold</a>':
|
||||
@ -521,6 +521,14 @@ if (file_exists($config['has_installed'])) {
|
||||
case '4.4.98-pre':
|
||||
if (!$twig) load_twig();
|
||||
$twig->clearCacheFiles();
|
||||
case '4.4.98':
|
||||
foreach ($boards as &$board) {
|
||||
query(sprintf('ALTER TABLE ``posts_%s`` ADD `files` text DEFAULT NULL AFTER `bump`;', $board['uri'])) or error(db_error());
|
||||
query(sprintf('ALTER TABLE ``posts_%s`` ADD `num_files` int(11) DEFAULT 0 AFTER `files`;', $board['uri'])) or error(db_error());
|
||||
query(sprintf('UPDATE ``posts_%s`` SET `files` = CONCAT(\'[{"file":"\',`filename`,\'", "size":"\',`filesize`,\'", "width":"\',`filewidth`,\'","height":"\',`fileheight`,\'","thumbwidth":"\',`thumbwidth`,\'","thumbheight":"\',`thumbheight`,\'", "file_path":"%s\/src\/\',`filename`,\'","thumb_path":"%s\/thumb\/\',`filename`,\'"}]\') WHERE `file` IS NOT NULL', $board['uri'], $board['uri'], $board['uri'])) or error(db_error());
|
||||
query(sprintf('ALTER TABLE ``posts_%s`` DROP COLUMN `thumb`, DROP COLUMN `thumbwidth`, DROP COLUMN `thumbheight`, DROP COLUMN `file`, DROP COLUMN `fileheight`, DROP COLUMN `filesize`, DROP COLUMN `filename`', $board['uri'])) or error(db_error());
|
||||
query(sprintf('ALTER TABLE ``posts_%s`` REBUILD', $board['uri'])) or error(db_error());
|
||||
}
|
||||
case false:
|
||||
// TODO: enhance Tinyboard -> vichan upgrade path.
|
||||
query("CREATE TABLE IF NOT EXISTS ``search_queries`` ( `ip` varchar(39) NOT NULL, `time` int(11) NOT NULL, `query` text NOT NULL) ENGINE=MyISAM DEFAULT CHARSET=utf8;") or error(db_error());
|
||||
@ -679,6 +687,13 @@ if ($step == 0) {
|
||||
'required' => false,
|
||||
'message' => '(Optional) `gifsicle` was not found or executable; you may not use `convert+gifsicle` for better animated GIF thumbnailing.',
|
||||
),
|
||||
array(
|
||||
'category' => 'Image processing',
|
||||
'name' => '`md5sum` (quick file hashing)',
|
||||
'result' => $can_exec && shell_exec('echo "vichan" | md5sum') == "141225c362da02b5c359c45b665168de -\n",
|
||||
'required' => false,
|
||||
'message' => '(Optional) `md5sum` was not found or executable; file hashing for multiple images will be slower.',
|
||||
),
|
||||
array(
|
||||
'category' => 'File permissions',
|
||||
'name' => getcwd(),
|
||||
@ -833,9 +848,9 @@ if ($step == 0) {
|
||||
}
|
||||
|
||||
file_write($config['has_installed'], VERSION);
|
||||
if (!file_unlink(__FILE__)) {
|
||||
/*if (!file_unlink(__FILE__)) {
|
||||
$page['body'] .= '<div class="ban"><h2>Delete install.php!</h2><p>I couldn\'t remove <strong>install.php</strong>. You will have to remove it manually.</p></div>';
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
echo Element('page.html', $page);
|
||||
|
30
js/multi_image.js
Normal file
30
js/multi_image.js
Normal file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* multi-image.js - Add support for multiple images to the post form
|
||||
*
|
||||
* Copyright (c) 2014 Fredrick Brennan <admin@8chan.co>
|
||||
*
|
||||
* Usage:
|
||||
* $config['max_images'] = 3;
|
||||
* $config['additional_javascript'][] = 'js/jquery.min.js';
|
||||
* $config['additional_javascript'][] = 'js/multi-image.js';
|
||||
*/
|
||||
|
||||
function multi_image() {
|
||||
$('input[type=file]').after('<a href="#" class="add_image">+</a>');
|
||||
|
||||
$(document).on('click', 'a.add_image', function(e) {
|
||||
e.preventDefault();
|
||||
$('#upload_url').remove();
|
||||
|
||||
var images_len = $('input[type=file]').length;
|
||||
|
||||
if (!(images_len >= max_images)) {
|
||||
$('.add_image').after('<br/><input type="file" name="file'+(images_len+1)+'" id="upload_file'+(images_len+1)+'">');
|
||||
if (typeof setup_form !== 'undefined') setup_form($('form[name="post"]'));
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if (active_page == 'thread' || active_page == 'index' && max_images > 1) {
|
||||
$(document).ready(multi_image);
|
||||
}
|
210
post.php
210
post.php
@ -150,7 +150,7 @@ if (isset($_POST['delete'])) {
|
||||
if (!isset($_POST['body'], $_POST['board']))
|
||||
error($config['error']['bot']);
|
||||
|
||||
$post = array('board' => $_POST['board']);
|
||||
$post = array('board' => $_POST['board'], 'files' => array());
|
||||
|
||||
// Check if board exists
|
||||
if (!openBoard($post['board']))
|
||||
@ -178,7 +178,7 @@ if (isset($_POST['delete'])) {
|
||||
$post['op'] = true;
|
||||
|
||||
if (!(($post['op'] && $_POST['post'] == $config['button_newtopic']) ||
|
||||
(!$post['op'] && $_POST['post'] == $config['button_reply'])))
|
||||
(!$post['op'] && $_POST['post'] == $config['button_reply'])))
|
||||
error($config['error']['bot']);
|
||||
|
||||
// Check the referrer
|
||||
@ -328,21 +328,12 @@ if (isset($_POST['delete'])) {
|
||||
);
|
||||
}
|
||||
|
||||
// Check for a file
|
||||
if ($post['op'] && !isset($post['no_longer_require_an_image_for_op'])) {
|
||||
if (!isset($_FILES['file']['tmp_name']) || $_FILES['file']['tmp_name'] == '' && $config['force_image_op'])
|
||||
error($config['error']['noimage']);
|
||||
}
|
||||
|
||||
$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']) || (isset($_FILES['file']) && $_FILES['file']['tmp_name'] != ''));
|
||||
|
||||
if ($post['has_file'])
|
||||
$post['filename'] = urldecode(get_magic_quotes_gpc() ? stripslashes($_FILES['file']['name']) : $_FILES['file']['name']);
|
||||
$post['has_file'] = (!isset($post['embed']) && (($post['op'] && !isset($post['no_longer_require_an_image_for_op']) && $config['force_image_op']) || !empty($_FILES)));
|
||||
|
||||
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']);
|
||||
@ -367,6 +358,22 @@ if (isset($_POST['delete'])) {
|
||||
}
|
||||
|
||||
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.'));
|
||||
}
|
||||
|
||||
$size = $_FILES['file']['size'];
|
||||
if ($size > $config['max_filesize'])
|
||||
error(sprintf3($config['error']['filesize'], array(
|
||||
@ -374,6 +381,7 @@ if (isset($_POST['delete'])) {
|
||||
'filesz' => number_format($size),
|
||||
'maxsz' => number_format($config['max_filesize'])
|
||||
)));
|
||||
$post['filesize'] = $size;
|
||||
}
|
||||
|
||||
|
||||
@ -409,16 +417,39 @@ if (isset($_POST['delete'])) {
|
||||
} else $noko = $config['always_noko'];
|
||||
|
||||
if ($post['has_file']) {
|
||||
$post['extension'] = strtolower(mb_substr($post['filename'], mb_strrpos($post['filename'], '.') + 1));
|
||||
if (isset($config['filename_func']))
|
||||
$post['file_id'] = $config['filename_func']($post);
|
||||
else
|
||||
$post['file_id'] = time() . substr(microtime(), 2, 3);
|
||||
$i = 0;
|
||||
foreach ($_FILES as $key => $file) {
|
||||
if ($file['size'] && $file['tmp_name']) {
|
||||
$file['filename'] = urldecode(get_magic_quotes_gpc() ? stripslashes($file['name']) : $file['name']);
|
||||
$file['extension'] = strtolower(mb_substr($file['filename'], mb_strrpos($file['filename'], '.') + 1));
|
||||
if (isset($config['filename_func']))
|
||||
$file['file_id'] = $config['filename_func']($file);
|
||||
else
|
||||
$file['file_id'] = time() . substr(microtime(), 2, 3);
|
||||
|
||||
$post['file'] = $board['dir'] . $config['dir']['img'] . $post['file_id'] . '.' . $post['extension'];
|
||||
$post['thumb'] = $board['dir'] . $config['dir']['thumb'] . $post['file_id'] . '.' . ($config['thumb_ext'] ? $config['thumb_ext'] : $post['extension']);
|
||||
if (sizeof($_FILES) > 1)
|
||||
$file['file_id'] .= "-$i";
|
||||
|
||||
$file['file'] = $board['dir'] . $config['dir']['img'] . $file['file_id'] . '.' . $file['extension'];
|
||||
$file['thumb'] = $board['dir'] . $config['dir']['thumb'] . $file['file_id'] . '.' . ($config['thumb_ext'] ? $config['thumb_ext'] : $file['extension']);
|
||||
$post['files'][] = $file;
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($post['files'])) $post['has_file'] = false;
|
||||
|
||||
// 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']);
|
||||
@ -475,7 +506,7 @@ if (isset($_POST['delete'])) {
|
||||
$user_flag = $_POST['user_flag'];
|
||||
|
||||
if (!isset($config['user_flags'][$user_flag]))
|
||||
error('Invalid flag selection!');
|
||||
error(_('Invalid flag selection!'));
|
||||
|
||||
$flag_alt = isset($user_flag_alt) ? $user_flag_alt : $config['user_flags'][$user_flag];
|
||||
|
||||
@ -505,21 +536,38 @@ if (isset($_POST['delete'])) {
|
||||
|
||||
|
||||
if ($post['has_file']) {
|
||||
if (!in_array($post['extension'], $config['allowed_ext']) && !in_array($post['extension'], $config['allowed_ext_files']))
|
||||
error($config['error']['unknownext']);
|
||||
foreach ($post['files'] as $key => &$file) {
|
||||
if (!in_array($file['extension'], $config['allowed_ext']) && !in_array($file['extension'], $config['allowed_ext_files']))
|
||||
error($config['error']['unknownext']);
|
||||
|
||||
$is_an_image = !in_array($post['extension'], $config['allowed_ext_files']);
|
||||
$file['is_an_image'] = !in_array($file['extension'], $config['allowed_ext_files']);
|
||||
|
||||
// Truncate filename if it is too long
|
||||
$post['filename'] = mb_substr($post['filename'], 0, $config['max_filename_len']);
|
||||
// Truncate filename if it is too long
|
||||
$file['filename'] = mb_substr($file['filename'], 0, $config['max_filename_len']);
|
||||
|
||||
$upload = $_FILES['file']['tmp_name'];
|
||||
if (!isset($filenames)) {
|
||||
$filenames = escapeshellarg($file['tmp_name']);
|
||||
} else {
|
||||
$filenames .= (' ' . escapeshellarg($file['tmp_name']));
|
||||
}
|
||||
$upload = $file['tmp_name'];
|
||||
|
||||
if (!is_readable($upload))
|
||||
error($config['error']['nomove']);
|
||||
if (!is_readable($upload))
|
||||
error($config['error']['nomove']);
|
||||
}
|
||||
|
||||
$post['filehash'] = md5_file($upload);
|
||||
$post['filesize'] = filesize($upload);
|
||||
if ($output = shell_exec_error("cat $filenames | md5sum")) {
|
||||
$hash = explode(' ', $output)[0];
|
||||
$post['filehash'] = $hash;
|
||||
} elseif ($config['max_images'] === 1) {
|
||||
$post['filehash'] = md5_file($upload);
|
||||
} else {
|
||||
$str_to_hash = '';
|
||||
foreach (explode(' ', $filenames) as $i => $f) {
|
||||
$str_to_hash .= file_get_contents($f);
|
||||
}
|
||||
$post['filehash'] = md5($str_to_hash);
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasPermission($config['mod']['bypass_filters'], $board['uri'])) {
|
||||
@ -529,7 +577,8 @@ if (isset($_POST['delete'])) {
|
||||
}
|
||||
|
||||
if ($post['has_file']) {
|
||||
if ($is_an_image && $config['ie_mime_type_detection'] !== false) {
|
||||
foreach ($post['files'] as $key => &$file) {
|
||||
if ($file['is_an_image'] && $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)) {
|
||||
@ -540,7 +589,7 @@ if (isset($_POST['delete'])) {
|
||||
require_once 'inc/image.php';
|
||||
|
||||
// find dimensions of an image using GD
|
||||
if (!$size = @getimagesize($upload)) {
|
||||
if (!$size = @getimagesize($file['tmp_name'])) {
|
||||
error($config['error']['invalidimg']);
|
||||
}
|
||||
if ($size[0] > $config['max_width'] || $size[1] > $config['max_height']) {
|
||||
@ -548,93 +597,93 @@ if (isset($_POST['delete'])) {
|
||||
}
|
||||
|
||||
|
||||
if ($config['convert_auto_orient'] && ($post['extension'] == 'jpg' || $post['extension'] == 'jpeg')) {
|
||||
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']) && ($post['extension'] == 'jpg' || $post['extension'] == 'jpeg')))) {
|
||||
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($upload);
|
||||
$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($upload) . ' ' .
|
||||
escapeshellarg($file['tmp_name']) . ' ' .
|
||||
ImageConvert::jpeg_exif_orientation(false, $exif) . ' ' .
|
||||
($config['strip_exif'] ? '+profile "*"' :
|
||||
($config['use_exiftool'] ? '' : '+profile "*"')
|
||||
) . ' ' .
|
||||
escapeshellarg($upload));
|
||||
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($upload)))
|
||||
error('exiftool failed!', null, $exiftool_error);
|
||||
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`.
|
||||
}
|
||||
} else {
|
||||
$error = shell_exec_error(($gm ? 'gm ' : '') . 'convert ' .
|
||||
escapeshellarg($upload) . ' -auto-orient ' . escapeshellarg($upload));
|
||||
escapeshellarg($file['tmp_name']) . ' -auto-orient ' . escapeshellarg($upload));
|
||||
}
|
||||
if ($error)
|
||||
error('Could not auto-orient image!', null, $error);
|
||||
$size = @getimagesize($upload);
|
||||
error(_('Could not auto-orient image!'), null, $error);
|
||||
$size = @getimagesize($file['tmp_name']);
|
||||
if ($config['strip_exif'])
|
||||
$post['exif_stripped'] = true;
|
||||
$file['exif_stripped'] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// create image object
|
||||
$image = new Image($upload, $post['extension'], $size);
|
||||
$image = new Image($file['tmp_name'], $file['extension'], $size);
|
||||
if ($image->size->width > $config['max_width'] || $image->size->height > $config['max_height']) {
|
||||
$image->delete();
|
||||
error($config['error']['maxsize']);
|
||||
}
|
||||
|
||||
$post['width'] = $image->size->width;
|
||||
$post['height'] = $image->size->height;
|
||||
$file['width'] = $image->size->width;
|
||||
$file['height'] = $image->size->height;
|
||||
|
||||
if ($config['spoiler_images'] && isset($_POST['spoiler'])) {
|
||||
$post['thumb'] = 'spoiler';
|
||||
$file['thumb'] = 'spoiler';
|
||||
|
||||
$size = @getimagesize($config['spoiler_image']);
|
||||
$post['thumbwidth'] = $size[0];
|
||||
$post['thumbheight'] = $size[1];
|
||||
$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'] &&
|
||||
$post['extension'] == ($config['thumb_ext'] ? $config['thumb_ext'] : $post['extension'])) {
|
||||
$file['extension'] == ($config['thumb_ext'] ? $config['thumb_ext'] : $file['extension'])) {
|
||||
|
||||
// Copy, because there's nothing to resize
|
||||
copy($upload, $post['thumb']);
|
||||
copy($file['tmp_name'], $file['thumb']);
|
||||
|
||||
$post['thumbwidth'] = $image->size->width;
|
||||
$post['thumbheight'] = $image->size->height;
|
||||
$file['thumbwidth'] = $image->size->width;
|
||||
$file['thumbheight'] = $image->size->height;
|
||||
} else {
|
||||
$thumb = $image->resize(
|
||||
$config['thumb_ext'] ? $config['thumb_ext'] : $post['extension'],
|
||||
$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($post['thumb']);
|
||||
$thumb->to($file['thumb']);
|
||||
|
||||
$post['thumbwidth'] = $thumb->width;
|
||||
$post['thumbheight'] = $thumb->height;
|
||||
$file['thumbwidth'] = $thumb->width;
|
||||
$file['thumbheight'] = $thumb->height;
|
||||
|
||||
$thumb->_destroy();
|
||||
}
|
||||
|
||||
if ($config['redraw_image'] || (!@$post['exif_stripped'] && $config['strip_exif'] && ($post['extension'] == 'jpg' || $post['extension'] == 'jpeg'))) {
|
||||
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($upload)))
|
||||
error('Could not strip EXIF metadata!', null, $error);
|
||||
escapeshellarg($file['tmp_name'])))
|
||||
error(_('Could not strip EXIF metadata!', null, $error));
|
||||
} else {
|
||||
$image->to($post['file']);
|
||||
$image->to($file['file']);
|
||||
$dont_copy_file = true;
|
||||
}
|
||||
}
|
||||
@ -642,26 +691,25 @@ if (isset($_POST['delete'])) {
|
||||
} else {
|
||||
// not an image
|
||||
//copy($config['file_thumb'], $post['thumb']);
|
||||
$post['thumb'] = 'file';
|
||||
$file['thumb'] = 'file';
|
||||
|
||||
$size = @getimagesize(sprintf($config['file_thumb'],
|
||||
isset($config['file_icons'][$post['extension']]) ?
|
||||
$config['file_icons'][$post['extension']] : $config['file_icons']['default']));
|
||||
$post['thumbwidth'] = $size[0];
|
||||
$post['thumbheight'] = $size[1];
|
||||
isset($config['file_icons'][$file['extension']]) ?
|
||||
$config['file_icons'][$file['extension']] : $config['file_icons']['default']));
|
||||
$file['thumbwidth'] = $size[0];
|
||||
$file['thumbheight'] = $size[1];
|
||||
}
|
||||
|
||||
if (!isset($dont_copy_file) || !$dont_copy_file) {
|
||||
if (isset($post['file_tmp'])) {
|
||||
if (!@rename($upload, $post['file']))
|
||||
if (isset($file['file_tmp'])) {
|
||||
if (!@rename($file['tmp_name'], $file['file']))
|
||||
error($config['error']['nomove']);
|
||||
chmod($post['file'], 0644);
|
||||
} elseif (!@move_uploaded_file($upload, $post['file']))
|
||||
chmod($file['file'], 0644);
|
||||
} elseif (!@move_uploaded_file($file['tmp_name'], $file['file']))
|
||||
error($config['error']['nomove']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($post['has_file']) {
|
||||
if ($config['image_reject_repost']) {
|
||||
if ($p = getPostByHash($post['filehash'])) {
|
||||
undoImage($post);
|
||||
@ -689,7 +737,7 @@ if (isset($_POST['delete'])) {
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasPermission($config['mod']['postunoriginal'], $board['uri']) && $config['robot_enable'] && checkRobot($post['body_nomarkup'])) {
|
||||
undoImage($post);
|
||||
@ -702,11 +750,13 @@ if (isset($_POST['delete'])) {
|
||||
|
||||
// Remove board directories before inserting them into the database.
|
||||
if ($post['has_file']) {
|
||||
$post['file_path'] = $post['file'];
|
||||
$post['thumb_path'] = $post['thumb'];
|
||||
$post['file'] = mb_substr($post['file'], mb_strlen($board['dir'] . $config['dir']['img']));
|
||||
if ($is_an_image && $post['thumb'] != 'spoiler')
|
||||
$post['thumb'] = mb_substr($post['thumb'], mb_strlen($board['dir'] . $config['dir']['thumb']));
|
||||
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']));
|
||||
if ($file['is_an_image'] && $file['thumb'] != 'spoiler')
|
||||
$file['thumb'] = mb_substr($file['thumb'], mb_strlen($board['dir'] . $config['dir']['thumb']));
|
||||
}
|
||||
}
|
||||
|
||||
$post = (object)$post;
|
||||
@ -716,6 +766,10 @@ if (isset($_POST['delete'])) {
|
||||
}
|
||||
$post = (array)$post;
|
||||
|
||||
if ($post['files'])
|
||||
$post['files'] = $post['files'];
|
||||
$post['num_files'] = sizeof($post['files']);
|
||||
|
||||
$post['id'] = $id = post($post);
|
||||
|
||||
insertFloodPost($post);
|
||||
|
@ -109,6 +109,9 @@ form table tr td div label {
|
||||
.unimportant, .unimportant * {
|
||||
font-size: 10px;
|
||||
}
|
||||
.file {
|
||||
float: left;
|
||||
}
|
||||
p.fileinfo {
|
||||
display: block;
|
||||
margin: 0;
|
||||
|
@ -291,6 +291,7 @@ function ready() {
|
||||
{% endraw %}
|
||||
|
||||
var post_date = "{{ config.post_date }}";
|
||||
var max_images = {{ config.max_images }};
|
||||
|
||||
onready(init);
|
||||
|
||||
|
38
templates/post/fileinfo.html
Normal file
38
templates/post/fileinfo.html
Normal file
@ -0,0 +1,38 @@
|
||||
{% if post.embed %}
|
||||
{{ post.embed }}
|
||||
{% else %}
|
||||
<div class="files">
|
||||
{% for file in post.files %}
|
||||
<div class="file">
|
||||
{% if file.file == 'deleted' %}
|
||||
<img class="post-image deleted" src="{{ config.image_deleted }}" alt="" />
|
||||
{% else %}
|
||||
<p class="fileinfo">File: <a href="{{ config.uri_img }}{{ file.file }}">{{ file.file }}</a> <span class="unimportant">
|
||||
(
|
||||
{% if file.thumb == 'spoiler' %}
|
||||
{% trans %}Spoiler Image{% endtrans %},
|
||||
{% endif %}
|
||||
{{ file.size|filesize }}
|
||||
{% if file.width and file.height %}
|
||||
, {{ file.width}}x{{ file.height }}
|
||||
{% if config.show_ratio %}
|
||||
, {{ ratio(file.width, file.height) }}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if config.show_filename and file.filename %}
|
||||
,
|
||||
{% if file.filename|length > config.max_filename_display %}
|
||||
<span class="postfilename" title="{{ file.filename|e }}">{{ file.filename|truncate(config.max_filename_display)|bidi_cleanup }}</span>
|
||||
{% else %}
|
||||
<span class="postfilename">{{ file.filename|e|bidi_cleanup }}</span>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% include "post/image_identification.html" %}
|
||||
)
|
||||
</span></p>
|
||||
{% include "post/image.html" with {'post':file} %}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
@ -1,7 +1,6 @@
|
||||
{% filter remove_whitespace %}
|
||||
{# tabs and new lines will be ignored #}
|
||||
<div class="post reply" id="reply_{{ post.id }}">
|
||||
|
||||
<p class="intro"{% if not index %} id="{{ post.id }}"{% endif %}>
|
||||
<input type="checkbox" class="delete" name="delete_{{ post.id }}" id="delete_{{ post.id }}" />
|
||||
<label for="delete_{{ post.id }}">
|
||||
@ -18,38 +17,9 @@
|
||||
{{ post.id }}
|
||||
</a>
|
||||
</p>
|
||||
{% if post.embed %}
|
||||
{{ post.embed }}
|
||||
{% elseif post.file == 'deleted' %}
|
||||
<img class="post-image deleted" src="{{ config.image_deleted }}" alt="" />
|
||||
{% elseif post.file and post.file %}
|
||||
<p class="fileinfo">File: <a href="{{ config.uri_img }}{{ post.file }}">{{ post.file }}</a> <span class="unimportant">
|
||||
(
|
||||
{% if post.thumb == 'spoiler' %}
|
||||
{% trans %}Spoiler Image{% endtrans %},
|
||||
{% endif %}
|
||||
{{ post.filesize|filesize }}
|
||||
{% if post.filewidth and post.fileheight %}
|
||||
, {{ post.filewidth}}x{{ post.fileheight }}
|
||||
{% if config.show_ratio %}
|
||||
, {{ post.ratio }}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if config.show_filename and post.filename %}
|
||||
,
|
||||
{% if post.filename|length > config.max_filename_display %}
|
||||
<span class="postfilename" title="{{ post.filename|e }}">{{ post.filename|truncate(config.max_filename_display)|bidi_cleanup }}</span>
|
||||
{% else %}
|
||||
<span class="postfilename">{{ post.filename|e|bidi_cleanup }}</span>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% include "post/image_identification.html" %}
|
||||
)
|
||||
</span></p>
|
||||
{% include "post/image.html" %}
|
||||
{% endif %}
|
||||
{% include 'post/fileinfo.html' %}
|
||||
{{ post.postControls }}
|
||||
<div class="body">
|
||||
<div class="body" {% if post.files|length > 1 %}style="clear:both"{% endif %}>
|
||||
{% endfilter %}{% if index %}{{ post.body|truncate_body(post.link) }}{% else %}{{ post.body }}{% endif %}{% filter remove_whitespace %}
|
||||
{% if post.modifiers['ban message'] %}
|
||||
{{ config.mod.ban_message|sprintf(post.modifiers['ban message']) }}
|
||||
|
@ -2,38 +2,8 @@
|
||||
{# tabs and new lines will be ignored #}
|
||||
|
||||
<div id="thread_{{ post.id }}" data-board="{{ board.uri }}">
|
||||
|
||||
{% if post.embed %}
|
||||
{{ post.embed }}
|
||||
{% elseif post.file == 'deleted' %}
|
||||
<img class="post-image deleted" src="{{ config.image_deleted }}" alt="" />
|
||||
{% elseif post.file and post.file %}
|
||||
<p class="fileinfo">{% trans %}File:{% endtrans %} <a href="{{ config.uri_img }}{{ post.file }}">{{ post.file }}</a> <span class="unimportant">
|
||||
(
|
||||
{% if post.thumb == 'spoiler' %}
|
||||
{% trans %}Spoiler Image{% endtrans %},
|
||||
{% endif %}
|
||||
{{ post.filesize|filesize }}
|
||||
{% if post.filewidth and post.fileheight %}
|
||||
, {{ post.filewidth}}x{{ post.fileheight }}
|
||||
{% if config.show_ratio %}
|
||||
, {{ post.ratio }}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if config.show_filename and post.filename %}
|
||||
,
|
||||
{% if post.filename|length > config.max_filename_display %}
|
||||
<span class="postfilename" title="{{ post.filename|e }}">{{ post.filename|truncate(config.max_filename_display)|bidi_cleanup }}</span>
|
||||
{% else %}
|
||||
<span class="postfilename">{{ post.filename|e|bidi_cleanup }}</span>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% include "post/image_identification.html" %}
|
||||
)
|
||||
</span></p>
|
||||
{% include "post/image.html" %}
|
||||
{% endif %}
|
||||
<div class="post op"><p class="intro"{% if not index %} id="{{ post.id }}"{% endif %}>
|
||||
{% include 'post/fileinfo.html' %}
|
||||
<div class="post op" {%if post.num_files > 1%}style='clear:both'{%endif%}><p class="intro"{% if not index %} id="{{ post.id }}"{% endif %}>
|
||||
<input type="checkbox" class="delete" name="delete_{{ post.id }}" id="delete_{{ post.id }}" />
|
||||
<label for="delete_{{ post.id }}">
|
||||
{% include 'post/subject.html' %}
|
||||
|
@ -10,14 +10,8 @@ CREATE TABLE IF NOT EXISTS ``posts_{{ board }}`` (
|
||||
`body_nomarkup` text,
|
||||
`time` int(11) NOT NULL,
|
||||
`bump` int(11) DEFAULT NULL,
|
||||
`thumb` varchar(255) DEFAULT NULL,
|
||||
`thumbwidth` int(11) DEFAULT NULL,
|
||||
`thumbheight` int(11) DEFAULT NULL,
|
||||
`file` varchar(255) DEFAULT NULL,
|
||||
`filewidth` int(11) DEFAULT NULL,
|
||||
`fileheight` int(11) DEFAULT NULL,
|
||||
`filesize` int(11) DEFAULT NULL,
|
||||
`filename` text,
|
||||
`files` text DEFAULT NULL,
|
||||
`num_files` int(11) DEFAULT 0,
|
||||
`filehash` text CHARACTER SET ascii,
|
||||
`password` varchar(20) DEFAULT NULL,
|
||||
`ip` varchar(39) CHARACTER SET ascii NOT NULL,
|
||||
|
@ -40,7 +40,10 @@
|
||||
while ($post = $query->fetch(PDO::FETCH_ASSOC)) {
|
||||
$post['link'] = $config['root'] . $board['dir'] . $config['dir']['res'] . sprintf($config['file_page'], ($post['thread'] ? $post['thread'] : $post['id']));
|
||||
$post['board_name'] = $board['name'];
|
||||
$post['file'] = $config['uri_thumb'] . $post['thumb'];
|
||||
if (isset($post['files']))
|
||||
$files = json_decode($post['files']);
|
||||
if ($files[0]->file == 'deleted') continue;
|
||||
$post['file'] = $config['uri_thumb'] . $files[0]->thumb;
|
||||
$recent_posts[] = $post;
|
||||
}
|
||||
|
||||
|
@ -42,7 +42,7 @@
|
||||
foreach ($boards as &$_board) {
|
||||
if (in_array($_board['uri'], $this->excluded))
|
||||
continue;
|
||||
$query .= sprintf("SELECT *, '%s' AS `board` FROM ``posts_%s`` WHERE `file` IS NOT NULL AND `file` != 'deleted' AND `thumb` != 'spoiler' UNION ALL ", $_board['uri'], $_board['uri']);
|
||||
$query .= sprintf("SELECT *, '%s' AS `board` FROM ``posts_%s`` WHERE `files` IS NOT NULL UNION ALL ", $_board['uri'], $_board['uri']);
|
||||
}
|
||||
$query = preg_replace('/UNION ALL $/', 'ORDER BY `time` DESC LIMIT ' . (int)$settings['limit_images'], $query);
|
||||
|
||||
@ -54,10 +54,14 @@
|
||||
|
||||
while ($post = $query->fetch(PDO::FETCH_ASSOC)) {
|
||||
openBoard($post['board']);
|
||||
if (isset($post['files']))
|
||||
$files = json_decode($post['files']);
|
||||
|
||||
if ($files[0]->file == 'deleted') continue;
|
||||
|
||||
// board settings won't be available in the template file, so generate links now
|
||||
$post['link'] = $config['root'] . $board['dir'] . $config['dir']['res'] . sprintf($config['file_page'], ($post['thread'] ? $post['thread'] : $post['id'])) . '#' . $post['id'];
|
||||
$post['src'] = $config['uri_thumb'] . $post['thumb'];
|
||||
if ($files) $post['src'] = $config['uri_thumb'] . $files[0]->thumb;
|
||||
|
||||
$recent_images[] = $post;
|
||||
}
|
||||
@ -105,7 +109,7 @@
|
||||
$stats['unique_posters'] = number_format($query->fetchColumn());
|
||||
|
||||
// Active content
|
||||
$query = 'SELECT SUM(`filesize`) FROM (';
|
||||
/*$query = 'SELECT SUM(`filesize`) FROM (';
|
||||
foreach ($boards as &$_board) {
|
||||
if (in_array($_board['uri'], $this->excluded))
|
||||
continue;
|
||||
@ -113,7 +117,7 @@
|
||||
}
|
||||
$query = preg_replace('/UNION ALL $/', ') AS `posts_all`', $query);
|
||||
$query = query($query) or error(db_error());
|
||||
$stats['active_content'] = $query->fetchColumn();
|
||||
$stats['active_content'] = $query->fetchColumn();*/
|
||||
|
||||
return Element('themes/recent/recent.html', Array(
|
||||
'settings' => $settings,
|
||||
|
@ -51,14 +51,14 @@
|
||||
|
||||
$num_images = 0;
|
||||
while ($po = $posts->fetch()) {
|
||||
if ($po['file'])
|
||||
if ($po['files'])
|
||||
$num_images++;
|
||||
|
||||
$thread->add(new Post($po, $mod ? '?/' : $config['root'], $mod));
|
||||
|
||||
}
|
||||
if ($posts->rowCount() == ($post['sticky'] ? $config['threads_preview_sticky'] : $config['threads_preview'])) {
|
||||
$ct = prepare(sprintf("SELECT COUNT(`id`) as `num` FROM ``posts_%s`` WHERE `thread` = :thread UNION ALL SELECT COUNT(`id`) FROM ``posts_%s`` WHERE `file` IS NOT NULL AND `thread` = :thread", $post['board'], $post['board']));
|
||||
$ct = prepare(sprintf("SELECT COUNT(`id`) as `num` FROM ``posts_%s`` WHERE `thread` = :thread UNION ALL SELECT COUNT(`id`) FROM ``posts_%s`` WHERE `files` IS NOT NULL AND `thread` = :thread", $post['board'], $post['board']));
|
||||
$ct->bindValue(':thread', $post['id'], PDO::PARAM_INT);
|
||||
$ct->execute() or error(db_error($count));
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user