diff --git a/imgboard.php b/imgboard.php index 57b9337..1521b55 100644 --- a/imgboard.php +++ b/imgboard.php @@ -70,6 +70,7 @@ if (isset($_POST['message']) || isset($_POST['file'])) { list($loggedin, $isadmin) = manageCheckLogIn(); $rawpost = isRawPost(); if (!$loggedin) { + checkCAPTCHA(); checkBanned(); checkMessageSize(); checkFlood(); diff --git a/inc/captcha.php b/inc/captcha.php new file mode 100644 index 0000000..9dcaaf1 --- /dev/null +++ b/inc/captcha.php @@ -0,0 +1,386 @@ + + * @license GPLv3 + * @link http://code.google.com/p/cool-php-captcha + * @version 0.3 + * + */ + +session_start(); +putenv('GDFONTPATH=' . realpath('./fonts/')); +$captcha = new SimpleCaptcha(); +$captcha->CreateImage(); + +/** + * SimpleCaptcha class + * + */ +class SimpleCaptcha { + /** Width of the image */ + public $width = 175; + + /** Height of the image */ + public $height = 55; + + /** Dictionary word file (empty for random text) */ + public $wordsFile = ''; + + /** + * Path for resource files (fonts, words, etc.) + * + * "resources" by default. For security reasons, is better move this + * directory to another location outise the web server + * + */ + public $resourcesPath = './fonts'; + + /** Min word length (for non-dictionary random text generation) */ + public $minWordLength = 4; + + /** + * Max word length (for non-dictionary random text generation) + * + * Used for dictionary words indicating the word-length + * for font-size modification purposes + */ + public $maxWordLength = 6; + + /** Sessionname to store the original text */ + public $session_var = 'tinyibcaptcha'; + + /** Background color in RGB-array */ + public $backgroundColor = array(254, 254, 254); + + /** Foreground colors in RGB-array */ + public $colors = array( + array(27, 78, 181), // blue + array(22, 163, 35), // green + array(214, 36, 7), // red + ); + + /** Shadow color in RGB-array or null */ + public $shadowColor = array(0, 0, 0); + + /** Horizontal line through the text */ + public $lineWidth = 3; + + /** + * Font configuration + * + * - font: TTF file + * - spacing: relative pixel space between character + * - minSize: min font size + * - maxSize: max font size + */ + public $fonts = array( + 'Roboto-Regular' => array('spacing' => 0, 'minSize' => 27, 'maxSize' => 27, 'font' => 'roboto_regular.ttf'), + 'Roboto-Bold' => array('spacing' => 0, 'minSize' => 27, 'maxSize' => 27, 'font' => 'roboto_bold.ttf') + ); + + /** Wave configuracion in X and Y axes */ + public $Yperiod = 12; + public $Yamplitude = 14; + public $Xperiod = 11; + public $Xamplitude = 5; + + /** letter rotation clockwise */ + public $maxRotation = 8; + + /** + * Internal image size factor (for better image quality) + * 1: low, 2: medium, 3: high + */ + public $scale = 3; + + /** + * Blur effect for better image quality (but slower image processing). + * Better image results with scale=3 + */ + public $blur = true; + + /** Debug? */ + public $debug = false; + + /** Image format: jpeg or png */ + public $imageFormat = 'png'; + + /** GD image */ + public $im; + + public function __construct($config = array()) { + } + + public function CreateImage() { + $ini = microtime(true); + + /** Initialization */ + $this->ImageAllocate(); + + /** Text insertion */ + $text = $this->GetCaptchaText(); + $fontcfg = $this->fonts[array_rand($this->fonts)]; + $this->WriteText($text, $fontcfg); + + $_SESSION[$this->session_var] = $text; + + /** Transformations */ + if (!empty($this->lineWidth)) { + $this->WriteLine(); + } + $this->WaveImage(); + if ($this->blur && function_exists('imagefilter')) { + imagefilter($this->im, IMG_FILTER_GAUSSIAN_BLUR); + } + $this->ReduceImage(); + + if ($this->debug) { + imagestring($this->im, 1, 1, $this->height - 8, + "$text {$fontcfg['font']} " . round((microtime(true) - $ini) * 1000) . "ms", + $this->GdFgColor + ); + } + + /** Output */ + $this->WriteImage(); + $this->Cleanup(); + } + + /** + * Creates the image resources + */ + protected function ImageAllocate() { + // Cleanup + if (!empty($this->im)) { + imagedestroy($this->im); + } + + $this->im = imagecreatetruecolor($this->width * $this->scale, $this->height * $this->scale); + + // Background color + $this->GdBgColor = imagecolorallocate($this->im, + $this->backgroundColor[0], + $this->backgroundColor[1], + $this->backgroundColor[2] + ); + imagefilledrectangle($this->im, 0, 0, $this->width * $this->scale, $this->height * $this->scale, $this->GdBgColor); + + // Foreground color + $color = $this->colors[mt_rand(0, sizeof($this->colors) - 1)]; + $this->GdFgColor = imagecolorallocate($this->im, $color[0], $color[1], $color[2]); + + // Shadow color + if (!empty($this->shadowColor) && is_array($this->shadowColor) && sizeof($this->shadowColor) >= 3) { + $this->GdShadowColor = imagecolorallocate($this->im, + $this->shadowColor[0], + $this->shadowColor[1], + $this->shadowColor[2] + ); + } + } + + /** + * Text generation + * + * @return string Text + */ + protected function GetCaptchaText() { + $text = $this->GetDictionaryCaptchaText(); + if (!$text) { + $text = $this->GetRandomCaptchaText(); + } + return $text; + } + + /** + * Random text generation + * + * @return string Text + */ + protected function GetRandomCaptchaText($length = null) { + if (empty($length)) { + $length = rand($this->minWordLength, $this->maxWordLength); + } + + $words = "abcdefghijlmnopqrstvwyz"; + $vocals = "aeiou"; + + $text = ""; + $vocal = rand(0, 1); + for ($i = 0; $i < $length; $i++) { + if ($vocal) { + $text .= substr($vocals, mt_rand(0, 4), 1); + } else { + $text .= substr($words, mt_rand(0, 22), 1); + } + $vocal = !$vocal; + } + return $text; + } + + /** + * Random dictionary word generation + * + * @param boolean $extended Add extended "fake" words + * @return string Word + */ + function GetDictionaryCaptchaText($extended = false) { + if (empty($this->wordsFile)) { + return false; + } + + // Full path of words file + if (substr($this->wordsFile, 0, 1) == '/') { + $wordsfile = $this->wordsFile; + } else { + $wordsfile = $this->resourcesPath . '/' . $this->wordsFile; + } + + if (!file_exists($wordsfile)) { + return false; + } + + $fp = fopen($wordsfile, "r"); + $length = strlen(fgets($fp)); + if (!$length) { + return false; + } + $line = rand(1, (filesize($wordsfile) / $length) - 2); + if (fseek($fp, $length * $line) == -1) { + return false; + } + $text = trim(fgets($fp)); + fclose($fp); + + /** Change ramdom volcals */ + if ($extended) { + $text = preg_split('//', $text, -1, PREG_SPLIT_NO_EMPTY); + $vocals = array('a', 'e', 'i', 'o', 'u'); + foreach ($text as $i => $char) { + if (mt_rand(0, 1) && in_array($char, $vocals)) { + $text[$i] = $vocals[mt_rand(0, 4)]; + } + } + $text = implode('', $text); + } + + return $text; + } + + /** + * Horizontal line insertion + */ + protected function WriteLine() { + $x1 = $this->width * $this->scale * .15; + $x2 = $this->textFinalX; + $y1 = rand($this->height * $this->scale * .40, $this->height * $this->scale * .65); + $y2 = rand($this->height * $this->scale * .40, $this->height * $this->scale * .65); + $width = $this->lineWidth / 2 * $this->scale; + + for ($i = $width * -1; $i <= $width; $i++) { + imageline($this->im, $x1, $y1 + $i, $x2, $y2 + $i, $this->GdFgColor); + } + } + + /** + * Text insertion + */ + protected function WriteText($text, $fontcfg = array()) { + if (empty($fontcfg)) { + // Select the font configuration + $fontcfg = $this->fonts[array_rand($this->fonts)]; + } + + $fontfile = $fontcfg['font']; + + /** Increase font-size for shortest words: 9% for each glyph missing */ + $lettersMissing = $this->maxWordLength - strlen($text); + $fontSizefactor = 1 + ($lettersMissing * 0.09); + + // Text generation (char by char) + $x = 20 * $this->scale; + $y = round(($this->height * 27 / 40) * $this->scale); + $length = strlen($text); + for ($i = 0; $i < $length; $i++) { + $degree = rand($this->maxRotation * -1, $this->maxRotation); + $fontsize = rand($fontcfg['minSize'], $fontcfg['maxSize']) * $this->scale * $fontSizefactor; + $letter = substr($text, $i, 1); + + if ($this->shadowColor) { + $coords = imagettftext($this->im, $fontsize, $degree, + $x + $this->scale, $y + $this->scale, + $this->GdShadowColor, $fontfile, $letter); + } + $coords = imagettftext($this->im, $fontsize, $degree, + $x, $y, + $this->GdFgColor, $fontfile, $letter); + $x += ($coords[2] - $x) + ($fontcfg['spacing'] * $this->scale); + } + + $this->textFinalX = $x; + } + + /** + * Wave filter + */ + protected function WaveImage() { + // X-axis wave generation + $xp = $this->scale * $this->Xperiod * rand(1, 3); + $k = rand(0, 100); + for ($i = 0; $i < ($this->width * $this->scale); $i++) { + imagecopy($this->im, $this->im, + $i - 1, sin($k + $i / $xp) * ($this->scale * $this->Xamplitude), + $i, 0, 1, $this->height * $this->scale); + } + + // Y-axis wave generation + $k = rand(0, 100); + $yp = $this->scale * $this->Yperiod * rand(1, 2); + for ($i = 0; $i < ($this->height * $this->scale); $i++) { + imagecopy($this->im, $this->im, + sin($k + $i / $yp) * ($this->scale * $this->Yamplitude), $i - 1, + 0, $i, $this->width * $this->scale, 1); + } + } + + /** + * Reduce the image to the final size + */ + protected function ReduceImage() { + // Reduzco el tama�o de la imagen + $imResampled = imagecreatetruecolor($this->width, $this->height); + imagecopyresampled($imResampled, $this->im, + 0, 0, 0, 0, + $this->width, $this->height, + $this->width * $this->scale, $this->height * $this->scale + ); + imagedestroy($this->im); + $this->im = $imResampled; + } + + /** + * File generation + */ + protected function WriteImage() { + if ($this->imageFormat == 'png' && function_exists('imagepng')) { + imagealphablending($this->im, true); + imagesavealpha($this->im, false); + imagecolortransparent($this->im, $this->GdBgColor); + + header("Content-type: image/png"); + imagepng($this->im); + } else { + header("Content-type: image/jpeg"); + imagejpeg($this->im, null, 80); + } + } + + /** + * Cleanup + */ + protected function Cleanup() { + imagedestroy($this->im); + } +} diff --git a/inc/defines.php b/inc/defines.php index 339bcc8..d1392ea 100644 --- a/inc/defines.php +++ b/inc/defines.php @@ -30,6 +30,9 @@ if (!defined('TINYIB_WEBM')) { if (!defined('TINYIB_NOFILEOK')) { define('TINYIB_NOFILEOK', false); } +if (!defined('TINYIB_CAPTCHA')) { + define('TINYIB_CAPTCHA', false); +} if (!defined('TINYIB_REQMOD')) { define('TINYIB_REQMOD', 'disable'); } diff --git a/inc/flatfile/flatfile_utils.php b/inc/flatfile/flatfile_utils.php index 8f5b1cd..0326dd0 100644 --- a/inc/flatfile/flatfile_utils.php +++ b/inc/flatfile/flatfile_utils.php @@ -71,9 +71,9 @@ class TableUtils { /** Uses 'define' to create global constants for all the column names */ function createDefines(&$tables) { foreach ($tables as $tablename => $discard) { - $tabledef = & $tables[$tablename]; // PHP4 compatible + $tabledef = &$tables[$tablename]; // PHP4 compatible foreach ($tabledef as $colname => $discard) { - $coldef = & $tabledef[$colname]; + $coldef = &$tabledef[$colname]; define(strtoupper($tablename) . '_' . $colname, $coldef->index); } } diff --git a/inc/fonts/LICENSE b/inc/fonts/LICENSE new file mode 100644 index 0000000..63d5302 --- /dev/null +++ b/inc/fonts/LICENSE @@ -0,0 +1,203 @@ +Font data copyright Google 2012 + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/inc/fonts/roboto_bold.ttf b/inc/fonts/roboto_bold.ttf new file mode 100644 index 0000000..aaf374d Binary files /dev/null and b/inc/fonts/roboto_bold.ttf differ diff --git a/inc/fonts/roboto_regular.ttf b/inc/fonts/roboto_regular.ttf new file mode 100644 index 0000000..3e6e2e7 Binary files /dev/null and b/inc/fonts/roboto_regular.ttf differ diff --git a/inc/functions.php b/inc/functions.php index 5804ada..372b086 100644 --- a/inc/functions.php +++ b/inc/functions.php @@ -187,8 +187,8 @@ function writePage($filename, $contents) { } function fixLinksInRes($html) { - $search = array(' href="css/', ' src="js/', ' href="src/', ' href="thumb/', ' href="res/', ' href="imgboard.php', ' href="favicon.ico', 'src="thumb/', ' action="imgboard.php'); - $replace = array(' href="../css/', ' src="../js/', ' href="../src/', ' href="../thumb/', ' href="../res/', ' href="../imgboard.php', ' href="../favicon.ico', 'src="../thumb/', ' action="../imgboard.php'); + $search = array(' href="css/', ' src="js/', ' href="src/', ' href="thumb/', ' href="res/', ' href="imgboard.php', ' href="favicon.ico', 'src="thumb/', 'src="inc/', ' action="imgboard.php'); + $replace = array(' href="../css/', ' src="../js/', ' href="../src/', ' href="../thumb/', ' href="../res/', ' href="../imgboard.php', ' href="../favicon.ico', 'src="../thumb/', 'src="../inc/', ' action="../imgboard.php'); return str_replace($search, $replace, $html); } @@ -221,6 +221,21 @@ function deletePostImages($post) { } } +function checkCAPTCHA() { + if (!TINYIB_CAPTCHA) { + return; // CAPTCHA is disabled + } + + $captcha = isset($_POST['captcha']) ? strtolower(trim($_POST['captcha'])) : ''; + $captcha_solution = isset($_SESSION['tinyibcaptcha']) ? strtolower(trim($_SESSION['tinyibcaptcha'])) : ''; + + if ($captcha == '') { + fancyDie('Please enter the CAPTCHA text.'); + } else if ($captcha != $captcha_solution) { + fancyDie('Incorrect CAPTCHA text entered. Please try again.
Click the image to retrieve a new CAPTCHA.'); + } +} + function checkBanned() { $ban = banByIP($_SERVER['REMOTE_ADDR']); if ($ban) { diff --git a/inc/html.php b/inc/html.php index 9408f85..c82d0c9 100644 --- a/inc/html.php +++ b/inc/html.php @@ -214,8 +214,19 @@ EOF; $file_input_html = ''; $unique_posts_html = ''; - if (TINYIB_REQMOD != 'disable') { - $reqmod_html = '
  • All posts' . (TINYIB_REQMOD == 'files' ? ' with a file attached' : '') . ' will be moderated before being shown.
  • '; + $captcha_html = ''; + if (TINYIB_CAPTCHA) { + $captcha_html = << + + CAPTCHA + + +   (enter the text below)
    + CAPTCHA + + +EOF; } if (TINYIB_PIC || TINYIB_WEBM || TINYIB_SWF) { @@ -238,6 +249,10 @@ EOF; EOF; } + if (TINYIB_REQMOD != 'disable') { + $reqmod_html = '
  • All posts' . (TINYIB_REQMOD == 'files' ? ' with a file attached' : '') . ' will be moderated before being shown.
  • '; + } + $thumbnails_html = ''; if (TINYIB_PIC) { $thumbnails_html = "
  • Images greater than $maxdimensions will be thumbnailed.
  • "; @@ -298,13 +313,14 @@ EOF; + $captcha_html $file_input_html Password -  (for post and file deletion) +   (for post and file deletion) diff --git a/js/tinyib.js b/js/tinyib.js index c7e4b51..aa7e5d8 100644 --- a/js/tinyib.js +++ b/js/tinyib.js @@ -23,6 +23,21 @@ function quotePost(postID) { 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"; + } + + return false; +} + document.addEventListener('DOMContentLoaded', function () { var newpostpassword = document.getElementById("newpostpassword"); if (newpostpassword) { diff --git a/settings.default.php b/settings.default.php index 240f410..fbefe1e 100644 --- a/settings.default.php +++ b/settings.default.php @@ -14,6 +14,7 @@ define('TINYIB_MODPASS', ""); // Moderators only have access to delete ( // Board description and behavior define('TINYIB_BOARD', "b"); // Unique identifier for this board using only letters and numbers define('TINYIB_BOARDDESC', "TinyIB"); // Displayed at the top of every page +define('TINYIB_CAPTCHA', false); // Reduce spam by requiring users to pass a CAPTCHA when posting (click Rebuild All in the management panel after enabling) define('TINYIB_REQMOD', "disable"); // Require moderation before displaying posts: disable / files / all (see README for instructions, only MySQL is supported) // Board appearance