Add optional WebA and WebM support

json
Trevor Slocum 9 years ago
parent 777800c696
commit 90a878f8ee

1
.gitignore vendored

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

@ -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
------------

@ -1,182 +1,215 @@
html, body {
font-size:12pt;
background:#EEF2FF;
color:#000000;
font-size: 12pt;
background: #EEF2FF;
color: #000000;
}
a {
background:inherit;
color:#34345C;
text-decoration:none;
font-family:sans-serif;
background: inherit;
color: #34345C;
text-decoration: none;
font-family: sans-serif;
}
a:visited {
background:inherit;
color:#34345C;
text-decoration:none;
font-family:sans-serif;
background: inherit;
color: #34345C;
text-decoration: none;
font-family: sans-serif;
}
a:hover {
color:#DD0000;
background:inherit;
font-family:sans-serif;
color: #DD0000;
background: inherit;
font-family: sans-serif;
}
.filesize a {
text-decoration:underline;
text-decoration: underline;
}
.filesize a:visited {
text-decoration:underline;
text-decoration: underline;
}
.adminbar {
background:inherit;
background: inherit;
}
.logo {
clear:both;
text-align:center;
background:inherit;
font-size:24pt;
color:#AF0A0F;
width:100%;
}
clear: both;
text-align: center;
background: inherit;
font-size: 24pt;
color: #AF0A0F;
width: 100%;
}
.replymode {
background:#0010E0;
color:#FFFFFF;
width:100%;
background: #0010E0;
color: #FFFFFF;
width: 100%;
}
.manageinfo {
background:#00B930;
color:#FFFFFF;
width:100%;
background: #00B930;
color: #FFFFFF;
width: 100%;
}
.catalogmode {
background:#0040E0;
color:#FFFFFF;
width:100%;
background: #0040E0;
color: #FFFFFF;
width: 100%;
}
.postarea {
background:inherit;
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;
background: #9988EE;
color: #000000;
font-weight: 800;
}
.footer {
font-size:10px;
font-family:sans-serif;
font-size: 10px;
font-family: sans-serif;
}
.passvalid {
background:#9988EE;
text-align:center;
width:100%;
color:#ffffff;
background: #9988EE;
text-align: center;
width: 100%;
color: #ffffff;
}
.dellist {
background:inherit;
text-align:center;
background: inherit;
text-align: center;
}
.delbuttons {
background:inherit;
text-align:center;
padding-bottom:4px;
background: inherit;
text-align: center;
padding-bottom: 4px;
}
.managehead {
background:#0F8FE1;
color:#000000;
font-family:sans-serif;
font-size:14px;
padding:0px;
background: #0F8FE1;
color: #000000;
font-family: sans-serif;
font-size: 14px;
padding: 0px;
}
.postlists {
background:#FFFFFF;
width:100%;
padding:0px;
color:#000000;
background: #FFFFFF;
width: 100%;
padding: 0px;
color: #000000;
}
.row1 {
background:#9AD2F6;
font-family:sans-serif;
font-size:12px;
color:#000000;
background: #9AD2F6;
font-family: sans-serif;
font-size: 12px;
color: #000000;
}
.row2 {
background:#FFFFFF;
font-family:sans-serif;
font-size:12px;
color:#000000;
background: #FFFFFF;
font-family: sans-serif;
font-size: 12px;
color: #000000;
}
.unkfunc {
color:#789922;
color: #789922;
}
.filesize {
font-size:12px;
font-family:sans-serif;
text-decoration:underline;
font-size: 12px;
font-family: sans-serif;
text-decoration: underline;
/*padding-left:3em;*/
}
.filetitle {
background:inherit;
font-size:18px;
font-family:serif;
color:#0F0C5D;
font-weight:800;
background: inherit;
font-size: 18px;
font-family: serif;
color: #0F0C5D;
font-weight: 800;
}
.postername {
background:inherit;
font-size:12px;
font-family:serif;
color:#117743;
font-weight:800;
background: inherit;
font-size: 12px;
font-family: serif;
color: #117743;
font-weight: 800;
}
.oldpost {
background:inherit;
font-size:18px;
font-family:serif;
color:#0F0C5D;
font-weight:800;
background: inherit;
font-size: 18px;
font-family: serif;
color: #0F0C5D;
font-weight: 800;
}
.omittedposts {
background:inherit;
font-size:18px;
font-family:serif;
color:#070707;
font-weight:800;
background: inherit;
font-size: 18px;
font-family: serif;
color: #070707;
font-weight: 800;
}
.reply {
background:#D6DAF0;
color:#000000;
font-family:serif;
background: #D6DAF0;
color: #000000;
font-family: serif;
}
.replyhl {
background: #D6BAD0;
color: #000000;
}
.replytitle {
background:inherit;
font-size:18px;
font-family:serif;
color:#0F0C5D;
font-weight:800;
background: inherit;
font-size: 18px;
font-family: serif;
color: #0F0C5D;
font-weight: 800;
}
.commentpostername {
background:inherit;
font-size:12px;
font-family:serif;
color:#117743;
font-weight:800;
background: inherit;
font-size: 12px;
font-family: serif;
color: #117743;
font-weight: 800;
}
.thumbnailmsg {
background:inherit;
font-size:9px;
font-family:sans-serif;
color:#000000;
background: inherit;
font-size: 9px;
font-family: sans-serif;
color: #000000;
}

