Add optional WebA and WebM support

This commit is contained in:
Trevor Slocum 2014-06-24 12:51:22 -07:00
parent 777800c696
commit 90a878f8ee
16 changed files with 860 additions and 705 deletions

1
.gitignore vendored
View File

@ -5,3 +5,4 @@ settings.php
.posts.lock
.project
.settings/
.idea/

View File

@ -5,10 +5,13 @@ TinyIB - A Lightweight and Efficient [Image Board](http://en.wikipedia.org/wiki/
**No database? No problem.** Store posts as text files for a portable set-up capable of running on virtually any PHP host.
For demos see [example installations](https://github.com/tslocum/TinyIB/wiki). [![githalytics.com alpha](https://cruel-carlota.pagodabox.com/5135372febbc40bacddbb13c1f0a8333 "githalytics.com")](http://githalytics.com/tslocum/TinyIB)
To allow new threads without requiring an image, see the [Text Board Mode](https://github.com/tslocum/TinyIB/wiki/Text-Board-Mode) page.
For demos see the [TinyIB Installations](https://github.com/tslocum/TinyIB/wiki) page. [![githalytics.com alpha](https://cruel-carlota.pagodabox.com/5135372febbc40bacddbb13c1f0a8333 "githalytics.com")](http://githalytics.com/tslocum/TinyIB)
Features
------------
- GIF, JPG, PNG and WebA/WebM upload.
- Reference links >>###
- Delete post via password.
- Management panel:
@ -30,6 +33,11 @@ Installing
- `git clone git://github.com/tslocum/TinyIB.git ./`
4. Copy **settings.default.php** to **settings.php**
5. Configure **settings.php**
- To allow WebA/WebM upload:
- Ensure your web host is running Linux.
- Install [mediainfo](http://mediaarea.net/en/MediaInfo). On Ubuntu, run ``sudo apt-get install mediainfo``.
- Set ``TINYIB_WEBM`` to ``true``.
- To remove the play icon from thumbnails, delete or rename **video_overlay.png**.
6. [CHMOD](http://en.wikipedia.org/wiki/Chmod) write permissions to these directories:
- ./ (the directory containing TinyIB)
- ./src/
@ -41,6 +49,15 @@ Installing
- Directories will be verified to be writable.
- The file index.html will be created containing the new image board.
Moderating
------------
1. If you are not logged in already, log in to the management panel by clicking **[Manage]**.
2. On the board, tick the checkbox next to the offending post.
3. Scroll to the bottom of the page.
4. Click **Delete** with the password field blank.
- From this page you are able to delete the post and/or ban the author.
Updating
------------

View File

@ -3,32 +3,39 @@ html, body {
background: #EEF2FF;
color: #000000;
}
a {
background: inherit;
color: #34345C;
text-decoration: none;
font-family: sans-serif;
}
a:visited {
background: inherit;
color: #34345C;
text-decoration: none;
font-family: sans-serif;
}
a:hover {
color: #DD0000;
background: inherit;
font-family: sans-serif;
}
.filesize a {
text-decoration: underline;
}
.filesize a:visited {
text-decoration: underline;
}
.adminbar {
background: inherit;
}
.logo {
clear: both;
text-align: center;
@ -37,58 +44,70 @@ a:hover {
color: #AF0A0F;
width: 100%;
}
.replymode {
background: #0010E0;
color: #FFFFFF;
width: 100%;
}
.manageinfo {
background: #00B930;
color: #FFFFFF;
width: 100%;
}
.catalogmode {
background: #0040E0;
color: #FFFFFF;
width: 100%;
}
.postarea {
background: inherit;
}
.rules {
/*font-size:0.7em;*/
width: 468px;
font-size: 10px;
font-family: sans-serif;
}
.rules li {
margin-left: 1em;
/*text-indent: 0em;*/
}
.postblock {
background: #9988EE;
color: #000000;
font-weight: 800;
}
.footer {
font-size: 10px;
font-family: sans-serif;
}
.passvalid {
background: #9988EE;
text-align: center;
width: 100%;
color: #ffffff;
}
.dellist {
background: inherit;
text-align: center;
}
.delbuttons {
background: inherit;
text-align: center;
padding-bottom: 4px;
}
.managehead {
background: #0F8FE1;
color: #000000;
@ -96,33 +115,39 @@ a:hover {
font-size: 14px;
padding: 0px;
}
.postlists {
background: #FFFFFF;
width: 100%;
padding: 0px;
color: #000000;
}
.row1 {
background: #9AD2F6;
font-family: sans-serif;
font-size: 12px;
color: #000000;
}
.row2 {
background: #FFFFFF;
font-family: sans-serif;
font-size: 12px;
color: #000000;
}
.unkfunc {
color: #789922;
}
.filesize {
font-size: 12px;
font-family: sans-serif;
text-decoration: underline;
/*padding-left:3em;*/
}
.filetitle {
background: inherit;
font-size: 18px;
@ -130,6 +155,7 @@ a:hover {
color: #0F0C5D;
font-weight: 800;
}
.postername {
background: inherit;
font-size: 12px;
@ -137,6 +163,7 @@ a:hover {
color: #117743;
font-weight: 800;
}
.oldpost {
background: inherit;
font-size: 18px;
@ -144,6 +171,7 @@ a:hover {
color: #0F0C5D;
font-weight: 800;
}
.omittedposts {
background: inherit;
font-size: 18px;
@ -151,15 +179,18 @@ a:hover {
color: #070707;
font-weight: 800;
}
.reply {
background: #D6DAF0;
color: #000000;
font-family: serif;
}
.replyhl {
background: #D6BAD0;
color: #000000;
}
.replytitle {
background: inherit;
font-size: 18px;
@ -167,6 +198,7 @@ a:hover {
color: #0F0C5D;
font-weight: 800;
}
.commentpostername {
background: inherit;
font-size: 12px;
@ -174,6 +206,7 @@ a:hover {
color: #117743;
font-weight: 800;
}
.thumbnailmsg {
background: inherit;
font-size: 9px;

View File

@ -2,15 +2,19 @@ html, body {
background: #FFFFEE;
color: #800000;
}
a {
color: #0000EE;
}
a:hover {
color: #DD0000;
}
.reflink a:hover {
font-weight: bold;
}
.logo {
clear: both;
text-align: center;
@ -18,6 +22,7 @@ a:hover {
color: #800000;
width: 100%;
}
.replymode {
background: #E04000;
text-align: center;
@ -25,6 +30,7 @@ a:hover {
color: #FFFFFF;
width: 100%;
}
.manageinfo {
background: #00B930;
text-align: center;
@ -32,6 +38,7 @@ a:hover {
color: #FFFFFF;
width: 100%;
}
.catalogmode {
background: #0040E0;
text-align: center;
@ -39,103 +46,126 @@ a:hover {
color: #FFFFFF;
width: 100%;
}
.rules {
/*font-size:0.7em;*/
width: 468px;
font-size: 10px;
font-family: sans-serif;
}
.rules li {
margin-left: 1em;
/*text-indent: 0em;*/
}
.postblock {
background: #EEAA88;
color: #800000;
font-weight: 800;
}
.footer {
font-size: 12px;
font-family: serif;
}
.passvalid {
background: #EEAA88;
text-align: center;
width: 100%;
color: #ffffff;
}
.dellist {
font-weight: bold;
text-align: center;
}
.delbuttons {
text-align: center;
padding-bottom: 4px;
}
.managehead {
background: #AAAA66;
color: #400000;
padding: 0px;
}
.postlists {
background: #FFFFFF;
width: 100%;
padding: 0px;
color: #800000;
}
.row1 {
background: #EEEECC;
color: #800000;
}
.row2 {
background: #DDDDAA;
color: #800000;
}
.unkfunc {
background: inherit;
color: #789922;
}
.filesize {
text-decoration: none;
}
.filetitle {
background: inherit;
font-size: 1.2em;
color: #CC1105;
font-weight: 800;
}
.postername {
color: #117743;
font-weight: bold;
}
.postertrip {
color: #228854;
}
.oldpost {
color: #CC1105;
font-weight: 800;
}
.omittedposts {
color: #707070;
}
.reply {
background: #F0E0D6;
color: #800000;
}
.replyhl {
background: #F0C0B0;
color: #800000;
}
.replytitle {
font-size: 1.2em;
color: #CC1105;
font-weight: 800;
}
.commentpostername {
color: #117743;
font-weight: 800;
}
.thumbnailmsg {
font-size: small;
color: #800000;
@ -144,6 +174,7 @@ a:hover {
.abbrev {
color: #707070;
}
.highlight {
background: #F0E0D6;
color: #800000;

View File

@ -118,4 +118,6 @@ form {
float: right;
}
.adminbar a:link, .adminbar a:visited, .adminbar a:active, .adminbar a:hover { text-decoration: none; }
.adminbar a:link, .adminbar a:visited, .adminbar a:active, .adminbar a:hover {
text-decoration: none;
}

View File

@ -10,10 +10,16 @@ ob_implicit_flush();
ob_end_flush();
if (get_magic_quotes_gpc()) {
foreach ($_GET as $key => $val) { $_GET[$key] = stripslashes($val); }
foreach ($_POST as $key => $val) { $_POST[$key] = stripslashes($val); }
foreach ($_GET as $key => $val) {
$_GET[$key] = stripslashes($val);
}
foreach ($_POST as $key => $val) {
$_POST[$key] = stripslashes($val);
}
}
if (get_magic_quotes_runtime()) {
set_magic_quotes_runtime(0);
}
if (get_magic_quotes_runtime()) { set_magic_quotes_runtime(0); }
function fancyDie($message) {
die('<body text="#800000" bgcolor="#FFFFEE" align="center"><br><div style="display: inline-block; background-color: #F0E0D6;font-size: 1.25em;font-family: Tahoma, Geneva, sans-serif;padding: 7px;border: 1px solid #D9BFB7;border-left: none;border-top: none;">' . $message . '</div><br><br>- <a href="javascript:history.go(-1)">Click here to go back</a> -</body>');
@ -26,7 +32,9 @@ require 'settings.php';
// Check directories are writable by the script
$writedirs = array("res", "src", "thumb");
if (TINYIB_DBMODE == 'flatfile') { $writedirs[] = "inc/flatfile"; }
if (TINYIB_DBMODE == 'flatfile') {
$writedirs[] = "inc/flatfile";
}
foreach ($writedirs as $dir) {
if (!is_writable($dir)) {
fancyDie("Directory '" . $dir . "' can not be written to. Please modify its permissions.");
@ -89,42 +97,114 @@ if (isset($_POST['message']) || isset($_POST['file'])) {
fancyDie("That file is larger than " . TINYIB_MAXKBDESC . ".");
}
$post['file_original'] = htmlentities(substr($_FILES['file']['name'], 0, 50), ENT_QUOTES);
$post['file_original'] = trim(htmlentities(substr($_FILES['file']['name'], 0, 50), ENT_QUOTES));
$post['file_hex'] = md5_file($_FILES['file']['tmp_name']);
$post['file_size'] = $_FILES['file']['size'];
$post['file_size_formatted'] = convertBytes($post['file_size']);
$file_type = strtolower(preg_replace('/.*(\..+)/', '\1', $_FILES['file']['name'])); if ($file_type == '.jpeg') { $file_type = '.jpg'; }
$file_type = strtolower(preg_replace('/.*(\..+)/', '\1', $_FILES['file']['name']));
if ($file_type == '.jpeg') {
$file_type = '.jpg';
}
if ($file_type == '.weba') {
$file_type = '.webm';
}
$file_name = time() . substr(microtime(), 2, 3);
$post['file'] = $file_name . $file_type;
$post['thumb'] = $file_name . "s" . $file_type;
$post['thumb'] = $file_name . "s" . ($file_type == '.webm' ? '.jpg' : $file_type);
$file_location = "src/" . $post['file'];
$thumb_location = "thumb/" . $post['thumb'];
if (!($file_type == '.jpg' || $file_type == '.gif' || $file_type == '.png')) {
fancyDie("Only GIF, JPG, and PNG files are allowed.");
}
if (!@getimagesize($_FILES['file']['tmp_name'])) {
fancyDie("Failed to read the size of the uploaded file. Please retry the submission.");
}
$file_info = getimagesize($_FILES['file']['tmp_name']);
$file_mime = $file_info['mime'];
if (!($file_mime == "image/jpeg" || $file_mime == "image/gif" || $file_mime == "image/png")) {
fancyDie("Only GIF, JPG, and PNG files are allowed.");
}
checkDuplicateImage($post['file_hex']);
checkDuplicateFile($post['file_hex']);
if (!move_uploaded_file($_FILES['file']['tmp_name'], $file_location)) {
fancyDie("Could not copy uploaded file.");
}
if ($file_type == '.webm') {
$file_mime_output = shell_exec('file --mime-type ' . $file_location);
$file_mime_split = explode(' ', $file_mime_output);
$file_mime = strtolower(trim(array_pop($file_mime_split)));
} else {
if (!@getimagesize($file_location)) {
@unlink($file_location);
fancyDie("Failed to read the size of the uploaded file. Please retry the submission.");
}
$file_info = getimagesize($file_location);
$file_mime = $file_info['mime'];
}
if (!($file_mime == "image/jpeg" || $file_mime == "image/gif" || $file_mime == "image/png" || (TINYIB_WEBM && ($file_mime == "video/webm" || $file_mime == "audio/webm")))) {
@unlink($file_location);
fancyDie("Only " . (TINYIB_WEBM ? "GIF, JPG, PNG, and WEBM" : "GIF, JPG, and PNG") . " files are allowed.");
}
if ($_FILES['file']['size'] != filesize($file_location)) {
@unlink($file_location);
fancyDie("File transfer failure. Please go back and try again.");
}
$post['image_width'] = $file_info[0]; $post['image_height'] = $file_info[1];
if ($file_mime == "audio/webm" || $file_mime == "video/webm") {
$post['image_width'] = intval(shell_exec('mediainfo --Inform="Video;%Width%" ' . $file_location));
$post['image_height'] = intval(shell_exec('mediainfo --Inform="Video;%Height%" ' . $file_location));
if ($post['image_width'] <= 0 || $post['image_height'] <= 0) {
$post['image_width'] = 0;
$post['image_height'] = 0;
$file_location_old = $file_location;
$file_location = substr($file_location, 0, -1) . 'a'; // replace webm with weba
rename($file_location_old, $file_location);
$post['file'] = substr($post['file'], 0, -1) . 'a'; // replace webm with weba
}
if ($file_mime == "video/webm") {
list($thumb_maxwidth, $thumb_maxheight) = thumbnailDimensions($post);
shell_exec("ffmpegthumbnailer -s " . max($thumb_maxwidth, $thumb_maxheight) . " -i $file_location -o $thumb_location") . '!';
$thumb_info = getimagesize($thumb_location);
$post['thumb_width'] = $thumb_info[0];
$post['thumb_height'] = $thumb_info[1];
if ($post['thumb_width'] <= 0 || $post['thumb_height'] <= 0) {
@unlink($file_location);
@unlink($thumb_location);
fancyDie("Sorry, your video appears to be corrupt.");
}
if (file_exists('video_overlay.png')) {
$thumbnail = imagecreatefromjpeg($thumb_location);
list($width, $height, $type, $attr) = getimagesize($thumb_location);
$overlay_play = imagecreatefrompng('video_overlay.png');
imagealphablending($overlay_play, false);
imagesavealpha($overlay_play, true);
list($overlay_width, $overlay_height, $overlay_type, $overlay_attr) = getimagesize('video_overlay.png');
$new_thumbnail = imagecreatetruecolor($width, $height);
imagecopyresampled($new_thumbnail, $thumbnail, 0, 0, 0, 0, $width, $height, $width, $height);
imagecopyresampled($new_thumbnail, $overlay_play, ($width / 2) - ($overlay_width / 2), ($height / 2) - ($overlay_height / 2), 0, 0, $overlay_width, $overlay_width, $overlay_width, $overlay_height);
imagejpeg($new_thumbnail, $thumb_location);
$thumb_info = getimagesize($thumb_location);
$post['thumb_width'] = $thumb_info[0];
$post['thumb_height'] = $thumb_info[1];
}
}
$duration = intval(shell_exec('mediainfo --Inform="' . ($file_mime == 'video/webm' ? 'Video' : 'Audio') . ';%Duration%" ' . $file_location));
$mins = floor(round($duration / 1000) / 60);
$secs = str_pad(floor(round($duration / 1000) % 60), 2, "0", STR_PAD_LEFT);
$post['file_original'] = "$mins:$secs" . ($post['file_original'] != '' ? (', ' . $post['file_original']) : '');
} else {
$file_info = getimagesize($file_location);
$post['image_width'] = $file_info[0];
$post['image_height'] = $file_info[1];
list($thumb_maxwidth, $thumb_maxheight) = thumbnailDimensions($post);
@ -133,7 +213,9 @@ if (isset($_POST['message']) || isset($_POST['file'])) {
}
$thumb_info = getimagesize($thumb_location);
$post['thumb_width'] = $thumb_info[0]; $post['thumb_height'] = $thumb_info[1];
$post['thumb_width'] = $thumb_info[0];
$post['thumb_height'] = $thumb_info[1];
}
}
}
@ -172,7 +254,9 @@ if (isset($_POST['message']) || isset($_POST['file'])) {
rebuildIndexes();
// Check if the request is to delete a post and/or its associated image
} elseif (isset($_GET['delete']) && !isset($_GET['manage'])) {
if (!isset($_POST['delete'])) { fancyDie('Tick the box next to a post and click "Delete" to delete it.'); }
if (!isset($_POST['delete'])) {
fancyDie('Tick the box next to a post and click "Delete" to delete it.');
}
$post = postByID($_POST['delete']);
if ($post) {
@ -183,7 +267,11 @@ if (isset($_POST['message']) || isset($_POST['file'])) {
echo '--&gt; --&gt; --&gt;<meta http-equiv="refresh" content="0;url=' . basename($_SERVER['PHP_SELF']) . '?manage&moderate=' . $_POST['delete'] . '">';
} elseif ($post['password'] != '' && md5(md5($_POST['password'])) == $post['password']) {
deletePostByID($post['id']);
if ($post['parent'] == TINYIB_NEWTHREAD) { threadUpdated($post['id']); } else { threadUpdated($post['parent']); }
if ($post['parent'] == TINYIB_NEWTHREAD) {
threadUpdated($post['id']);
} else {
threadUpdated($post['parent']);
}
fancyDie('Post deleted.');
} else {
fancyDie('Invalid password.');
@ -195,8 +283,12 @@ if (isset($_POST['message']) || isset($_POST['file'])) {
$redirect = false;
// Check if the request is to access the management area
} elseif (isset($_GET['manage'])) {
$text = ''; $onload = ''; $navbar = '&nbsp;';
$redirect = false; $loggedin = false; $isadmin = false;
$text = '';
$onload = '';
$navbar = '&nbsp;';
$redirect = false;
$loggedin = false;
$isadmin = false;
$returnlink = basename($_SERVER['PHP_SELF']);
list($loggedin, $isadmin) = manageCheckLogIn();
@ -303,5 +395,3 @@ if (isset($_POST['message']) || isset($_POST['file'])) {
if ($redirect) {
echo '--&gt; --&gt; --&gt;<meta http-equiv="refresh" content="0;url=' . (is_string($redirect) ? $redirect : 'index.html') . '">';
}
?>

View File

@ -1,5 +1,7 @@
<?php
if (!defined('TINYIB_BOARD')) { die(''); }
if (!defined('TINYIB_BOARD')) {
die('');
}
# Post Structure
define('POSTS_FILE', '.posts');
@ -130,7 +132,9 @@ function convertPostsToSQLStyle($posts, $singlepost=false) {
$post['parent'] = TINYIB_NEWTHREAD;
}
if ($singlepost) { return $post; }
if ($singlepost) {
return $post;
}
$newposts[] = $post;
}
return $newposts;
@ -226,7 +230,9 @@ function convertBansToSQLStyle($bans, $singleban=false) {
$ban['expire'] = $oldban[BAN_EXPIRE];
$ban['reason'] = $oldban[BAN_REASON];
if ($singleban) { return $ban; }
if ($singleban) {
return $ban;
}
$newbans[] = $ban;
}
return $newbans;
@ -257,5 +263,3 @@ function clearExpiredBans() {
function deleteBanByID($id) {
$GLOBALS['db']->deleteWhere(BANS_FILE, new SimpleWhereClause(BAN_ID, '=', $id, INTEGER_COMPARISON));
}
?>

View File

@ -1,5 +1,7 @@
<?php
if (!defined('TINYIB_BOARD')) { die(''); }
if (!defined('TINYIB_BOARD')) {
die('');
}
if (!function_exists('mysql_connect')) {
fancyDie("MySQL library is not installed");
@ -224,5 +226,3 @@ function clearExpiredBans() {
function deleteBanByID($id) {
mysql_query("DELETE FROM `" . TINYIB_DBBANS . "` WHERE `id` = " . mysql_real_escape_string($id) . " LIMIT 1");
}
?>

View File

@ -1,5 +1,7 @@
<?php
if (!defined('TINYIB_BOARD')) { die(''); }
if (!defined('TINYIB_BOARD')) {
die('');
}
if (!function_exists('sqlite_open')) {
fancyDie("SQLite library is not installed");
@ -193,5 +195,3 @@ function clearExpiredBans() {
function deleteBanByID($id) {
sqlite_query($GLOBALS["db"], "DELETE FROM " . TINYIB_DBBANS . " WHERE id = " . sqlite_escape_string($id));
}
?>

View File

@ -1,5 +1,7 @@
<?php
if (!defined('TINYIB_BOARD')) { die(''); }
if (!defined('TINYIB_BOARD')) {
die('');
}
define('TINYIB_NEWTHREAD', '0');
define('TINYIB_INDEXPAGE', false);
@ -7,7 +9,15 @@ define('TINYIB_RESPAGE', true);
// The following are provided for backward compatibility and should not be relied upon
// Copy new settings from settings.default.php to settings.php
if (!defined('TINYIB_MAXREPLIES')) { define('TINYIB_MAXREPLIES', 0); }
if (!defined('TINYIB_MAXWOP')) { define('TINYIB_MAXWOP', TINYIB_MAXW); }
if (!defined('TINYIB_MAXHOP')) { define('TINYIB_MAXHOP', TINYIB_MAXH); }
?>
if (!defined('TINYIB_MAXREPLIES')) {
define('TINYIB_MAXREPLIES', 0);
}
if (!defined('TINYIB_MAXWOP')) {
define('TINYIB_MAXWOP', TINYIB_MAXW);
}
if (!defined('TINYIB_MAXHOP')) {
define('TINYIB_MAXHOP', TINYIB_MAXH);
}
if (!defined('TINYIB_WEBM')) {
define('TINYIB_WEBM', false);
}

View File

@ -50,8 +50,7 @@ $comparison_type_for_col_type = array(
FLOAT_COL => NUMERIC_COMPARISON
);
function get_comparison_type_for_col_type($coltype)
{
function get_comparison_type_for_col_type($coltype) {
global $comparison_type_for_col_type;
return $comparison_type_for_col_type[$coltype];
}
@ -77,8 +76,7 @@ class Flatfile {
*/
var $datadir;
function Flatfile()
{
function Flatfile() {
$this->schemata = array();
}
@ -174,8 +172,7 @@ class Flatfile {
/** Get a lock for writing a file
* @access private
*/
function getLock ($tablename)
{
function getLock($tablename) {
ignore_user_abort(true);
$fp = fopen($this->datadir . $tablename . '.lock', 'w');
if (!flock($fp, LOCK_EX)) {
@ -188,8 +185,7 @@ class Flatfile {
/** Release a lock
* @access private
*/
function releaseLock ($lockfp)
{
function releaseLock($lockfp) {
flock($lockfp, LOCK_UN);
ignore_user_abort(false);
}
@ -206,8 +202,7 @@ class Flatfile {
* @param array $newRow The new row to add to the table
* @return int The newly assigned ID
*/
function insertWithAutoId ($tablename, $idField, $newRow)
{
function insertWithAutoId($tablename, $idField, $newRow) {
$lockfp = $this->getLock($tablename);
$rows = $this->selectWhere($tablename, null, 1,
new OrderBy($idField, DESCENDING, INTEGER_COMPARISON));
@ -229,8 +224,7 @@ class Flatfile {
* @param string $tablename The table to insert data into
* @param array $newRow The new row to add to the table
*/
function insert ($tablename, $newRow)
{
function insert($tablename, $newRow) {
$lockfp = $this->getLock($tablename);
$this->tables[$tablename][] = $newRow;
$this->writeTable($tablename);
@ -244,8 +238,7 @@ class Flatfile {
* @param int $idField The index of the field which is the ID field
* @param array $updatedRow The updated row to add to the table
*/
function updateRowById ($tablename, $idField, $updatedRow)
{
function updateRowById($tablename, $idField, $updatedRow) {
$this->updateSetWhere($tablename, $updatedRow,
new SimpleWhereClause($idField, '=', $updatedRow[$idField]));
}
@ -261,15 +254,14 @@ class Flatfile {
* @param array $newFields A hashtable (with integer keys) of fields to update
* @param WhereClause $whereClause The criteria or NULL to update all rows
*/
function updateSetWhere ($tablename, $newFields, $whereClause)
{
function updateSetWhere($tablename, $newFields, $whereClause) {
$schema = $this->getSchema($tablename);
$lockfp = $this->getLock($tablename);
for ($i = 0; $i < count($this->tables[$tablename]); ++$i) {
if ($whereClause === NULL ||
$whereClause->testRow($this->tables[$tablename][$i], $schema)) {
foreach ($newFields as $k => $v)
{
$whereClause->testRow($this->tables[$tablename][$i], $schema)
) {
foreach ($newFields as $k => $v) {
$this->tables[$tablename][$i][$k] = $v;
}
}
@ -278,6 +270,7 @@ class Flatfile {
$this->releaseLock($lockfp);
$this->loadTable($tablename);
}
/**
* Deletes all rows in a table that match specified criteria
*
@ -290,7 +283,8 @@ class Flatfile {
$lockfp = $this->getLock($tablename);
for ($i = count($this->tables[$tablename]) - 1; $i >= 0; --$i) {
if ($whereClause === NULL ||
$whereClause->testRow($this->tables[$tablename][$i], $schema)) {
$whereClause->testRow($this->tables[$tablename][$i], $schema)
) {
unset($this->tables[$tablename][$i]);
}
}
@ -316,8 +310,7 @@ class Flatfile {
* @param mixed $orderBy Either an OrderBy object or an array of them
* @return string function name
*/
function getOrderByFunction ($orderBy, $rowSchema = null)
{
function getOrderByFunction($orderBy, $rowSchema = null) {
$orderer = new Orderer($orderBy, $rowSchema);
return array(&$orderer, 'compare');
}
@ -364,19 +357,15 @@ class Flatfile {
* @param string $rowSchema An array specifying the column types for data
* files that match the regex, using constants defined in flatfile_utils.php
*/
function addSchema($fileregex, $rowSchema)
{
function addSchema($fileregex, $rowSchema) {
array_push($this->schemata, array($fileregex, $rowSchema));
}
/** Retrieves the schema for a given filename */
function getSchema($filename)
{
foreach ($this->schemata as $rowSchemaPair)
{
function getSchema($filename) {
foreach ($this->schemata as $rowSchemaPair) {
$fileregex = $rowSchemaPair[0];
if (preg_match($fileregex, $filename))
{
if (preg_match($fileregex, $filename)) {
return $rowSchemaPair[1];
}
}
@ -385,21 +374,20 @@ class Flatfile {
}
/////////////////////////// UTILITY FUNCTIONS ////////////////////////////////////
/**
* equivalent of strcmp for comparing integers, used internally for sorting and comparing
*/
function intcmp ($a, $b)
{
function intcmp($a, $b) {
return (int)$a - (int)$b;
}
/**
* equivalent of strcmp for comparing floats, used internally for sorting and comparing
*/
function numcmp ($a, $b)
{
function numcmp($a, $b) {
return (float)$a - (float)$b;
}
@ -411,8 +399,7 @@ function numcmp ($a, $b)
* @abstract
* @package flatfile
*/
class WhereClause
{
class WhereClause {
/**
* Tests a table row object
* @abstract
@ -421,15 +408,15 @@ class WhereClause
* @return bool True if the $row passes the WhereClause
* selection criteria, false otherwise
*/
function testRow ($row, $rowSchema = null) {}
function testRow($row, $rowSchema = null) {
}
}
/**
* Negates a where clause
* @package flatfile
*/
class NotWhere extends WhereClause
{
class NotWhere extends WhereClause {
/** @access private */
var $clause;
@ -440,8 +427,7 @@ class NotWhere extends WhereClause
* of the WhereClause object passed in when testing rows.
* @param WhereClause $whereclause The WhereClause object to negate
*/
function NotWhere ($whereclause)
{
function NotWhere($whereclause) {
$this->clause = $whereclause;
}
@ -456,8 +442,7 @@ class NotWhere extends WhereClause
*
* @package flatfile
*/
class SimpleWhereClause extends WhereClause
{
class SimpleWhereClause extends WhereClause {
/**#@+
* @access private
*/
@ -494,8 +479,7 @@ class SimpleWhereClause extends WhereClause
* STRING_COMPARISON (default), NUMERIC COMPARISON or INTEGER_COMPARISON
*
*/
function SimpleWhereClause ($field, $operator, $value, $compare_type = DEFAULT_COMPARISON)
{
function SimpleWhereClause($field, $operator, $value, $compare_type = DEFAULT_COMPARISON) {
$this->field = $field;
$this->operator = $operator;
$this->value = $value;
@ -507,14 +491,10 @@ class SimpleWhereClause extends WhereClause
return TRUE;
$cmpfunc = $this->compare_type;
if ($cmpfunc == DEFAULT_COMPARISON)
{
if ($rowSchema != null)
{
if ($cmpfunc == DEFAULT_COMPARISON) {
if ($rowSchema != null) {
$cmpfunc = get_comparison_type_for_col_type($rowSchema[$this->field]);
}
else
{
} else {
$cmpfunc = STRING_COMPARISON;
}
}
@ -546,8 +526,7 @@ class SimpleWhereClause extends WhereClause
* {@link WhereClause WhereClause} class to work like a SQL 'LIKE' clause
* @package flatfile
*/
class LikeWhereClause extends WhereClause
{
class LikeWhereClause extends WhereClause {
/**
* Creates a new LikeWhereClause
*
@ -556,8 +535,7 @@ class LikeWhereClause extends WhereClause
* wildcard, and is case insensitve. e.g. 'test%' will match 'TESTS' and 'Testing'
*/
function LikeWhereClause ($field, $value)
{
function LikeWhereClause($field, $value) {
$this->field = $field;
$this->regexp = '/^' . str_replace('%', '.*', preg_quote($value)) . '$/i';
}
@ -599,20 +577,15 @@ class ListWhereClause extends WhereClause {
function testRow($tablerow, $rowSchema = null) {
$func = $this->compareAs;
if ($func == DEFAULT_COMPARISON)
{
if ($rowSchema)
{
if ($func == DEFAULT_COMPARISON) {
if ($rowSchema) {
$func = get_comparison_type_for_col_type($rowSchema[$this->field]);
}
else
{
} else {
$func = STRING_COMPARISON;
}
}
foreach ($this->list as $item)
{
foreach ($this->list as $item) {
if ($func($tablerow[$this->field], $item) == 0)
return true;
}
@ -625,8 +598,7 @@ class ListWhereClause extends WhereClause {
* together.
* @package flatfile
*/
class CompositeWhereClause extends WhereClause
{
class CompositeWhereClause extends WhereClause {
/**
* @var array Stores the child clauses
* @access protected
@ -637,8 +609,7 @@ class CompositeWhereClause extends WhereClause
* Add a {@link WhereClause WhereClause} to the list of clauses to be used for testing
* @param WhereClause $whereClause The WhereClause object to add
*/
function add ($whereClause)
{
function add($whereClause) {
$this->clauses[] = $whereClause;
}
}
@ -654,8 +625,7 @@ class CompositeWhereClause extends WhereClause
* false if no clauses have been added for consistency).
* @package flatfile
*/
class OrWhereClause extends CompositeWhereClause
{
class OrWhereClause extends CompositeWhereClause {
function testRow($tablerow, $rowSchema = null) {
foreach ($this->clauses as $clause) {
if ($clause->testRow($tablerow, $rowSchema))
@ -683,8 +653,7 @@ class OrWhereClause extends CompositeWhereClause
* true if no clauses have been added for consistency).
* @package flatfile
*/
class AndWhereClause extends CompositeWhereClause
{
class AndWhereClause extends CompositeWhereClause {
function testRow($tablerow, $rowSchema = null) {
foreach ($this->clauses as $clause) {
if (!$clause->testRow($tablerow, $rowSchema))
@ -731,8 +700,7 @@ class OrderBy {
* @param int $compareAs Comparison type: DEFAULT_COMPARISON, STRING_COMPARISON, INTEGER_COMPARISION,
* or NUMERIC_COMPARISON, or the name of a user defined function that you want to use for doing the comparison.
*/
function OrderBy($field, $orderType, $compareAs = DEFAULT_COMPARISON)
{
function OrderBy($field, $orderType, $compareAs = DEFAULT_COMPARISON) {
$this->field = $field;
$this->orderType = $orderType;
$this->compareAs = $compareAs;
@ -760,14 +728,11 @@ class Orderer {
function Orderer($orderBy, $rowSchema = null) {
if (!is_array($orderBy))
$orderBy = array($orderBy);
if ($rowSchema)
{
if ($rowSchema) {
// Fix the comparison types
foreach ($orderBy as $index => $discard)
{
foreach ($orderBy as $index => $discard) {
$item =& $orderBy[$index]; // PHP4
if ($item->compareAs == DEFAULT_COMPARISON)
{
if ($item->compareAs == DEFAULT_COMPARISON) {
$item->compareAs = get_comparison_type_for_col_type($rowSchema[$item->field]);
}
}
@ -786,12 +751,10 @@ class Orderer {
/**
* @access private
*/
function compare_priv($row1, $row2, $index)
{
function compare_priv($row1, $row2, $index) {
$orderBy = $this->orderByList[$index];
$cmpfunc = $orderBy->compareAs;
if ($cmpfunc == DEFAULT_COMPARISON)
{
if ($cmpfunc == DEFAULT_COMPARISON) {
$cmpfunc = STRING_COMPARISON;
}
$cmp = $orderBy->orderType * $cmpfunc($row1[$orderBy->field], $row2[$orderBy->field]);
@ -804,4 +767,3 @@ class Orderer {
return $cmp;
}
}
?>

View File

@ -13,23 +13,19 @@ define('DATE_COL', 'date');
/** EXPERIMENTAL: Encapsulates info about a column in a flatfile DB */
class Column
{
class Column {
/**
* Create a new column object
*/
function Column($index, $type)
{
function Column($index, $type) {
$this->index = $index;
$this->type = $type;
}
}
/** EXPERIMENTAL: Represent a column that is a foreign key. Used for temporarily building tables array */
class JoinColumn
{
function JoinColumn($index, $tablename, $columnname)
{
class JoinColumn {
function JoinColumn($index, $tablename, $columnname) {
$this->index = $index;
$this->tablename = $tablename;
$this->columnname = $columnname;
@ -39,8 +35,7 @@ class JoinColumn
/**
* EXPERIMENTAL: Utilities for handling definitions of tables.
*/
class TableUtils
{
class TableUtils {
/**
* Finds JoinColumns in an array of tables, and adds 'type' fields by looking up the columns
*
@ -49,21 +44,17 @@ class TableUtils
* COLUMN_NAME_CONSTANT should be a unique constant within the table, and
* column definition should be a Column object or JoinColumn object
*/
function resolveJoins(&$tables)
{
foreach ($tables as $tablename => $discard)
{
function resolveJoins(&$tables) {
foreach ($tables as $tablename => $discard) {
// PHP4 compatible: can't do : foreach ($tables as $tablename => &$tabledef)
// and strangely, if we do
// foreach ($tables as $tablename => &$tabledef)
// $tabledef =& $tables[$tablename];
// then we get bugs
$tabledef =& $tables[$tablename];
foreach ($tabledef as $colname => $discard)
{
foreach ($tabledef as $colname => $discard) {
$coldef =& $tabledef[$colname]; // PHP4 compatible
if (is_a($coldef, 'JoinColumn') or is_subclass_of($coldef, 'JoinColumn'))
{
if (is_a($coldef, 'JoinColumn') or is_subclass_of($coldef, 'JoinColumn')) {
TableUtils::resolveColumnJoin($coldef, $tables);
}
}
@ -71,21 +62,17 @@ class TableUtils
}
/** @access private */
function resolveColumnJoin(&$columndef, &$tables)
{
function resolveColumnJoin(&$columndef, &$tables) {
// Doesn't work if the column it is joined to is also
// a JoinColumn, but I can't think of ever wanting to do that
$columndef->type = $tables[$columndef->tablename][$columndef->columnname]->type;
}
/** Uses 'define' to create global constants for all the column names */
function createDefines(&$tables)
{
foreach ($tables as $tablename => $discard)
{
function createDefines(&$tables) {
foreach ($tables as $tablename => $discard) {
$tabledef = & $tables[$tablename]; // PHP4 compatible
foreach ($tabledef as $colname => $discard)
{
foreach ($tabledef as $colname => $discard) {
$coldef = & $tabledef[$colname];
define(strtoupper($tablename) . '_' . $colname, $coldef->index);
}
@ -98,15 +85,11 @@ class TableUtils
* A row schema is just an array of the column types for a table,
* using the constants defined above.
*/
function createRowSchema(&$tabledef)
{
function createRowSchema(&$tabledef) {
$row_schema = array();
foreach ($tabledef as $colname => $coldef)
{
foreach ($tabledef as $colname => $coldef) {
$row_schema[$coldef->index] = $coldef->type;
}
return $row_schema;
}
}
?>

View File

@ -1,5 +1,7 @@
<?php
if (!defined('TINYIB_BOARD')) { die(''); }
if (!defined('TINYIB_BOARD')) {
die('');
}
function cleanString($string) {
$search = array("<", ">");
@ -160,13 +162,19 @@ function postLink($message) {
}
function colorQuote($message) {
if (substr($message, -1, 1) != "\n") { $message .= "\n"; }
if (substr($message, -1, 1) != "\n") {
$message .= "\n";
}
return preg_replace('/^(&gt;[^\>](.*))\n/m', '<span class="unkfunc">\\1</span>' . "\n", $message);
}
function deletePostImages($post) {
if ($post['file'] != '') { @unlink('src/' . $post['file']); }
if ($post['thumb'] != '') { @unlink('thumb/' . $post['thumb']); }
if ($post['file'] != '') {
@unlink('src/' . $post['file']);
}
if ($post['thumb'] != '') {
@unlink('thumb/' . $post['thumb']);
}
}
function checkBanned() {
@ -200,7 +208,8 @@ function checkMessageSize() {
}
function manageCheckLogIn() {
$loggedin = false; $isadmin = false;
$loggedin = false;
$isadmin = false;
if (isset($_POST['password'])) {
if ($_POST['password'] == TINYIB_ADMINPASS) {
$_SESSION['tinyib'] = TINYIB_ADMINPASS;
@ -273,7 +282,7 @@ function validateFileUpload() {
}
}
function checkDuplicateImage($hex) {
function checkDuplicateFile($hex) {
$hexmatches = postsByHex($hex);
if (count($hexmatches) > 0) {
foreach ($hexmatches as $hexmatch) {
@ -340,7 +349,9 @@ function createThumbnail($name, $filename, $new_w, $new_h) {
function fastImageCopyResampled(&$dst_image, &$src_image, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h, $quality = 3) {
// Author: Tim Eckel - Date: 12/17/04 - Project: FreeRingers.net - Freely distributable.
if (empty($src_image) || empty($dst_image)) { return false; }
if (empty($src_image) || empty($dst_image)) {
return false;
}
if ($quality <= 1) {
$temp = imagecreatetruecolor($dst_w + 1, $dst_h + 1);
@ -377,5 +388,3 @@ function strallpos($haystack, $needle, $offset = 0) {
}
return $result;
}
?>

View File

@ -1,5 +1,7 @@
<?php
if (!defined('TINYIB_BOARD')) { die(''); }
if (!defined('TINYIB_BOARD')) {
die('');
}
function pageHeader() {
$return = <<<EOF
@ -37,7 +39,9 @@ function buildPost($post, $res) {
$return = "";
$threadid = ($post['parent'] == TINYIB_NEWTHREAD) ? $post['id'] : $post['parent'];
$postlink = ($res == TINYIB_RESPAGE) ? ($threadid . '.html#' . $post['id']) : ('res/' . $threadid . '.html#' . $post['id']);
if (!isset($post["omitted"])) { $post["omitted"] = 0; }
if (!isset($post["omitted"])) {
$post["omitted"] = 0;
}
if ($post["parent"] != TINYIB_NEWTHREAD) {
$return .= <<<EOF
@ -161,6 +165,8 @@ EOF;
$postingmode = '&#91;<a href="../">Return</a>&#93;<div class="replymode">Posting mode: Reply</div> ';
}
$filetypes = (TINYIB_WEBM ? "GIF, JPG, PNG, and WEBM" : "GIF, JPG, and PNG");
$unique_posts_html = '';
$unique_posts = uniquePosts();
if ($unique_posts > 0) {
@ -243,7 +249,7 @@ EOF;
<tr>
<td colspan="2" class="rules">
<ul>
<li>Supported file types are GIF, JPG, and PNG.</li>
<li>Supported file types are $filetypes.</li>
$max_file_size_rules_html
<li>Images greater than $maxdimensions will be thumbnailed.</li>
$unique_posts_html
@ -277,7 +283,9 @@ EOF;
}
function rebuildIndexes() {
$page = 0; $i = 0; $htmlposts = '';
$page = 0;
$i = 0;
$htmlposts = '';
$threads = allThreads();
$pages = ceil(count($threads) / TINYIB_THREADSPERPAGE) - 1;
@ -297,7 +305,9 @@ function rebuildIndexes() {
$file = ($page == 0) ? 'index.html' : $page . '.html';
writePage($file, buildPage($htmlposts, 0, $pages, $page));
$page++; $i = 0; $htmlposts = '';
$page++;
$i = 0;
$htmlposts = '';
}
}
@ -322,7 +332,9 @@ function rebuildThread($id) {
function adminBar() {
global $loggedin, $isadmin, $returnlink;
$return = '[<a href="' . $returnlink . '" style="text-decoration: underline;">Return</a>]';
if (!$loggedin) { return $return; }
if (!$loggedin) {
return $return;
}
return '[<a href="?manage">Status</a>] [' . (($isadmin) ? '<a href="?manage&bans">Bans</a>] [' : '') . '<a href="?manage&moderate">Moderate Post</a>] [<a href="?manage&rawpost">Raw Post</a>] [' . (($isadmin) ? '<a href="?manage&rebuildall">Rebuild All</a>] [' : '') . '<a href="?manage&logout">Log Out</a>] &middot; ' . $return;
}
@ -570,7 +582,9 @@ function manageStatus() {
$posts = latestPosts();
$i = 0;
foreach ($posts as $post) {
if ($post_html != '') { $post_html .= '<tr><td colspan="2"><hr></td></tr>'; }
if ($post_html != '') {
$post_html .= '<tr><td colspan="2"><hr></td></tr>';
}
$post_html .= '<tr><td>' . buildPost($post, TINYIB_INDEXPAGE) . '</td><td valign="top" align="right"><form method="get" action="?"><input type="hidden" name="manage" value=""><input type="hidden" name="moderate" value="' . $post['id'] . '"><input type="submit" value="Moderate" class="managebutton"></form></td></tr>';
}
@ -620,4 +634,3 @@ EOF;
function manageInfo($text) {
return '<div class="manageinfo">' . $text . '</div>';
}
?>

View File

@ -8,6 +8,7 @@ define('TINYIB_PREVIEWREPLIES', 3); // Amount of replies previewed on index page
define('TINYIB_MAXREPLIES', 0); // Maximum replies before a thread stops bumping [0 to disable]
define('TINYIB_MAXKB', 2048); // Maximum file size in kilobytes [0 to disable]
define('TINYIB_MAXKBDESC', "2 MB"); // Human-readable representation of the maximum file size
define('TINYIB_WEBM', false); // Enable .weba and .webm audio/video file upload (see README for instructions)
define('TINYIB_MAXW', 250); // Maximum image width (reply) - Images exceeding these sizes will be thumbnailed
define('TINYIB_MAXH', 250); // Maximum image height (reply)
define('TINYIB_MAXWOP', 250); // Maximum image width (new thread)
@ -17,7 +18,7 @@ define('TINYIB_LOGO', ""); // Logo HTML
define('TINYIB_TRIPSEED', ""); // Enter some random text - Used when generating secure tripcodes - Must not change once set
define('TINYIB_ADMINPASS', ""); // Text entered at the manage prompt to gain administrator access
define('TINYIB_MODPASS', ""); // Moderators only have access to delete posts ["" to disable]
define('TINYIB_DBMODE', "flatfile"); // Choose: flatfile / mysql / sqlite
define('TINYIB_DBMODE', "flatfile"); // Choose: flatfile / mysql / sqlite (flatfile is not recommended for popular sites)
// Note: The following only apply when TINYIB_DBMODE is set to mysql
define('TINYIB_DBHOST', "localhost");
@ -26,4 +27,3 @@ define('TINYIB_DBPASSWORD', "");
define('TINYIB_DBNAME', "");
define('TINYIB_DBPOSTS', TINYIB_BOARD . "_posts");
define('TINYIB_DBBANS', "bans");
?>

BIN
video_overlay.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB