Add embedding support (YT, Vimeo, SoundCloud) and make links in messages clickable
This commit is contained in:
parent
5c0f55681c
commit
b721aac519
8 changed files with 183 additions and 39 deletions
|
@ -14,6 +14,7 @@ For demos see the [TinyIB Installations](https://github.com/tslocum/TinyIB/wiki)
|
|||
Features
|
||||
------------
|
||||
- GIF, JPG, PNG, SWF and WebA/WebM upload.
|
||||
- YouTube, Vimeo and SoundCloud embedding.
|
||||
- CAPTCHA.
|
||||
- Reference links >>###
|
||||
- Delete post via password.
|
||||
|
|
61
imgboard.php
61
imgboard.php
|
@ -89,12 +89,53 @@ if (isset($_POST['message']) || isset($_POST['file'])) {
|
|||
$post['message'] = $_POST['message']; // Treat message as raw HTML
|
||||
} else {
|
||||
$rawposttext = '';
|
||||
$post['message'] = str_replace("\n", '<br>', colorQuote(postLink(cleanString(rtrim($_POST['message'])))));
|
||||
$post['message'] = str_replace("\n", '<br>', makeLinksClickable(colorQuote(postLink(cleanString(rtrim($_POST['message']))))));
|
||||
}
|
||||
$post['password'] = ($_POST['password'] != '') ? md5(md5($_POST['password'])) : '';
|
||||
$post['nameblock'] = nameBlock($post['name'], $post['tripcode'], $post['email'], time(), $rawposttext);
|
||||
|
||||
if (isset($_FILES['file'])) {
|
||||
if (isset($_POST['embed']) && trim($_POST['embed']) != '') {
|
||||
list($service, $embed) = getEmbed(trim($_POST['embed']));
|
||||
if (empty($embed) || !isset($embed['html']) || !isset($embed['title']) || !isset($embed['thumbnail_url'])) {
|
||||
fancyDie("Invalid embed URL. Only YouTube, Vimeo, and SoundCloud URLs are supported.");
|
||||
}
|
||||
|
||||
$post['file_hex'] = $service;
|
||||
$temp_file = time() . substr(microtime(), 2, 3) . '.tmp';
|
||||
$file_location = "thumb/" . $temp_file;
|
||||
file_put_contents($file_location, file_get_contents($embed['thumbnail_url']));
|
||||
|
||||
$file_info = getimagesize($file_location);
|
||||
$file_mime = $file_info['mime'];
|
||||
$post['image_width'] = $file_info[0];
|
||||
$post['image_height'] = $file_info[1];
|
||||
|
||||
if ($file_mime == "image/jpeg") {
|
||||
$post['thumb'] = $temp_file . '.jpg';
|
||||
} else if ($file_mime == "image/gif") {
|
||||
$post['thumb'] = $temp_file . '.gif';
|
||||
} else if ($file_mime == "image/png") {
|
||||
$post['thumb'] = $temp_file . '.png';
|
||||
} else {
|
||||
fancyDie("Error while processing audio/video.");
|
||||
}
|
||||
$thumb_location = "thumb/" . $post['thumb'];
|
||||
|
||||
list($thumb_maxwidth, $thumb_maxheight) = thumbnailDimensions($post);
|
||||
|
||||
if (!createThumbnail($file_location, $thumb_location, $thumb_maxwidth, $thumb_maxheight)) {
|
||||
fancyDie("Could not create thumbnail.");
|
||||
}
|
||||
|
||||
addVideoOverlay($thumb_location);
|
||||
|
||||
$thumb_info = getimagesize($thumb_location);
|
||||
$post['thumb_width'] = $thumb_info[0];
|
||||
$post['thumb_height'] = $thumb_info[1];
|
||||
|
||||
$post['file_original'] = cleanString($embed['title']);
|
||||
$post['file'] = str_ireplace(array('src="https://', 'src="http://'), 'src="//', $embed['html']);
|
||||
} else if (isset($_FILES['file'])) {
|
||||
if ($_FILES['file']['name'] != "") {
|
||||
validateFileUpload();
|
||||
|
||||
|
@ -233,11 +274,21 @@ if (isset($_POST['message']) || isset($_POST['file'])) {
|
|||
}
|
||||
|
||||
if ($post['file'] == '') { // No file uploaded
|
||||
if ($post['parent'] == TINYIB_NEWTHREAD && (TINYIB_PIC || TINYIB_SWF || TINYIB_WEBM) && !TINYIB_NOFILEOK) {
|
||||
fancyDie("A file is required to start a thread.");
|
||||
$allowed = "";
|
||||
if (TINYIB_PIC || TINYIB_SWF || TINYIB_WEBM) {
|
||||
$allowed = "file";
|
||||
}
|
||||
if (TINYIB_EMBED) {
|
||||
if ($allowed != "") {
|
||||
$allowed .= " or ";
|
||||
}
|
||||
$allowed .= "embed URL";
|
||||
}
|
||||
if ($post['parent'] == TINYIB_NEWTHREAD && $allowed != "" && !TINYIB_NOFILEOK) {
|
||||
fancyDie("A $allowed is required to start a thread.");
|
||||
}
|
||||
if (str_replace('<br>', '', $post['message']) == "") {
|
||||
fancyDie("Please enter a message" . ((TINYIB_PIC || TINYIB_SWF || TINYIB_WEBM) ? " and/or upload a file" : "") . ".");
|
||||
fancyDie("Please enter a message" . ($allowed != "" ? " and/or upload a $allowed" : "") . ".");
|
||||
}
|
||||
} else {
|
||||
echo $post['file_original'] . ' uploaded.<br>';
|
||||
|
|
|
@ -27,6 +27,9 @@ if (!defined('TINYIB_SWF')) {
|
|||
if (!defined('TINYIB_WEBM')) {
|
||||
define('TINYIB_WEBM', false);
|
||||
}
|
||||
if (!defined('TINYIB_EMBED')) {
|
||||
define('TINYIB_EMBED', false);
|
||||
}
|
||||
if (!defined('TINYIB_THUMBNAIL')) {
|
||||
define('TINYIB_THUMBNAIL', 'gd');
|
||||
}
|
||||
|
|
|
@ -213,7 +213,7 @@ function colorQuote($message) {
|
|||
}
|
||||
|
||||
function deletePostImages($post) {
|
||||
if ($post['file'] != '') {
|
||||
if ($post['file_hex'] != 'YouTube' && $post['file_hex'] != 'Vimeo' && $post['file_hex'] != 'SoundCloud' && $post['file'] != '') {
|
||||
@unlink('src/' . $post['file']);
|
||||
}
|
||||
if ($post['thumb'] != '') {
|
||||
|
@ -499,3 +499,19 @@ function strallpos($haystack, $needle, $offset = 0) {
|
|||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
function getEmbed($url) {
|
||||
$services = array('YouTube' => "http://www.youtube.com/oembed?url=" . urlencode($url) . "&format=json", 'Vimeo' => "http://vimeo.com/api/oembed.json?url=" . urlencode($url), 'SoundCloud' => "http://soundcloud.com/oembed?format=json&url=" . $url);
|
||||
foreach ($services as $service => $service_url) {
|
||||
$curl = curl_init($service_url);
|
||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
|
||||
$return = curl_exec($curl);
|
||||
curl_close($curl);
|
||||
$result = json_decode($return, true);
|
||||
if (!empty($result)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return array($service, $result);
|
||||
}
|
||||
|
|
72
inc/html.php
72
inc/html.php
|
@ -22,6 +22,7 @@ EOF;
|
|||
<link rel="stylesheet" type="text/css" href="css/global.css">
|
||||
<link rel="stylesheet" type="text/css" href="css/futaba.css" title="Futaba">
|
||||
<link rel="alternate stylesheet" type="text/css" href="css/burichan.css" title="Burichan">
|
||||
<script src="js/jquery.js"></script>
|
||||
<script src="js/tinyib.js"></script>
|
||||
</head>
|
||||
EOF;
|
||||
|
@ -71,6 +72,15 @@ function supportedFileTypes() {
|
|||
return $types_formatted;
|
||||
}
|
||||
|
||||
function makeLinksClickable($text) {
|
||||
$text = preg_replace('!(((f|ht)tp(s)?://)[-a-zA-Zа-яА-Я()0-9@:%\!_+.,~#?&;//=]+)!i', '<a href="$1" target="_blank">$1</a>', $text);
|
||||
$text = preg_replace('/\(\<a href\=\"(.*)\)"\ target\=\"\_blank\">(.*)\)\<\/a>/i', '(<a href="$1" target="_blank">$2</a>)', $text);
|
||||
$text = preg_replace('/\<a href\=\"(.*)\."\ target\=\"\_blank\">(.*)\.\<\/a>/i', '<a href="$1" target="_blank">$2</a>.', $text);
|
||||
$text = preg_replace('/\<a href\=\"(.*)\,"\ target\=\"\_blank\">(.*)\,\<\/a>/i', '<a href="$1" target="_blank">$2</a>,', $text);
|
||||
|
||||
return $text;
|
||||
}
|
||||
|
||||
function buildPost($post, $res) {
|
||||
$return = "";
|
||||
$threadid = ($post['parent'] == TINYIB_NEWTHREAD) ? $post['id'] : $post['parent'];
|
||||
|
@ -85,6 +95,11 @@ function buildPost($post, $res) {
|
|||
$post["omitted"] = 0;
|
||||
}
|
||||
|
||||
$embed = '';
|
||||
if ($post["file_hex"] == "YouTube" || $post["file_hex"] == "Vimeo" || $post["file_hex"] == "SoundCloud") {
|
||||
$embed = str_replace("'", "\'", $post['file']);
|
||||
}
|
||||
|
||||
if ($post["parent"] != TINYIB_NEWTHREAD) {
|
||||
$return .= <<<EOF
|
||||
<table>
|
||||
|
@ -95,6 +110,24 @@ function buildPost($post, $res) {
|
|||
</td>
|
||||
<td class="reply" id="reply${post["id"]}">
|
||||
EOF;
|
||||
} elseif ($embed != "") {
|
||||
$return .= <<<EOF
|
||||
<span class="filesize">Embed: <a href="#" id="tiembed${post['id']}">${post["file_original"]}</a>–(${post["file_hex"]})</span>
|
||||
<br>
|
||||
<span id="thumbembed${post['id']}">
|
||||
<a href="#" id="exembed${post['id']}">
|
||||
<img src="thumb/${post["thumb"]}" alt="${post["id"]}" class="thumb opthumb" id="thumbnail${post['id']}" width="${post["thumb_width"]}" height="${post["thumb_height"]}">
|
||||
</a>
|
||||
</span>
|
||||
<div id="embed${post['id']}" class="thumb" style="display: none;"></div>
|
||||
<script type="text/javascript">
|
||||
$("#tiembed${post['id']}, #exembed${post['id']}").click(function(){
|
||||
showEmbed('${post['id']}', '$embed');
|
||||
return false;
|
||||
});
|
||||
</script>
|
||||
EOF;
|
||||
|
||||
} elseif ($post["file"] != "") {
|
||||
$return .= <<<EOF
|
||||
<span class="filesize">File: <a href="src/${post["file"]}">${post["file"]}</a>–(${post["file_size_formatted"]}, ${post["image_width"]}x${post["image_height"]}, ${post["file_original"]})</span>
|
||||
|
@ -123,8 +156,27 @@ ${post["nameblock"]}
|
|||
</span>
|
||||
EOF;
|
||||
|
||||
if ($post['parent'] != TINYIB_NEWTHREAD && $post["file"] != "") {
|
||||
$return .= <<<EOF
|
||||
if ($post['parent'] != TINYIB_NEWTHREAD) {
|
||||
if ($embed != "") {
|
||||
$return .= <<<EOF
|
||||
<br>
|
||||
<span class="filesize"><a href="#" id="tiembed${post['id']}">${post['file_original']}</a>–(${post['file_hex']})</span>
|
||||
<br>
|
||||
<span id="thumbembed${post['id']}">
|
||||
<a href="#" id="exembed${post['id']}">
|
||||
<img src="thumb/${post["thumb"]}" alt="${post["id"]}" class="thumb" id="thumbnail${post['id']}" width="${post["thumb_width"]}" height="${post["thumb_height"]}">
|
||||
</a>
|
||||
</span>
|
||||
<div id="embed${post['id']}" class="thumb" style="display: none;"></div>
|
||||
<script type="text/javascript">
|
||||
$("#tiembed${post['id']}, #exembed${post['id']}").click(function(){
|
||||
showEmbed('${post['id']}', '$embed');
|
||||
return false;
|
||||
});
|
||||
</script>
|
||||
EOF;
|
||||
} else if ($post["file"] != "") {
|
||||
$return .= <<<EOF
|
||||
<br>
|
||||
<span class="filesize"><a href="src/${post["file"]}">${post["file"]}</a>–(${post["file_size_formatted"]}, ${post["image_width"]}x${post["image_height"]}, ${post["file_original"]})</span>
|
||||
<br>
|
||||
|
@ -132,6 +184,7 @@ EOF;
|
|||
<span id="thumb${post["id"]}"><img src="thumb/${post["thumb"]}" alt="${post["id"]}" class="thumb" width="${post["thumb_width"]}" height="${post["thumb_height"]}"></span>
|
||||
</a>
|
||||
EOF;
|
||||
}
|
||||
}
|
||||
|
||||
if ($post['parent'] == TINYIB_NEWTHREAD && $res == TINYIB_INDEXPAGE) {
|
||||
|
@ -212,6 +265,7 @@ EOF;
|
|||
$reqmod_html = '';
|
||||
$filetypes_html = '';
|
||||
$file_input_html = '';
|
||||
$embed_input_html = '';
|
||||
$unique_posts_html = '';
|
||||
|
||||
$captcha_html = '';
|
||||
|
@ -249,6 +303,19 @@ EOF;
|
|||
EOF;
|
||||
}
|
||||
|
||||
if (TINYIB_EMBED) {
|
||||
$embed_input_html = <<<EOF
|
||||
<tr>
|
||||
<td class="postblock">
|
||||
Embed
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" name="embed" size="28" accesskey="e"> (paste a YouTube URL)
|
||||
</td>
|
||||
</tr>
|
||||
EOF;
|
||||
}
|
||||
|
||||
if (TINYIB_REQMOD != 'disable') {
|
||||
$reqmod_html = '<li>All posts' . (TINYIB_REQMOD == 'files' ? ' with a file attached' : '') . ' will be moderated before being shown.</li>';
|
||||
}
|
||||
|
@ -315,6 +382,7 @@ EOF;
|
|||
</tr>
|
||||
$captcha_html
|
||||
$file_input_html
|
||||
$embed_input_html
|
||||
<tr>
|
||||
<td class="postblock">
|
||||
Password
|
||||
|
|
4
js/jquery.js
vendored
Normal file
4
js/jquery.js
vendored
Normal file
File diff suppressed because one or more lines are too long
60
js/tinyib.js
60
js/tinyib.js
|
@ -4,55 +4,55 @@ function getCookie(name) {
|
|||
if (parts.length == 2) return parts.pop().split(";").shift();
|
||||
}
|
||||
|
||||
function storePassword() {
|
||||
var newpostpassword = document.getElementById("newpostpassword");
|
||||
if (newpostpassword) {
|
||||
var expiration_date = new Date();
|
||||
expiration_date.setFullYear(expiration_date.getFullYear() + 7);
|
||||
document.cookie = "tinyib_password=" + encodeURIComponent(newpostpassword.value) + "; path=/; expires=" + expiration_date.toGMTString();
|
||||
}
|
||||
}
|
||||
|
||||
function quotePost(postID) {
|
||||
var message_element = document.getElementById("message");
|
||||
if (message_element) {
|
||||
message_element.focus();
|
||||
message_element.value += '>>' + postID + "\n";
|
||||
}
|
||||
$("#message").val('>>' + postID + "\n").focus();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function reloadCAPTCHA() {
|
||||
var captcha_element = document.getElementById("captcha");
|
||||
if (captcha_element) {
|
||||
captcha_element.focus();
|
||||
captcha_element.value = "";
|
||||
}
|
||||
|
||||
var captchaimg_element = document.getElementById("captchaimage");
|
||||
if (captchaimg_element) {
|
||||
captchaimg_element.src += "#new";
|
||||
}
|
||||
$("#captcha").val("").focus();
|
||||
$("#captchaimage").attr("src", $("#captchaimage").attr("src") + "#new")
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
var newpostpassword = document.getElementById("newpostpassword");
|
||||
function showEmbed(id, embedhtml){
|
||||
if($("#thumbembed"+ id).attr('expanded') != 'true') {
|
||||
$("#thumbembed"+ id).hide();
|
||||
$("#embed"+ id).show();
|
||||
$("#embed"+ id).html(embedhtml);
|
||||
$("#thumbembed"+ id).attr('expanded', 'true');
|
||||
}else{
|
||||
$("#embed"+ id).hide();
|
||||
$("#embed"+ id).html('');
|
||||
$("#thumbembed"+ id).show();
|
||||
$("#thumbembed"+ id).attr('expanded', 'false');
|
||||
}
|
||||
}
|
||||
|
||||
$(function() {
|
||||
var newpostpassword = $("#newpostpassword");
|
||||
if (newpostpassword) {
|
||||
newpostpassword.addEventListener("change", storePassword);
|
||||
newpostpassword.change(function () {
|
||||
var newpostpassword = $("#newpostpassword");
|
||||
if (newpostpassword) {
|
||||
var expiration_date = new Date();
|
||||
expiration_date.setFullYear(expiration_date.getFullYear() + 7);
|
||||
document.cookie = "tinyib_password=" + encodeURIComponent(newpostpassword.val()) + "; path=/; expires=" + expiration_date.toGMTString();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var password = getCookie("tinyib_password");
|
||||
if (password && password != "") {
|
||||
if (newpostpassword) {
|
||||
newpostpassword.value = password;
|
||||
newpostpassword.val(password);
|
||||
}
|
||||
|
||||
var deletepostpassword = document.getElementById("deletepostpassword");
|
||||
var deletepostpassword = $("#deletepostpassword");
|
||||
if (deletepostpassword) {
|
||||
deletepostpassword.value = password;
|
||||
deletepostpassword.val(password);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -29,10 +29,11 @@ define('TINYIB_DELAY', 30); // Delay (in seconds) between posts from t
|
|||
define('TINYIB_MAXTHREADS', 100); // Oldest threads are discarded when the thread count passes this limit [0 to disable]
|
||||
define('TINYIB_MAXREPLIES', 0); // Maximum replies before a thread stops bumping [0 to disable]
|
||||
|
||||
// File types
|
||||
// Upload types
|
||||
define('TINYIB_PIC', true); // Enable .jpg, .png and .gif image file upload
|
||||
define('TINYIB_SWF', false); // Enable .swf Flash file upload
|
||||
define('TINYIB_WEBM', false); // Enable .weba and .webm audio/video file upload (see README for instructions)
|
||||
define('TINYIB_EMBED', false); // Enable embedding (e.g. YouTube, Vimeo, SoundCloud)
|
||||
|
||||
// File control
|
||||
define('TINYIB_MAXKB', 2048); // Maximum file size in kilobytes [0 to disable]
|
||||
|
|
Loading…
Reference in a new issue