@ -1,151 +1,182 @@
html, body {
background:#FFFFEE;
color:#800000;
background: #FFFFEE;
color: #800000;
}
a {
color:#0000EE;
color: #0000EE;
}
a:hover {
color:#DD0000;
color: #DD0000;
}
.reflink a:hover{
.reflink a:hover {
font-weight: bold;
}
.logo {
clear:both;
text-align:center;
font-size:2em;
color:#800000;
width:100%;
clear: both;
text-align: center;
font-size: 2em;
color: #800000;
width: 100%;
}
.replymode {
background:#E04000;
text-align:center;
padding:2px;
color:#FFFFFF;
width:100%;
background: #E04000;
text-align: center;
padding: 2px;
color: #FFFFFF;
width: 100%;
}
.manageinfo {
background:#00B930;
text-align:center;
padding:2px;
color:#FFFFFF;
width:100%;
background: #00B930;
text-align: center;
padding: 2px;
color: #FFFFFF;
width: 100%;
}
.catalogmode {
background:#0040E0;
text-align:center;
padding:2px;
color:#FFFFFF;
width:100%;
background: #0040E0;
text-align: center;
padding: 2px;
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;
background: #EEAA88;
color: #800000;
font-weight: 800;
}
.footer {
font-size:12px;
font-family:serif;
font-size: 12px;
font-family: serif;
}
.passvalid {
background:#EEAA88;
text-align:center;
width:100%;
color:#ffffff;
background: #EEAA88;
text-align: center;
width: 100%;
color: #ffffff;
}
.dellist {
font-weight: bold;
text-align:center;
text-align: center;
}
.delbuttons {
text-align:center;
padding-bottom:4px;
text-align: center;
padding-bottom: 4px;
}
.managehead {
background:#AAAA66;
color:#400000;
padding:0px;
background: #AAAA66;
color: #400000;
padding: 0px;
}
.postlists {
background:#FFFFFF;
width:100%;
padding:0px;
color:#800000;
background: #FFFFFF;
width: 100%;
padding: 0px;
color: #800000;
}
.row1 {
background:#EEEECC;
color:#800000;
background: #EEEECC;
color: #800000;
}
.row2 {
background:#DDDDAA;
color:#800000;
background: #DDDDAA;
color: #800000;
}
.unkfunc {
background:inherit;
color:#789922;
background: inherit;
color: #789922;
}
.filesize {
text-decoration:none;
text-decoration: none;
}
.filetitle {
background:inherit;
font-size:1.2em;
color:#CC1105;
font-weight:800;
background: inherit;
font-size: 1.2em;
color: #CC1105;
font-weight: 800;
}
.postername {
color:#117743;
font-weight:bold;
color: #117743;
font-weight: bold;
}
.postertrip {
color:#228854;
color: #228854;
}
.oldpost {
color:#CC1105;
font-weight:800;
color: #CC1105;
font-weight: 800;
}
.omittedposts {
color:#707070;
color: #707070;
}
.reply {
background: #F0E0D6;
color: #800000;
}
.replyhl {
background: #F0C0B0;
color: #800000;
}
.replytitle {
font-size: 1.2em;
color:#CC1105;
font-weight:800;
color: #CC1105;
font-weight: 800;
}
.commentpostername {
color:#117743;
font-weight:800;
color: #117743;
font-weight: 800;
}
.thumbnailmsg {
font-size: small;
color:#800000;
color: #800000;
}
.abbrev {
color:#707070;
color: #707070;
}
.highlight {
background:#F0E0D6;
color:#800000;
background: #F0E0D6;
color: #800000;
border: 2px dashed #EEAA88;
}

@ -22,9 +22,9 @@ form {
}
.aa {
white-space: pre;
text-align: left;
font-family: IPAMonaPGothic, Mona, 'MS PGothic', YOzFontAA97 !important;
white-space: pre;
text-align: left;
font-family: IPAMonaPGothic, Mona, 'MS PGothic', YOzFontAA97 !important;
}
.thumb {
@ -58,7 +58,7 @@ form {
text-decoration: none;
}
.reflink a:hover{
.reflink a:hover {
color: #800000;
}
@ -73,7 +73,7 @@ form {
}
.doubledash {
vertical-align: top;
vertical-align: top;
clear: both;
float: left;
font-size: 1.75em;
@ -91,7 +91,7 @@ form {
.footer {
clear: both;
text-align:center;
text-align: center;
}
.rules {
@ -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;
}

@ -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.");
@ -58,12 +66,12 @@ if (isset($_POST['message']) || isset($_POST['file'])) {
checkMessageSize();
checkFlood();
}
$post = newPost(setParent());
$post['ip'] = $_SERVER['REMOTE_ADDR'];
list($post['name'], $post['tripcode']) = nameAndTripcode($_POST['name']);
$post['name'] = cleanString(substr($post['name'], 0, 75));
$post['email'] = cleanString(str_replace('"', '&quot;', substr($_POST['email'], 0, 75)));
$post['subject'] = cleanString(substr($_POST['subject'], 0, 75));
@ -76,67 +84,141 @@ if (isset($_POST['message']) || isset($_POST['file'])) {
}
$post['password'] = ($_POST['password'] != '') ? md5(md5($_POST['password'])) : '';
$post['nameblock'] = nameBlock($post['name'], $post['tripcode'], $post['email'], time(), $rawposttext);
if (isset($_FILES['file'])) {
if ($_FILES['file']['name'] != "") {
validateFileUpload();
if (!is_file($_FILES['file']['tmp_name']) || !is_readable($_FILES['file']['tmp_name'])) {
fancyDie("File transfer failure. Please retry the submission.");
}
if ((TINYIB_MAXKB > 0) && (filesize($_FILES['file']['tmp_name']) > (TINYIB_MAXKB * 1024))) {
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];
list($thumb_maxwidth, $thumb_maxheight) = thumbnailDimensions($post);
if (!createThumbnail($file_location, $thumb_location, $thumb_maxwidth, $thumb_maxheight)) {
fancyDie("Could not create thumbnail.");
}
$thumb_info = getimagesize($thumb_location);
$post['thumb_width'] = $thumb_info[0]; $post['thumb_height'] = $thumb_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);
if (!createThumbnail($file_location, $thumb_location, $thumb_maxwidth, $thumb_maxheight)) {
fancyDie("Could not create thumbnail.");
}
$thumb_info = getimagesize($thumb_location);
$post['thumb_width'] = $thumb_info[0];
$post['thumb_height'] = $thumb_info[1];
}
}
}
if ($post['file'] == '') { // No file uploaded
if ($post['parent'] == TINYIB_NEWTHREAD) {
fancyDie("An image is required to start a thread.");
@ -147,18 +229,18 @@ if (isset($_POST['message']) || isset($_POST['file'])) {
} else {
echo $post['file_original'] . ' uploaded.<br>';
}
$post['id'] = insertPost($post);
if (strtolower($post['email']) == 'noko') {
$redirect = 'res/' . ($post['parent'] == TINYIB_NEWTHREAD ? $post['id'] : $post['parent']) . '.html#' . $post['id'];
}
trimThreads();
echo 'Updating thread...<br>';
if ($post['parent'] != TINYIB_NEWTHREAD) {
rebuildThread($post['parent']);
if (strtolower($post['email']) != 'sage') {
if (TINYIB_MAXREPLIES == 0 || numRepliesToThreadByID($post['parent']) <= TINYIB_MAXREPLIES) {
bumpThreadByID($post['parent']);
@ -167,23 +249,29 @@ if (isset($_POST['message']) || isset($_POST['file'])) {
} else {
rebuildThread($post['id']);
}
echo 'Updating index...<br>';
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) {
list($loggedin, $isadmin) = manageCheckLogIn();
if ($loggedin && $_POST['password'] == '') {
// Redirect to post moderation page
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,12 +283,16 @@ 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();
if ($loggedin) {
if ($isadmin) {
if (isset($_GET['rebuildall'])) {
@ -212,19 +304,19 @@ if (isset($_POST['message']) || isset($_POST['file'])) {
$text .= manageInfo('Rebuilt board.');
} elseif (isset($_GET['bans'])) {
clearExpiredBans();
if (isset($_POST['ip'])) {
if ($_POST['ip'] != '') {
$banexists = banByIP($_POST['ip']);
if ($banexists) {
fancyDie('Sorry, there is already a ban on record for that IP address.');
}
$ban = array();
$ban['ip'] = $_POST['ip'];
$ban['expire'] = ($_POST['expire'] > 0) ? (time() + $_POST['expire']) : 0;
$ban['reason'] = $_POST['reason'];
insertBan($ban);
$text .= manageInfo('Ban record added for ' . $ban['ip']);
}
@ -235,7 +327,7 @@ if (isset($_POST['message']) || isset($_POST['file'])) {
$text .= manageInfo('Ban record lifted for ' . $ban['ip']);
}
}
$onload = manageOnLoad('bans');
$text .= manageBanForm();
$text .= manageBansTable();
@ -254,7 +346,7 @@ if (isset($_POST['message']) || isset($_POST['file'])) {
}
}
}
if (isset($_GET['delete'])) {
$post = postByID($_GET['delete']);
if ($post) {
@ -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') . '">';
}
?>

@ -1,38 +1,40 @@
<?php
if (!defined('TINYIB_BOARD')) { die(''); }
if (!defined('TINYIB_BOARD')) {
die('');
}
# Post Structure
define('POSTS_FILE', '.posts');
define('POST_ID', 0);
define('POST_PARENT', 1);
define('POST_TIMESTAMP', 2);
define('POST_BUMPED', 3);
define('POST_IP', 4);
define('POST_NAME', 5);
define('POST_TRIPCODE', 6);
define('POST_EMAIL', 7);
define('POST_NAMEBLOCK', 8);
define('POST_SUBJECT', 9);
define('POST_MESSAGE', 10);
define('POST_PASSWORD', 11);
define('POST_FILE', 12);
define('POST_FILE_HEX', 13);
define('POST_FILE_ORIGINAL', 14);
define('POST_FILE_SIZE', 15);
define('POSTS_FILE', '.posts');
define('POST_ID', 0);
define('POST_PARENT', 1);
define('POST_TIMESTAMP', 2);
define('POST_BUMPED', 3);
define('POST_IP', 4);
define('POST_NAME', 5);
define('POST_TRIPCODE', 6);
define('POST_EMAIL', 7);
define('POST_NAMEBLOCK', 8);
define('POST_SUBJECT', 9);
define('POST_MESSAGE', 10);
define('POST_PASSWORD', 11);
define('POST_FILE', 12);
define('POST_FILE_HEX', 13);
define('POST_FILE_ORIGINAL', 14);
define('POST_FILE_SIZE', 15);
define('POST_FILE_SIZE_FORMATTED', 16);
define('POST_IMAGE_WIDTH', 17);
define('POST_IMAGE_HEIGHT', 18);
define('POST_THUMB', 19);
define('POST_THUMB_WIDTH', 20);
define('POST_THUMB_HEIGHT', 21);
define('POST_IMAGE_WIDTH', 17);
define('POST_IMAGE_HEIGHT', 18);
define('POST_THUMB', 19);
define('POST_THUMB_WIDTH', 20);
define('POST_THUMB_HEIGHT', 21);
# Ban Structure
define('BANS_FILE', '.bans');
define('BAN_ID', 0);
define('BAN_IP', 1);
define('BAN_TIMESTAMP', 2);
define('BAN_EXPIRE', 3);
define('BAN_REASON', 4);
define('BANS_FILE', '.bans');
define('BAN_ID', 0);
define('BAN_IP', 1);
define('BAN_TIMESTAMP', 2);
define('BAN_EXPIRE', 3);
define('BAN_REASON', 4);
require_once 'flatfile/flatfile.php';
$db = new Flatfile();
@ -51,7 +53,7 @@ function threadExistsByID($id) {
$compClause = new AndWhereClause();
$compClause->add(new SimpleWhereClause(POST_ID, '=', $id, INTEGER_COMPARISON));
$compClause->add(new SimpleWhereClause(POST_PARENT, '=', 0, INTEGER_COMPARISON));
return count($GLOBALS['db']->selectWhere(POSTS_FILE, $compClause, 1)) > 0;
}
@ -67,7 +69,7 @@ function insertPost($newpost) {
$post[POST_EMAIL] = $newpost['email'];
$post[POST_NAMEBLOCK] = $newpost['nameblock'];
$post[POST_SUBJECT] = $newpost['subject'];
$post[POST_MESSAGE] = $newpost['message'];
$post[POST_MESSAGE] = $newpost['message'];
$post[POST_PASSWORD] = $newpost['password'];
$post[POST_FILE] = $newpost['file'];
$post[POST_FILE_HEX] = $newpost['file_hex'];
@ -99,7 +101,7 @@ function countThreads() {
return count($rows);
}
function convertPostsToSQLStyle($posts, $singlepost=false) {
function convertPostsToSQLStyle($posts, $singlepost = false) {
$newposts = array();
foreach ($posts as $oldpost) {
$post = newPost();
@ -125,12 +127,14 @@ function convertPostsToSQLStyle($posts, $singlepost=false) {
$post['thumb'] = $oldpost[POST_THUMB];
$post['thumb_width'] = $oldpost[POST_THUMB_WIDTH];
$post['thumb_height'] = $oldpost[POST_THUMB_HEIGHT];
if ($post['parent'] == '') {
$post['parent'] = TINYIB_NEWTHREAD;
}
if ($singlepost) { return $post; }
if ($singlepost) {
return $post;
}
$newposts[] = $post;
}
return $newposts;
@ -150,7 +154,7 @@ function postsInThreadByID($id) {
$compClause = new OrWhereClause();
$compClause->add(new SimpleWhereClause(POST_ID, '=', $id, INTEGER_COMPARISON));
$compClause->add(new SimpleWhereClause(POST_PARENT, '=', $id, INTEGER_COMPARISON));
$rows = $GLOBALS['db']->selectWhere(POSTS_FILE, $compClause, -1, new OrderBy(POST_ID, ASCENDING, INTEGER_COMPARISON));
return convertPostsToSQLStyle($rows);
}
@ -175,7 +179,7 @@ function deletePostByID($id) {
$thispost = $post;
}
}
if (isset($thispost)) {
if ($thispost['parent'] == 0) {
@unlink('res/' . $thispost['id'] . '.html');
@ -190,7 +194,7 @@ function trimThreads() {
$numthreads = countThreads();
if ($numthreads > TINYIB_MAXTHREADS) {
$allthreads = allThreads();
for ($i=TINYIB_MAXTHREADS;$i<$numthreads;$i++) {
for ($i = TINYIB_MAXTHREADS; $i < $numthreads; $i++) {
deletePostByID($allthreads[$i]['id']);
}
}
@ -216,7 +220,7 @@ function allBans() {
return convertBansToSQLStyle($rows);
}
function convertBansToSQLStyle($bans, $singleban=false) {
function convertBansToSQLStyle($bans, $singleban = false) {
$newbans = array();
foreach ($bans as $oldban) {
$ban = array();
@ -225,8 +229,10 @@ function convertBansToSQLStyle($bans, $singleban=false) {
$ban['timestamp'] = $oldban[BAN_TIMESTAMP];
$ban['expire'] = $oldban[BAN_EXPIRE];
$ban['reason'] = $oldban[BAN_REASON];
if ($singleban) { return $ban; }
if ($singleban) {
return $ban;
}
$newbans[] = $ban;
}
return $newbans;
@ -239,7 +245,7 @@ function insertBan($newban) {
$ban[BAN_TIMESTAMP] = time();
$ban[BAN_EXPIRE] = $newban['expire'];
$ban[BAN_REASON] = $newban['reason'];
return $GLOBALS['db']->insertWithAutoId(BANS_FILE, BAN_ID, $ban);
}
@ -247,7 +253,7 @@ function clearExpiredBans() {
$compClause = new AndWhereClause();
$compClause->add(new SimpleWhereClause(BAN_EXPIRE, '>', 0, INTEGER_COMPARISON));
$compClause->add(new SimpleWhereClause(BAN_EXPIRE, '<=', time(), INTEGER_COMPARISON));
$bans = $GLOBALS['db']->selectWhere(BANS_FILE, $compClause, -1);
foreach ($bans as $ban) {
deleteBanByID($ban[BAN_ID]);
@ -257,5 +263,3 @@ function clearExpiredBans() {
function deleteBanByID($id) {
$GLOBALS['db']->deleteWhere(BANS_FILE, new SimpleWhereClause(BAN_ID, '=', $id, INTEGER_COMPARISON));
}
?>

@ -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");
@ -90,7 +92,7 @@ function countThreads() {
return mysql_result(mysql_query("SELECT COUNT(*) FROM `" . TINYIB_DBPOSTS . "` WHERE `parent` = 0"), 0, 0);
}
function allThreads() {
function allThreads() {
$threads = array();
$result = mysql_query("SELECT * FROM `" . TINYIB_DBPOSTS . "` WHERE `parent` = 0 ORDER BY `bumped` DESC");
if ($result) {
@ -105,7 +107,7 @@ function numRepliesToThreadByID($id) {
return mysql_result(mysql_query("SELECT COUNT(*) FROM `" . TINYIB_DBPOSTS . "` WHERE `parent` = " . $id), 0, 0);
}
function postsInThreadByID($id) {
function postsInThreadByID($id) {
$posts = array();
$result = mysql_query("SELECT * FROM `" . TINYIB_DBPOSTS . "` WHERE `id` = " . $id . " OR `parent` = " . $id . " ORDER BY `id` ASC");
if ($result) {
@ -116,7 +118,7 @@ function postsInThreadByID($id) {
return $posts;
}
function postsByHex($hex) {
function postsByHex($hex) {
$posts = array();
$result = mysql_query("SELECT `id`, `parent` FROM `" . TINYIB_DBPOSTS . "` WHERE `file_hex` = '" . mysql_real_escape_string($hex) . "' LIMIT 1");
if ($result) {
@ -127,7 +129,7 @@ function postsByHex($hex) {
return $posts;
}
function latestPosts() {
function latestPosts() {
$posts = array();
$result = mysql_query("SELECT * FROM `" . TINYIB_DBPOSTS . "` ORDER BY `timestamp` DESC LIMIT 10");
if ($result) {
@ -138,7 +140,7 @@ function latestPosts() {
return $posts;
}
function deletePostByID($id) {
function deletePostByID($id) {
$posts = postsInThreadByID($id);
foreach ($posts as $post) {
if ($post['id'] != $id) {
@ -159,7 +161,7 @@ function deletePostByID($id) {
function trimThreads() {
if (TINYIB_MAXTHREADS > 0) {
$result = mysql_query("SELECT `id` FROM `" . TINYIB_DBPOSTS . "` WHERE `parent` = 0 ORDER BY `bumped` DESC LIMIT " . TINYIB_MAXTHREADS. ", 10");
$result = mysql_query("SELECT `id` FROM `" . TINYIB_DBPOSTS . "` WHERE `parent` = 0 ORDER BY `bumped` DESC LIMIT " . TINYIB_MAXTHREADS . ", 10");
if ($result) {
while ($post = mysql_fetch_assoc($result)) {
deletePostByID($post['id']);
@ -168,7 +170,7 @@ function trimThreads() {
}
}
function lastPostByIP() {
function lastPostByIP() {
$replies = mysql_query("SELECT * FROM `" . TINYIB_DBPOSTS . "` WHERE `ip` = '" . $_SERVER['REMOTE_ADDR'] . "' ORDER BY `id` DESC LIMIT 1");
if ($replies) {
while ($post = mysql_fetch_assoc($replies)) {
@ -224,5 +226,3 @@ function clearExpiredBans() {
function deleteBanByID($id) {
mysql_query("DELETE FROM `" . TINYIB_DBBANS . "` WHERE `id` = " . mysql_real_escape_string($id) . " LIMIT 1");
}
?>

@ -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");
@ -75,11 +77,11 @@ function bumpThreadByID($id) {
sqlite_query($GLOBALS["db"], "UPDATE " . TINYIB_DBPOSTS . " SET bumped = " . time() . " WHERE id = " . $id);
}
function countThreads() {
function countThreads() {
return sqlite_fetch_single(sqlite_query($GLOBALS["db"], "SELECT COUNT(*) FROM " . TINYIB_DBPOSTS . " WHERE parent = 0"));
}
function allThreads() {
function allThreads() {
$threads = array();
$result = sqlite_fetch_all(sqlite_query($GLOBALS["db"], "SELECT * FROM " . TINYIB_DBPOSTS . " WHERE parent = 0 ORDER BY bumped DESC"), SQLITE_ASSOC);
foreach ($result as $thread) {
@ -92,7 +94,7 @@ function numRepliesToThreadByID($id) {
return sqlite_fetch_single(sqlite_query($GLOBALS["db"], "SELECT COUNT(*) FROM " . TINYIB_DBPOSTS . " WHERE parent = " . $id));
}
function postsInThreadByID($id) {
function postsInThreadByID($id) {
$posts = array();
$result = sqlite_fetch_all(sqlite_query($GLOBALS["db"], "SELECT * FROM " . TINYIB_DBPOSTS . " WHERE id = " . $id . " OR parent = " . $id . " ORDER BY id ASC"), SQLITE_ASSOC);
foreach ($result as $post) {
@ -101,7 +103,7 @@ function postsInThreadByID($id) {
return $posts;
}
function postsByHex($hex) {
function postsByHex($hex) {
$posts = array();
$result = sqlite_fetch_all(sqlite_query($GLOBALS["db"], "SELECT id, parent FROM " . TINYIB_DBPOSTS . " WHERE file_hex = '" . sqlite_escape_string($hex) . "' LIMIT 1"), SQLITE_ASSOC);
foreach ($result as $post) {
@ -110,7 +112,7 @@ function postsByHex($hex) {
return $posts;
}
function latestPosts() {
function latestPosts() {
$posts = array();
$result = sqlite_fetch_all(sqlite_query($GLOBALS["db"], "SELECT * FROM " . TINYIB_DBPOSTS . " ORDER BY timestamp DESC LIMIT 10"), SQLITE_ASSOC);
foreach ($result as $post) {
@ -119,7 +121,7 @@ function latestPosts() {
return $posts;
}
function deletePostByID($id) {
function deletePostByID($id) {
$posts = postsInThreadByID($id);
foreach ($posts as $post) {
if ($post['id'] != $id) {
@ -140,14 +142,14 @@ function deletePostByID($id) {
function trimThreads() {
if (TINYIB_MAXTHREADS > 0) {
$result = sqlite_fetch_all(sqlite_query($GLOBALS["db"], "SELECT id FROM " . TINYIB_DBPOSTS . " WHERE parent = 0 ORDER BY bumped DESC LIMIT " . TINYIB_MAXTHREADS. ", 10"), SQLITE_ASSOC);
$result = sqlite_fetch_all(sqlite_query($GLOBALS["db"], "SELECT id FROM " . TINYIB_DBPOSTS . " WHERE parent = 0 ORDER BY bumped DESC LIMIT " . TINYIB_MAXTHREADS . ", 10"), SQLITE_ASSOC);
foreach ($result as $post) {
deletePostByID($post['id']);
}
}
}
function lastPostByIP() {
function lastPostByIP() {
$result = sqlite_fetch_all(sqlite_query($GLOBALS["db"], "SELECT * FROM " . TINYIB_DBPOSTS . " WHERE ip = '" . $_SERVER['REMOTE_ADDR'] . "' ORDER BY id DESC LIMIT 1"), SQLITE_ASSOC);
foreach ($result as $post) {
return $post;
@ -193,5 +195,3 @@ function clearExpiredBans() {
function deleteBanByID($id) {
sqlite_query($GLOBALS["db"], "DELETE FROM " . TINYIB_DBBANS . " WHERE id = " . sqlite_escape_string($id));
}
?>

@ -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);
}

@ -27,7 +27,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* @license http://www.opensource.org/licenses/mit-license.php
*/
require_once('flatfile_utils.php');
require_once('flatfile_utils.php');
/** Used to indicate the default comparison should be done, which is STRING_COMPARISON in the absence of a schema, or whatever the schema specifies if one has been added */
define('DEFAULT_COMPARISON', '');
@ -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];
}
@ -71,28 +70,27 @@ class Flatfile {
/** @access private */
var $schemata;
/** The directory to store files in.
/** The directory to store files in.
* @var string
*/
var $datadir;
function Flatfile()
{
function Flatfile() {
$this->schemata = array();
}
/**
* Get all rows from a table
* @param string $tablename The table to get rows from
* @param string $tablename The table to get rows from
* @return array The table as an array of rows, where each row is an array of columns
*/
function selectAll ($tablename) {
function selectAll($tablename) {
if (!isset($this->tables[$tablename]))
$this->loadTable($tablename);
return $this->tables[$tablename];
return $this->tables[$tablename];
}
/**
* Selects rows from a table that match the specified criteria
*
@ -103,26 +101,26 @@ class Flatfile {
* ORDER BY $orderBy [ASC | DESC] [, $orderBy2 ...]
* </pre>
*
* @param string $tablename The table (file) to get the data from
* @param object $whereClause Either a {@link WhereClause WhereClause} object to do selection of rows, or NULL to select all
* @param mixed $limit Specifies limits for the rows returned:
* @param string $tablename The table (file) to get the data from
* @param object $whereClause Either a {@link WhereClause WhereClause} object to do selection of rows, or NULL to select all
* @param mixed $limit Specifies limits for the rows returned:
* - use -1 or omitted to return all rows
* - use an integer n to return the first n rows
* - use a two item array ($startrow, $endrow) to return rows $startrow to $endrow - 1 (zero indexed)
* - use a two item array ($startrow, -1) to return rows $startrow to the end (zero indexed)
* @param mixed $orderBy Either an {@link OrderBy} object or an array of them, defining the sorting that should be applied (if an array, then the first object in the array is the first key to sort on etc). Use NULL for no sorting.
* @param mixed $orderBy Either an {@link OrderBy} object or an array of them, defining the sorting that should be applied (if an array, then the first object in the array is the first key to sort on etc). Use NULL for no sorting.
* @return array The matching data, as an array of rows, where each row is an array of columns
*/
function selectWhere ($tablename, $whereClause, $limit = -1, $orderBy = NULL) {
function selectWhere($tablename, $whereClause, $limit = -1, $orderBy = NULL) {
if (!isset($this->tables[$tablename]))
$this->loadTable($tablename);
$table = $this->selectAll($tablename); // Get a copy
$schema = $this->getSchema($tablename);
if ($orderBy !== NULL)
usort($table, $this->getOrderByFunction($orderBy, $schema));
$results = array();
$count = 0;
@ -130,10 +128,10 @@ class Flatfile {
$limit = array(0, -1);
else if (!is_array($limit))
$limit = array(0, $limit);
foreach ($table as $row) {
if ($whereClause === NULL || $whereClause->testRow($row, $schema)) {
if ($count >= $limit[0])
if ($count >= $limit[0])
$results[] = $row;
++$count;
if (($count >= $limit[1]) && ($limit[1] != -1))
@ -142,22 +140,22 @@ class Flatfile {
}
return $results;
}
/**
* Select a row using a unique ID
* @param string $tablename The table to get data from
* @param string $idField The index of the field containing the ID
* @param string $id The ID to search for
* @return array The row of the table as an array
* @param string $tablename The table to get data from
* @param string $idField The index of the field containing the ID
* @param string $id The ID to search for
* @return array The row of the table as an array
*/
function selectUnique ($tablename, $idField, $id) {
function selectUnique($tablename, $idField, $id) {
$result = $this->selectWhere($tablename, new SimpleWhereClause($idField, '=', $id));
if (count($result) > 0)
return $result[0];
else
return array();
}
/*
* To correctly write a file, and not overwrite the changes
* another process is making, we need to:
@ -170,47 +168,44 @@ class Flatfile {
* the lock on a different file. getLock and releaseLock
* are helper functions to allow us to do this with little fuss