diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..bdb0cab --- /dev/null +++ b/.gitattributes @@ -0,0 +1,17 @@ +# Auto detect text files and perform LF normalization +* text=auto + +# Custom for Visual Studio +*.cs diff=csharp + +# Standard to msysgit +*.doc diff=astextplain +*.DOC diff=astextplain +*.docx diff=astextplain +*.DOCX diff=astextplain +*.dot diff=astextplain +*.DOT diff=astextplain +*.pdf diff=astextplain +*.PDF diff=astextplain +*.rtf diff=astextplain +*.RTF diff=astextplain diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0737778 --- /dev/null +++ b/.gitignore @@ -0,0 +1,221 @@ +################# +## Eclipse +################# + +*.pydevproject +.project +.metadata +bin/ +tmp/ +*.tmp +*.bak +*.swp +*~.nib +local.properties +.classpath +.settings/ +.loadpath + +# External tool builders +.externalToolBuilders/ + +# Locally stored "Eclipse launch configurations" +*.launch + +# CDT-specific +.cproject + +# PDT-specific +.buildpath + + +################# +## Visual Studio +################# + +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.sln.docstates + +# Build results + +[Dd]ebug/ +[Rr]elease/ +x64/ +build/ +[Bb]in/ +[Oo]bj/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +*_i.c +*_p.c +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.log +*.scc + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +*.ncrunch* +.*crunch*.local.xml + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.Publish.xml +*.pubxml +*.publishproj + +# NuGet Packages Directory +## TODO: If you have NuGet Package Restore enabled, uncomment the next line +#packages/ + +# Windows Azure Build Output +csx +*.build.csdef + +# Windows Store app package directory +AppPackages/ + +# Others +sql/ +*.Cache +ClientBin/ +[Ss]tyle[Cc]op.* +~$* +*~ +*.dbmdl +*.[Pp]ublish.xml +*.pfx +*.publishsettings + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file to a newer +# Visual Studio version. Backup files are not needed, because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +App_Data/*.mdf +App_Data/*.ldf + +############# +## Windows detritus +############# + +# Windows image file caches +Thumbs.db +ehthumbs.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Mac crap +.DS_Store + + +############# +## Python +############# + +*.py[cod] + +# Packages +*.egg +*.egg-info +dist/ +build/ +eggs/ +parts/ +var/ +sdist/ +develop-eggs/ +.installed.cfg + +# Installer logs +pip-log.txt + +# Unit test / coverage reports +.coverage +.tox + +#Translations +*.mo + +#Mr Developer +.mr.developer.cfg + +############# +## ninechan +############# +config.php diff --git a/README.md b/README.md index 1bbe57f..4823356 100644 --- a/README.md +++ b/README.md @@ -10,11 +10,11 @@ When downloading ninechan make sure to download it from the Releases tab thing a Requirements ------------ -| *Server-Side* | *Client-Side* | -| ---------------------- | ---------------------------- | -| PHP >= 5.3 | Enabled JavaScript | -| MySQL >= 4 | CSS Compatibility | -| Short PHP Tags | Cookies enabled | +| *Server-Side* | *Client-Side* | +| ---------------------------------- | ---------------------------- | +| PHP >= 5.3 | Enabled JavaScript | +| Any PDO compatible Database Engine | CSS Compatibility | +| Short PHP Tags | Cookies enabled | Features -------- @@ -30,4 +30,4 @@ Features Help ---- -Although I don't really see when you need help with the board just send me an email (email address is on github profile) or ask about it on one of the board on http://forum.flash.moe/viewforum.php?f=5 +Although I don't really see when you need help with the script just send me an email (email address is on github profile) or ask about it in the issues section diff --git a/bbcodes.json b/bbcodes.json new file mode 100644 index 0000000..a84aaff --- /dev/null +++ b/bbcodes.json @@ -0,0 +1,11 @@ +{ + "\/\\[b\\](.*?)\\[\\\/b\\]\/is": "<b>$1<\/b>", + "\/\\[i\\](.*?)\\[\\\/i\\]\/is": "<i>$1<\/i>", + "\/\\[u\\](.*?)\\[\\\/u\\]\/is": "<u>$1<\/u>", + "\/\\[url\\=(.*?)\\](.*?)\\[\\\/url\\]\/is": "<a href=\"$1\" rel=\"nofollow\" title=\"$2 - $1\">$2<\/a>", + "\/\\[url\\](.*?)\\[\\\/url\\]\/is": "<a href=\"$1\" rel=\"nofollow\" title=\"$1\">$1<\/a>", + "\/\\[spoiler\\](.*?)\\[\\\/spoiler\\]\/is": "<span class=\"spoiler\">$1<\/span>", + "\/>>(.*[0-9])\/i": "<a class=\"lquote\" href=\"#$1\">>>$1<\/a>", + "\/^>(.*?)$\/im": "<span class=\"quote\">>$1<\/span>", + "\/^.*(youtu.be|youtube.com\\\/embed\\\/|watch\\?v=|\\&v=)([^!<>@&#\\\/\\s]*)\/is": "<iframe style=\"width:425px;height:350px;\" src=\"https:\/\/www.youtube.com\/embed\/$2\" frameborder=\"0\" allowfullscreen><\/iframe>" +} diff --git a/changelog.txt b/changelog.txt index e4ecf85..b3476d7 100644 --- a/changelog.txt +++ b/changelog.txt @@ -121,7 +121,22 @@ Version 1.10.2e (06-12-2014): Indonesian language file added (thanks to Flappyzor) Version 1.11alpha1 (06-12-2014): ------------------------------- +-------------------------------- Made configuration variables more overviewable (WILL break things if you don't update your configuration file). Put version number in a define at the top of the file to make changing it easier in case I decide to use it elsewhere. Why was the doctype statement all the way on the top above the PHP code? + +Version 1.11alpha2 (16-12-2014): +-------------------------------- +Implement language version checking. + +-- 1.11alpha3 and alpha4 have been included in 2.0 -- + +Version 2.0 (12-05-2015): +-------------------------------- +Switch to PDO from MySQLi +Change config and language handling +Switch to ReCAPTCHA v2 +Redid JavaScript backend +Implemented thread bumping +Added SQL structure file diff --git a/config.example.php b/config.example.php new file mode 100644 index 0000000..7548b94 --- /dev/null +++ b/config.example.php @@ -0,0 +1,112 @@ +<?php +// Define configuration arrays +$sql=array();$ninechan=array(); + +/// Database Connection /// +// PDO DSN http://php.net/manual/en/pdo.drivers.php +$sql['dsn'] = "mysql:host=localhost;dbname=ninechan;"; + +// Database Username +$sql['user'] = "ninechan"; + +// Database Password +$sql['pass'] = ""; + +// Database Table +$sql['table'] = ""; + + +/// Board Settings /// +// Cookie Prefix (for if you have multiple boards and you want to keep the cookies apart). +$ninechan['cookiePrefix'] = "nine_"; + +// Path on the server for the cookies +$ninechan['cookiePath'] = "/"; + +// The time cookies should live +$ninechan['cookieLifetime'] = 604800; + +// Set if errors should be displayed +$ninechan['exposeErrors'] = true; + +// Set the language. Must match filename from file in /lang/ folder (excluding .php). +$ninechan['lang'] = "en"; + +// Define if the board should be open(false) or closed(true) +$ninechan['closed'] = false; + +// Set the message displayed when the board is closed +$ninechan['closedReason'] = "Maintenance"; + +// Board title +$ninechan['title'] = "ninechan board"; + +// Character set used by the board +$ninechan['charset'] = "utf-8"; + +// Specify the board description (set to null to disable) +$ninechan['desc'] = "Live development board"; + +// Set the paths to the CSS styles and their names (set to null to disable styles), please refrain from using special characters in titles +$ninechan['styles'] = array( + "ninechan.css" => "ninechan blue", + "ninechan2.css" => "ninechan red" +); + +// Set if the version number should be displayed, false is recommended +$ninechan['showVersion'] = true; + +// Amount of threads that should be displayed on a page of the index +$ninechan['threadsPerPage'] = 20; + +// Set the minimum character length of a title +$ninechan['titleMinLength'] = 5; + +// Set the maximum character length of a title +$ninechan['titleMaxLength'] = 40; + +// Set the minimum character length of a comment +$ninechan['commentMinLength'] = 5; + +// Set the maximum character length of a comment +$ninechan['commentMaxLength'] = 3000; + +// Specify the Mod Password for moderating posts +$ninechan['modPass'] = "change this if you don't want your board to get hacked"; + +// Specify the "encrypted" tripcodes of the admins (e.g. QphRmfeTkY) +$ninechan['adminTrip'] = array( + "QphRmfeTkY" +); + +// Specify the "encrypted" tripcodes of mods (e.g. QphRmfeTkY) +$ninechan['modTrip'] = array( + "QphRmfeTkY" +); + +// Specify the name used for Anonymous posters +$ninechan['anonName'] = "Anonymous"; + +// Specify whether admins should be Anonymous (0. No, 1. Fully anon, 2. Only hide trip) +$ninechan['adminsAreAnon'] = 0; + +// Specify whether mods should be Anonymous (0. No, 1. Fully anon, 2. Only hide trip) +$ninechan['modsAreAnon'] = 0; + +// Specify whether anonymous posting is forced or not +$ninechan['forcedAnon'] = false; + +// Specify in what way dates and times should be ordered following PHP's date() function (default: D Y-m-d H:i T) +$ninechan['dateFormat'] = 'D Y-m-d H:i T'; + +// JSON file containing BBcodes +$ninechan['bbCodes'] = 'bbcodes.json'; + +// Set whether reCAPTCHA should be enabled (reCAPTCHA PHP Library required). +$ninechan['reCaptcha'] = true; + +// reCAPTCHA Public key +$ninechan['reCaptchaPublic'] = "6LdQwAYTAAAAAKSW9Q7U6qS6HFTwotccCMr1Ejri"; + +// reCAPTCHA Private key +$ninechan['reCaptchaPrivate'] = "6LdQwAYTAAAAAJ3NUhUmFyc814B7AM1LGbVwWKp2"; diff --git a/config.php b/config.php deleted file mode 100644 index 25acb7d..0000000 --- a/config.php +++ /dev/null @@ -1,52 +0,0 @@ -<?php -// Define configuration arrays -$sql = array(); -$ninechan = array(); - -// Database Connection Settings -$sql['dsn'] = "mysql:host=localhost; dbname=ninechan;"; // PDO DSN -$sql['user'] = "root"; // Database Username -$sql['pass'] = ""; // Database Password -$sql['table'] = "nine"; // Database Table - -// Board Settings -$ninechan['cookiePrefix'] = "nine_"; // Cookie Prefix (for if you have multiple boards and you want to keep the cookies apart). -$ninechan['cookiePath'] = "/"; // Path on the server for the cookies -$ninechan['cookieLifetime'] = 604800; // The time cookies should live -$ninechan['exposeErrors'] = false; // Display errors -$ninechan['lang'] = "en"; // Set the language. Must match filename from file in /lang/ folder (excluding .php). -$ninechan['closed'] = false; // open(false) or close(true) the board -$ninechan['closedReason'] = "Maintenance"; // Set the message displayed when the board is closed -$ninechan['disablePosting'] = true; // Turn posting on or off -$ninechan['title'] = "ninechan"; // Board title -$ninechan['charset'] = "UTF-8"; // Character set used by the board -$ninechan['desc'] = "best shitty board software"; // Specify the board description (set to null to disable) -$ninechan['styles'] = array( // Paths to the CSS styles and their names (set to null to disable styles) - "ninechan.css" => "ninechan blue", - "ninechan2.css" => "ninechan red" - ); -$ninechan['showVersion'] = false; // Display version number in the footer, false is recommended -$ninechan['sage'] = false; // Should threads "disappear" after a certain amount of new threads (true = yes/false = no) -$ninechan['sageLimit'] = 20; // If "sage" is set to true, how many threads should be displayed -$ninechan['titleMinLength'] = 5; // Minimum character length of a title -$ninechan['titleMaxLength'] = 40; // Maximum character length of a title -$ninechan['commentMinLength'] = 5; // Minimum character length of a comment -$ninechan['commentMaxLength'] = 3000; // Maximum character length of a comment -$ninechan['modPass'] = "changethis"; // Password to the moderation panel -$ninechan['adminTrip'] = array( // Hashed tripcodes of the admins (e.g. QphRmfeTkY) - "first trip", - "second trip" - ); -$ninechan['modTrip'] = array( // Hashed tripcodes of moderators (e.g. QphRmfeTkY) - "first trip", - "second trip" - ); -$ninechan['anonName'] = "Anonymous"; // Name used for Anonymous posters -$ninechan['adminsAreAnon'] = 0; // Should Admins be Anonymous (0. No, 1. Fully anon, 2. Only hide trip) -$ninechan['modsAreAnon'] = 0; // Should Mods be Anonymous (0. No, 1. Fully anon, 2. Only hide trip) -$ninechan['forcedAnon'] = false; // Force Anonymous posting? -$ninechan['dateFormat'] = 'D Y-m-d H:i T'; // Date and time formatting, should be ordered following the PHP date() function (default: D Y-m-d H:i T) -$ninechan['reCaptcha'] = false; // Enable or disable reCAPTCHA (reCAPTCHA PHP Library required) -$ninechan['reCaptchaLib'] = "recaptcha.php"; // Path to the reCAPTCHA PHP Library (only required if reCAPTCHA is enabled) -$ninechan['reCaptchaPublic'] = ""; // reCAPTCHA Public key -$ninechan['reCaptchaPrivate'] = ""; // reCAPTCHA Private key diff --git a/index.php b/index.php index a323c2f..0bd047c 100644 --- a/index.php +++ b/index.php @@ -6,78 +6,84 @@ */ // Set ninechan version, don't change this or it'll probably break things. -define('N_VERSION', '1.11alpha4'); +$version = '2.0'; -// Configuration files -require 'config.php'; // Include Configuration -include 'lang/' . $ninechan['lang'] . '.php'; // Include language file +// Language file versions this version is compatible with +$langCompat = [ + '2.0' +]; +// Include Configuration +require 'config.php'; + +// Getting configuration values +function getConfig($key) { + + // Make $ninechan global + global $ninechan; + + // Check if the key exists and return the proper string + return array_key_exists($key, $ninechan) ? $ninechan[$key] : null; + +} + +// Error messages +function error($data) { + + global $version; + + print '<!DOCTYPE html><html><head><meta charset="utf-8" /><title>ninechan error</title></head><body>'; + print $data; + print '<hr />ninechan '. $version .'</body></html>'; + exit; + +} + +// Include language file +include 'lang/'. getConfig('lang') .'.php'; // Error Reporting -error_reporting($ninechan['exposeErrors'] ? -1 : 0); +error_reporting(getConfig('exposeErrors') ? -1 : 0); +// Getting language string +function getLang($key) { + + // Make $language global + global $language; + + // Check if the key exists and return the proper string + return array_key_exists($key, $language) ? $language[$key] : 'Undefined index'; -// Check language version -if(LDATA_VERSION != N_VERSION) { - print '<h2>Your language file [' . $ninechan['lang'] . '] is outdated!</h2>'; - print 'Please update your language file from Version ' . LDATA_VERSION . ' to Version ' . N_VERSION . '.'; - exit; } -// Check dependencies -if(version_compare(phpversion(), '5.3.0', '<')) // PHP 5.3 or higher - die('<h2>' . L_PHP_OUTDATED . '</h2>'); - -if(!extension_loaded('PDO')) // Check if PHP Data Objects is available - die('<h2>' . L_SQL_FUNCTION . '</h2>'); - - -// Connect to SQL using PDO -try { - $sqldb = new PDO($sql['dsn'], $sql['user'], $sql['pass']); -} catch(PDOException $e) { // Catch connection error - print '<h2>' . L_SQL_CONNECT . '</h2>'; - die($e->getMessage()); -} - - -// Initialise Database -$sqldb->query( // Indented SQL, WOw ! - "CREATE TABLE IF NOT EXISTS - `" . $sql['table'] . "` - ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `title` text NOT NULL, - `name` text, - `trip` text, - `email` text, - `date` text NOT NULL, - `content` text NOT NULL, - `password` text NOT NULL, - `ip` text NOT NULL, - `op` int(1) NOT NULL, - `tid` int(11) NOT NULL, - `locked` int(1) NOT NULL, - `ban` int(1) NOT NULL, - `del` int(1) NOT NULL, - PRIMARY KEY (`id`) - ) - ENGINE=InnoDB - DEFAULT - charset=latin1;" -); - - // Cleaning strings -function removeSpecialChars($data) { - $data = htmlentities($data, ENT_QUOTES | ENT_IGNORE, "UTF-8"); - $data = stripslashes($data); - return $data; +function cleanString($string, $lower = false, $nospecial = false) { + + // Run common sanitisation function over string + $string = htmlentities($string, ENT_QUOTES | ENT_IGNORE, getConfig('charset')); + $string = stripslashes($string); + $string = strip_tags($string); + + // If set also make the string lowercase + if($lower) + $string = strtolower($string); + + // If set remove all characters that aren't a-z or 0-9 + if($nospecial) + $string = preg_replace('/[^a-z0-9]/', '', $string); + + // Return clean string + return $string; + } // Parsing tripcodes function parseTrip($name) { + + // Match ! or # and everything after it if(preg_match("/(#|!)(.*)/", $name, $matches)) { + + // Get the cap code $cap = $matches[2]; $cap = mb_convert_encoding($cap, 'SJIS', 'UTF-8'); $cap = str_replace('#', '', $cap); @@ -86,47 +92,32 @@ function parseTrip($name) { $cap = str_replace("'", ''', $cap); $cap = str_replace('<', '<', $cap); $cap = str_replace('>', '>', $cap); - $salt = substr($cap.'H.',1,2); + + // Create the salt + $salt = substr($cap .'H.', 1, 2); $salt = preg_replace('/[^.\/0-9:;<=>?@A-Z\[\\\]\^_`a-z]/', '.', $salt); $salt = strtr($salt, ':;<=>?@[\]^_`', 'ABCDEFGabcdef'); + + // Generate tripcode $trip = substr(crypt($cap, $salt), -10); + + // Return tripcode return $trip; + } + } -// Parsing BBcodes -function parseBBcode($content){ - $bbcodecatch = array( - '/\[b\](.*?)\[\/b\]/is', - '/\[i\](.*?)\[\/i\]/is', - '/\[u\](.*?)\[\/u\]/is', - '/\[url\=(.*?)\](.*?)\[\/url\]/is', - '/\[url\](.*?)\[\/url\]/is', - '/\[spoiler\](.*?)\[\/spoiler\]/is', - '/>>(.*[0-9])/i', - '/^>(.*?)$/im', - '/^.*(youtu.be|youtube.com\/embed\/|watch\?v=|\&v=)([^!<>@&#\/\s]*)/is' - ); - - $bbcodereplace = array( - '<b>$1</b>', - '<i>$1</i>', - '<u>$1</u>', - '<a href="$1" rel="nofollow" title="$2 - $1">$2</a>', - '<a href="$1" rel="nofollow" title="$1">$1</a>', - '<span class="spoiler">$1</span>', - '<a class="lquote" href="#$1">>>$1</a>', - '<span class="quote">>$1</span>', - '<object type="application/x-shockwave-flash" style="width:425px; height:350px;" data="http://www.youtube.com/v/$2"><param name="movie" value="http://www.youtube.com/v/$2" /></object>' - ); - - $content = preg_replace( - $bbcodecatch, - $bbcodereplace, - $content - ); - +// Parsing post tags +function parsePost($content){ + + // Get bbcodes file + $bbcodes = json_decode(file_get_contents(getConfig('bbCodes')), true); + + $content = preg_replace(array_flip($bbcodes), $bbcodes, $content); + return nl2br($content); + } // Generating Random Password @@ -141,614 +132,916 @@ function generatePassword() { return $pass; } - // Moderation function nMod($mode, $id, $action) { + + // Make SQL variables global global $sql, $sqldb; - + + // Switch to the proper mode switch($mode) { + // Banning a poster case 'ban': $prepare = "UPDATE `". $sql['table'] ."` SET `ban` = :action WHERE `id` = :id"; break; - + // Deleting a post case 'del': - $prepare = "UPDATE `". $sql['table'] ."` SET `del` = :action WHERE `id` = :id"; + $prepare = "DELETE FROM `". $sql['table'] ."` WHERE `id` = :id"; break; - + // Prune an entire thread case 'prune': - $prepare = "UPDATE `". $sql['table'] ."` SET `del` = :action WHERE `tid` = :id"; + $prepare = "DELETE FROM `". $sql['table'] ."` WHERE `tid` = :id"; break; - + // Lock a thread case 'lock': $prepare = "UPDATE `". $sql['table'] ."` SET `locked` = :action WHERE `tid` = :id"; break; - + // Return false if there's no proper option default: return false; + } - - $query = $sqldb->prepare($prepare); - - $query->bindParam(':id', $id, PDO::PARAM_INT); - $query->bindParam(':action', ($action ? '1' : '0'), PDO::PARAM_INT); - + + $query = $sqldb->prepare($prepare); + $action = $action ? '1' : '0'; + + $query->bindParam(':id', $id, PDO::PARAM_INT); + $query->bindParam(':action', $action, PDO::PARAM_INT); + $query->execute(); - + // Return true if successful return true; + } +// Board HTML header +function nHead() { -// reCaptcha -if($ninechan['reCaptcha']) - require $ninechan['reCaptchaLib']; + $header = '<!DOCTYPE html> +<html> + <head> + <meta charset="'. getConfig('charset') .'" /> + <title>'. getConfig('title') .'</title>'. + (getConfig('desc') ? '<meta name="description" content="'. getConfig('desc') .'" />' : '') + .'<script type="text/javascript" charset="'. getConfig('charset') .'" src="ninechan.js"></script> + <script type="text/javascript"> + ninechan.cookiePrefix = "'. getConfig('cookiePrefix') .'"; + + window.onload = function() { + ninechan.init(); + } + + </script>'; + + // Check if styles are enabled + if(getConfig('styles')) { + + // Take the array + $styles = getConfig('styles'); + + // Iterate over all styles + foreach($styles as $url => $name) { + + // Get the key of the first entry + $main = key($styles); + + // Append styles to the header + $header .= '<link rel="'. ($url == $main ? null : 'alternate ') .'stylesheet" type="text/css" href="'. $url .'" title="'. $name .'" '. ($url == $main ? null : 'disabled ') .'/>'; + + } + + } + + $header .= '</head> + <body> + <h1><a href="./">'. getConfig('title') .'</a></h1>'. + (getConfig('desc') ? ' <i>'. getConfig('desc') .'</i>' : '') + .'<hr />'; + + return $header; + +} + +// Board HTML footer +function nFoot() { + + // Make $version global + global $version; + + $footer = '<hr />'; + + // Check if styles are enabled + if(getConfig('styles')) { + + // Take the array + $styles = getConfig('styles'); + + $footer .= '<h6>'; + + // List every style + foreach($styles as $name) + $footer .= '[<a href="javascript:void(0);" onclick="ninechan.setStyle(\''.$name.'\');">'.$name.'</a>]'."\r\n"; + + $footer .= '</h6>'; + + } + + /* + Please retain the full copyright notice below including the link to flash.moe. + This not only gives respect to the amount of time given freely by the developer + but also helps build interest, traffic and use of ninechan and other projects. + */ + + $footer .= '<h6> + <a href="http://ninechan.flash.moe/" target="_blank">ninechan</a> + '. (getConfig('showVersion') ? $version : '') .' + © <a href="http://flash.moe/" target="_blank">Flashwave</a> + </h6> + </body> +</html>'; + + // Return the footer + return $footer; + +} + +// Setting cookies +function nCookie($name, $content) { + + // Execute setcookie() + setcookie( + getConfig('cookiePrefix') . $name, + $content, + time() + getConfig('cookieLifetime'), + getConfig('cookiePath'), + $_SERVER['SERVER_NAME'] + ); + +} + +// Check if the IP is banned +function checkBan($ip) { + + // Make SQL variables global + global $sql, $sqldb; + + // Base64 encode IP + $ip = base64_encode($ip); + + // Prepare the statement + $banCheck = $sqldb->prepare("SELECT * FROM `". $sql['table'] ."` WHERE `ip` = :ip AND `ban` = '1'"); + + // Append ip the statement + $banCheck->bindParam(':ip', $ip, PDO::PARAM_STR); + + // Execute statement + $banCheck->execute(); + + // Fetch array + $return = $banCheck->fetchAll(PDO::FETCH_ASSOC); + + // Return the array + return $return; + +} + +// Getting thread data +function getPosts($id = 0) { + + // Make SQL variables global + global $sql, $sqldb; + + // Prepare the statement + $getPosts = $sqldb->prepare("SELECT * FROM `". $sql['table'] ."` WHERE ". ($id ? "`tid` = :tid" : "`op` = '1'") ." ORDER BY `". ($id ? "id`" : "lastreply` DESC")); + + // Bind the ID to the statement + if($id) + $getPosts->bindParam(':tid', $id, PDO::PARAM_INT); + + // Execute statement + $getPosts->execute(); + + // Fetch array + $return = $getPosts->fetchAll(PDO::FETCH_BOTH); + + // Return the array + return $return; + +} + +function verifyCaptcha($response) { + + // Attempt to get the response + $resp = @file_get_contents('https://www.google.com/recaptcha/api/siteverify?secret='. getConfig('reCaptchaPrivate') .'&response='. $response); + + // In the highly unlikely case that it failed to get anything forge a false + if(!$resp) + error('Could not connect to the ReCAPTCHA server.'); + + // Decode the response JSON from the servers + $resp = json_decode($resp, true); + + // Return shit + return $resp; + +} + +// Check language version +if(!in_array($langVersion, $langCompat)) { + + print '<h2>The selected language file is incompatible with this version!</h2>'; + print 'The version your language file was created for is <b>'. $langVersion .'</b>.<br />'; + print 'Your version of ninechan is compatible with the following language file versions:<ul>'; + foreach($langCompat as $ver) print '<li>'. $ver; + print '</ul>'; + exit; + +} + +// Check dependencies +if(version_compare(phpversion(), '5.3.0', '<')) // PHP 5.3 or higher + error('<h2>'. getLang('PHP_OUTDATED') .'</h2>'); + +if(!extension_loaded('PDO')) // Check if PHP Data Objects is available + error('<h2>'. getLang('SQL_FUNCTION') .'</h2>'); + +// Connect to SQL using PDO +try { + $sqldb = new PDO($sql['dsn'], $sql['user'], $sql['pass']); +} catch(PDOException $e) { // Catch connection error + error('<h2>'. getLang('SQL_CONNECT') .'</h2>'. $e->getMessage()); +} + +// Initialise Database +$sqldb->query(" +CREATE TABLE IF NOT EXISTS `". $sql['table'] ."` ( + `id` int(16) unsigned NOT NULL AUTO_INCREMENT, + `title` varchar(255) COLLATE utf8_bin NOT NULL, + `name` varchar(255) COLLATE utf8_bin DEFAULT NULL, + `trip` varchar(255) COLLATE utf8_bin DEFAULT NULL, + `email` varchar(255) COLLATE utf8_bin DEFAULT NULL, + `date` varchar(255) COLLATE utf8_bin NOT NULL, + `content` text COLLATE utf8_bin NOT NULL, + `password` varchar(255) COLLATE utf8_bin NOT NULL, + `ip` varchar(255) COLLATE utf8_bin NOT NULL, + `op` tinyint(1) unsigned NOT NULL DEFAULT '1', + `tid` int(16) unsigned NOT NULL DEFAULT '0', + `locked` tinyint(1) unsigned NOT NULL DEFAULT '0', + `ban` tinyint(1) unsigned NOT NULL DEFAULT '0', + `lastreply` int(11) unsigned NOT NULL DEFAULT '0', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; +"); // Session session_start(); // Start a session $auth = @$_SESSION['mod']; // Set an alias for mod -?> -<!DOCTYPE html> -<html> - <head> - <meta http-equiv="Content-type" content="text/html; charset=<?=$ninechan['charset'];?>" /> - <title><?=$ninechan['title'];?></title> - <?=($ninechan['desc'] ? '<meta name="description" content="'.$ninechan['desc'].'" />' : null);?> - <script type="text/javascript" charset="utf-8" src="ninechan.js"></script> - <script type="text/javascript"> - ninechan.cookiePrefix = "<?=$ninechan['cookiePrefix'];?>"; - - window.onload = function() { - ninechan.init(); - } - </script> - <?php - if($ninechan['styles']) { // Check if styles are enabled - foreach($ninechan['styles'] as $styleUrl => $styleName) { // Get styles from array - reset($ninechan['styles']); // Reset Array - $mainStyle = key($ninechan['styles']); // Get first entry - print '<link rel="'. ($styleUrl == $mainStyle ? null : 'alternate ') .'stylesheet" type="text/css" href="'. $styleUrl .'" title="'. $styleName .'" '. ($styleUrl == $mainStyle ? null : 'disabled ') .'/>'; // List every style - } - } - ?> - </head> - <body> - <h1><a href="./"><?=$ninechan['title'];?></a></h1> - <?=($ninechan['desc'] ? ' <i>'.$ninechan['desc'].'</i>' : null);?> - <hr /> - <?php - if($ninechan['closed']) { // Exit if board is set as closed in the config file - print L_BOARD_CLOSED."<br /><i>".L_REASON.": ".$ninechan['closedReason']."</i>"; - exit; - } - - $banCheck = ($sqldb->query("SELECT * FROM `".$sql['table']."` WHERE `ip`='".base64_encode($_SERVER['REMOTE_ADDR'])."' AND `ban`='1'")->rowCount() ? true : false); // Check if poster IP is banned, using num_rows because COUNT(*) didn't want to work or I did something wrong - - if($banCheck) - print '<div class="banmsg">'.L_USERBANNEDMSG.'</div><hr />'; - - print '<div class="banmsg">Everything is about to be broken and you can\'t do anything about it.</div><hr />'; - - if(!isset($_COOKIE[$ninechan['cookiePrefix'].'pass'])) { // Check if pass cookie is set if not set it - setcookie( // Generate random password and assign it to cookie - $ninechan['cookiePrefix'] . "pass", - generatePassword(), - time() + $ninechan['cookieLifetime'], - "/", - $_SERVER['SERVER_NAME'] - ); - } - - if(isset($_GET['v'])) { - switch($_GET['v']) { - // Main index - case 'index': - print '<h2>'.L_THREADS.'</h2>'; // Section title - print '<h3><a href="?v=post">'.L_NEWTHREAD.'</a></h3>'; // New thread link - - // Query to get OP posts - $getThreads = $sqldb->query("SELECT * FROM `".$sql['table']."` WHERE `del`='0' AND `op`='1' ORDER BY `date` desc".($ninechan['sage'] ? " LIMIT ".$ninechan['sageLimit'] : null)); - - // List posts - if(!$getThreads->rowCount()) { // Check if there's more than 1 post - print '<h3>'.L_EMPTY.'</h3>'; // Return L_EMPTY otherwise - } else { - print '<ol>'; - - while($thread = $getThreads->fetch()) { - // Need to figure out why the w3c validator does not like the & in a place where it should be... - print '<li><a href="?v=thread&t='.$thread['tid'].'">'.$thread['title'].'</a>'; - } - - print '</ol>'; - } - - print '<h3><a href="?v=post">'.L_NEWTHREAD.'</a></h3>'; // New thread link + +// Print the header +print nHead(); + +// Exit if board is set as closed in the config file +if($ninechan['closed']) { + + print '<h3>'. getLang('BOARD_CLOSED') .'</h3>'. getLang('REASON') .': '. getConfig('closedReason') .''; + print nFoot(); + exit; + +} + +// Check if the current IP is banned +if(checkBan($_SERVER['REMOTE_ADDR'])) + print '<div class="banmsg">'. getLang('USERBANNEDMSG') .'</div><hr />'; + +// Check if pass cookie is set and set it if it isn't +if(!isset($_COOKIE[getConfig('cookiePrefix') .'pass'])) + nCookie('pass', generatePassword()); + +// Check if view variable is set +if(isset($_GET['v'])) { + + // Switch to proper view + switch($_GET['v']) { + + // Main index + case 'index': + // Section title + print '<h2>'. getLang('THREADS') .'</h2>'; + + // New thread link + print '<h3><a href="?v=post">'. getLang('NEWTHREAD') .'</a></h3>'; + + // Get threads + $threads = getPosts(); + + // If at least one post was returned print the list + if($threads) { + + print '<ol>'; + + foreach($threads as $thread) + print '<li><a href="?v=thread&t='. $thread['tid'] .'">'. $thread['title'] .'</a>'; + + print '</ol>'; + + } else // Else return EMPTY + print '<h3>'. getLang('EMPTY') .'</h3>'; + + // New thread link + print '<h3><a href="?v=post">'. getLang('NEWTHREAD') .'</a></h3>'; + break; + + // Thread view + case 'thread': + // Just return NONEXISTENT if t is invalid + if(!isset($_GET['t']) || !is_numeric($_GET['t'])) { + + print('<h3>'. getLang('NONEXISTENT') .'</h3>'); break; - - // Thread view - case 'thread': - if(!isset($_GET['t']) || !is_numeric($_GET['t'])) { // Just return L_NONEXISTENT if t is invalid - print L_NONEXISTENT; - break; - } - - // Set Thread ID variable - $threadId = preg_replace('/\D/', '', $_GET['t']); - - // Prepare statement to get the thread data - $getThread = $sqldb->prepare("SELECT * FROM `".$sql['table']."` WHERE `tid` = :tid AND `del` = '0' ORDER BY `id`"); - - // Append directives - $getThread->bindParam(':tid', $threadId, PDO::PARAM_INT); - - // Execute Statement - $getThread->execute(); - - if(!$getThread->rowCount()) { // Check if requested thread exists - print L_NONEXISTENT; // If not return L_NONEXISTENT - break; - } else { - // Get thread data - $threadData = $getThread->fetchAll(); - - // Iterate over the thread data - foreach($threadData as $postData) { - if($postData['op']) { // Assign thread variables if poster is OP - print '<h2>'.L_THREAD.': '.$postData['title'].'</h2>'; // Print L_THREAD and the name of the thread - - if($postData['locked']) // Check if thread is locked and if true display message - print '<h3>'.L_LOCKED.'</h3>'; - else // otherwise print reply button - print '<h3><a href=?v=post&t='.$postData['tid'].'>'.L_NEWREPLY.'</a></h3>'; - - // Mod tools - if($auth == $ninechan['modPass']) { - print '<font size="2">[<a href=?v=mod&del=purge&id='.$postData['id'].'>'.L_PURGE.'</a>]'; - if($postData['lock']) { - print ' [<a href="?v=mod&lock=false&id='.$postData['id'].'">'.L_UNLOCK.'</a>]</font>'; - } else { - print ' [<a href="?v=mod&lock=true&id='.$postData['id'].'">'.L_LOCK.'</a>]</font>'; - } - } - } - - // Set names to Anonymous if required in the configuration - if($ninechan['forcedAnon']) { - $posterName = $ninechan['anonName']; - $posterTrip = null; - } elseif($ninechan['modsAreAnon'] == 1 && in_array($row['trip'], $ninechan['modTrip'])) { // Check if forced anon for mods is enabled - $posterName = $ninechan['anonName']; - $posterTrip = null; - } elseif($ninechan['modsAreAnon'] == 2 && in_array($row['trip'], $ninechan['modTrip'])) { // Check if forced trip anon for mods is enabled - $posterName = $postData['name']; - $posterTrip = null; - } elseif($ninechan['adminsAreAnon'] == 1 && in_array($row['trip'], $ninechan['adminTrip'])) { // Check if forced anon for admins is enabled - $posterName = $ninechan['anonName']; - $posterTrip = null; - } elseif($ninechan['adminsAreAnon'] == 2 && in_array($row['trip'], $ninechan['adminTrip'])) { // Check if forced trip anon for admins is enabled - $posterName = $postData['name']; - $posterTrip = null; - } else { - if(empty($postData['name'])) { - $posterName = $ninechan['anonName']; - } else { - $posterName = $postData['name']; - } - if(!empty($post['trip'])){ - $posterTrip = ' <span class="trip">!'.$postData['trip'].'</span>'; - } else { - $posterTrip = null; - } - } - - // Print the regular fieldset for posts - print '<fieldset id="'.$postData['id'].'">'; - print '<legend><b>'.$postData['title'].'</b> <a href="#'.$postData['id'].'">'.L_BY.'</a> <b>'; - - if(!empty($postData['email'])) - print '<a href="mailto:'.$postData['email'].'">'.$posterName.$posterTrip.'</a>'; - else - print $posterName.$posterTrip; - - if(in_array($postData['trip'], $ninechan['adminTrip'])) // Check if tripcode is Admin - print ' <span class="admincap">## Admin</span>'; - elseif(in_array($postData['trip'], $ninechan['modTrip'])) // Check if tripcode is Mod - print ' <span class="modcap">## Mod</span>'; - - print '</b></legend>'; - - print parseBBcode($postData['content']); // Parse BBcodes on post content - print '<br /><br />'; - - print ($postData['ban'] ? '<b><font size="2" class="ban">'.L_POSTBANNED.'</font></b><br />' : null); - - - if($auth == $ninechan['modPass']) { - print '<font size=2>[<a href="?v=mod&del=true&id='.$postData['id'].'&t='.$postData['tid'].'">'.L_DELETE.'</a>] [<a href="?v=mod&ban='.($postData['ban'] ? 'false' : 'true').'&id='.$postData['id'].'&t='.$postData['tid'].'">'.($postData['ban'] ? L_UNBAN : L_BAN).'</a>] [IP: '.base64_decode($postData['ip']).']</font><br />'; // Regular mod tools - } - - print '<font size=2><i>'.date($ninechan['dateFormat'], $postData['date']).' <a href="#'.$postData['id'].'">No.</a> <a href="?v=post&t='.$postData['tid'].'&text=>>'.$postData['id'].'">'.$postData['id'].'</a> [<a href="?v=del&id='.$postData['id'].'" title="'.L_DELPOST.'">X</a>]</i></font>'; - - print '</fieldset>'; - } - - // Mod tools - if($auth == $ninechan['modPass']) { - print '<font size="2">[<a href=?v=mod&del=purge&id='.$threadData['id'].'>'.L_PURGE.'</a>]'; - if($threadData['lock']) { - print ' [<a href="?v=mod&lock=false&id='.$threadData['id'].'">'.L_UNLOCK.'</a>]</font>'; - } else { - print ' [<a href="?v=mod&lock=true&id='.$threadData['id'].'">'.L_LOCK.'</a>]</font>'; - } - } - - if($threadData[0]['locked']) // Check if thread is locked and if true display message - print '<h3>'.L_LOCKED.'</h3>'; - else // otherwise print reply button - print '<h3><a href=?v=post&t='.$threadData[0]['tid'].'>'.L_NEWREPLY.'</a></h3>'; - } - break; - - // Posting - case 'post': - // Check if user is banned and if so don't display the form at all - if($banCheck) { - print '<h2>'. L_USERBANNED .'</h2>'; - break; - } - - // Print "global" form elements - print '<form method="post" action="'. $_SERVER['PHP_SELF'] .'?v=submit">'; - print '<table id="postForm" class="postForm">'; - - // Check if a thread ID is set - if(isset($_GET['t'])) { - // If so make sure it's numeric - if(!is_numeric($_GET['t'])) { - print '<h2>'. L_NOTNUMERIC .'</h2>'; - print '<a href="'. $_SERVER['PHP_SELF'] .'?v=index">'. L_RETURN .'</a>'; - break; - } - - // Assign Thread ID - $threadId = preg_replace('/\D/', '', $_GET['t']); - - // Prepare statement to get thread information - $getData = $sqldb->prepare("SELECT * FROM `".$sql['table']."` WHERE `tid` = :tid AND `op` = '1' ORDER BY `id` LIMIT 1"); - - // Bind Parameters - $getData->bindParam(':tid', $threadId, PDO::PARAM_INT); - - // Execute statement - $getData->execute(); - - // Assign thread data to variable - $threadData = $getData->fetch(); - - // Print non-existent thread if nothing was found - if($threadData == NULL) { - print '<h2>'. L_NONEXISTENT .'</h2>'; - print '<a href="'. $_SERVER['PHP_SELF'] .'?v=index">'. L_RETURN .'</a>'; - break; - } - - // Since we're not creating a thread set newThread to false - $newThread = false; - - $locked = $threadData['locked']; - - // Don't display posting form if thread is locked - if($locked) { - print '<h2>'. L_LOCKEDMSG .'</h2>'; - print '<meta http-equiv="refresh" content="2; URL="./?v=thread&t='. $threadData['tid'] .'" />'; - } else { - print '<h2>'. L_RETO .' '. $threadData['title'] .' ['. $threadData['tid'] .']</h2>'; - print '<input type="hidden" name="tid" value="'. $threadData['tid'] .'" />'; - - $threadTitle = 'Re: '. $threadData['title']; - } - } else { - print '<h2>'. L_NEWTHREAD .'</h2>'; - - $newThread = true; - $locked = false; - } - - if(isset($_GET['text'])) - $threadText = $_GET['text']."\r\n"; + + } + + // Strip all non-numeric characters from the string and assign it to $threadId + $threadId = preg_replace('/\D/', '', $_GET['t']); + + // Get thread data + $thread = getPosts($threadId); + + // Check if the thread exists + if($thread) { + + // Print post title + print '<h2>'. getLang('THREAD') .': '. $thread[0]['title'] .'</h2>'; + + // Check if thread is locked and if true display message + if($thread[0]['locked']) + print '<h3>'. getLang('LOCKED') .'</h3>'; + else + print '<h3><a href=?v=post&t='. $thread[0]['tid'] .'>'. getLang('NEWREPLY') .'</a></h3>'; + + // Moderator tools + if($auth == $ninechan['modPass']) { + + print '<h6>'; + + // Purge button + print '[<a href=?v=mod&del=purge&id='. $thread[0]['tid'] .'>'. getLang('PURGE') .'</a>]'."\r\n"; + + if($thread[0]['locked']) + print '[<a href="?v=mod&lock=false&id='. $thread[0]['tid'] .'">'. getLang('UNLOCK') .'</a>]'; else - $threadText = null; - - if(!$locked) { //-- Only display post page if thread isn't locked - print '<tr><td>'. L_NAME .'</td><td><input name="name" type="text" value="'. @$_COOKIE[$ninechan['cookiePrefix'].'name'] .'" /></td></tr>'; - print '<tr><td>'. L_EMAIL .'</td><td><input name="email" type="text" value="'. @$_COOKIE[$ninechan['cookiePrefix'].'email'] .'" /></td></tr>'; - print '<tr><td>'. L_TITLE .'</td><td><input name="title" type="text" value="'. @$threadTitle .'" /></td></tr>'; - print '<tr><td>'. L_COMMENT .'</td><td><textarea name="content" rows="6" cols="48">'. @$threadText .'</textarea></td></tr>'; - if($ninechan['reCaptcha']) //-- Display reCaptcha if enabled in config - print '<tr><td>'. L_VERIFICATION .'</td><td>'. recaptcha_get_html($ninechan['reCaptchaPublic']) .'</td></tr>'; - print '<tr><td>'. L_PASSWORD .'</td><td><input name="password" type="password" placeholder="'.L_PASSWORDCONTEXT.'" value="'. @$_COOKIE[$ninechan['cookiePrefix'].'pass'] .'" /> <input value="'. L_SUBMIT .'" type="submit" /></td></tr>'; - print '</table></form>'; + print '[<a href="?v=mod&lock=true&id='. $thread[0]['tid'] .'">'. getLang('LOCK') .'</a>]'; + + print '</h6>'; + + } + + // Print every post + foreach($thread as $post) { + + // Set poster name + if(getConfig('forcedAnon')) { + + $posterName = getConfig('anonName'); + $posterTrip = null; + + // Check if forced anon for mods or admins is enabled + } elseif((getConfig('modsAreAnon') === 1 && in_array($post['trip'], getConfig('modTrip'))) || (getConfig('adminsAreAnon') === 1 && in_array($post['trip'], getConfig('adminTrip')))) { + + $posterName = getConfig('anonName'); + $posterTrip = null; + + // Check if forced trip anon for mods or admins is enabled + } elseif((getConfig('modsAreAnon') === 2 && in_array($post['trip'], getConfig('modTrip'))) || (getConfig('adminsAreAnon') === 2 && in_array($post['trip'], getConfig('adminTrip')))) { + + $posterName = $post['name']; + $posterTrip = null; + + } else { + + // Check if name is set + $posterName = (empty($post['name']) ? getConfig('anonName') : $post['name']); + + // Check if trip isset + $posterTrip = (empty($post['trip']) ? '' : ' <span class="trip">!'. $post['trip'] .'</span>'); + } + + print '<fieldset id="'. $post['id'] .'">'; + + print '<legend><b>'. $post['title'] .'</b> <a href="#'. $post['id'].'">'. getLang('BY') .'</a> <b>'; + + if(empty($post['email'])) + print $posterName . $posterTrip; + else + print '<a href="mailto:'. $post['email'] .'">'. $posterName . $posterTrip .'</a>'; + + if(in_array($post['trip'], getConfig('adminTrip'))) // Check if tripcode is Admin + print ' <span class="admincap">## Admin</span>'; + elseif(in_array($post['trip'], getConfig('modTrip'))) // Check if tripcode is Mod + print ' <span class="modcap">## Mod</span>'; + + print '</b></legend>'; + + // Parse BBcode and other things in the post content + print '<div class="postContent">'. parsePost($post['content']) .'</div><br />'; + + // Check if (USER WAS BANNED FOR THIS POST) + if($post['ban']) + print '<h6 class="ban">'. getLang('POSTBANNED') .'</h6>'; + + // Moderator tools + if($auth == $ninechan['modPass']) { + + print '<h6>'; + print '[<a href="?v=mod&del=true&id='. $post['id'] .'&t='. $post['tid'] .'">'. getLang('DELETE') .'</a>]'."\r\n"; + print '[<a href="?v=mod&ban='. ($post['ban'] ? 'false' : 'true') .'&id='. $post['id'] .'&t='. $post['tid'] .'">'. getLang($post['ban'] ? 'UNBAN' : 'L_BAN') .'</a>]'."\r\n"; + print '[IP: '.base64_decode($post['ip']).']'; + print '</h6>'; + + } + + // Date and ID + print '<h6><i>'. date(getConfig('dateFormat'), $post['date']) .' <a href="#'. $post['id'] .'">No.</a> <a href="?v=post&t='. $post['tid'] .'&text=>>'. $post['id'] .'">'. $post['id'] .'</a> [<a href="?v=del&id='. $post['id'] .'" title="'. getLang('DELPOST') .'">X</a>]</i></h6>'; + + print '</fieldset>'; + + } + + // Moderator tools + if($auth == $ninechan['modPass']) { + + print '<h6>'; + + // Purge button + print '[<a href=?v=mod&del=purge&id='. $thread[0]['tid'] .'>'. getLang('PURGE') .'</a>]'."\r\n"; + + if($thread[0]['locked']) + print '[<a href="?v=mod&lock=false&id='. $thread[0]['tid'] .'">'. getLang('UNLOCK') .'</a>]'; + else + print '[<a href="?v=mod&lock=true&id='. $thread[0]['tid'] .'">'. getLang('LOCK') .'</a>]'; + + print '</h6>'; + + } + + // Check if thread is locked and if true display message + if($thread[0]['locked']) + print '<h3>'. getLang('LOCKED') .'</h3>'; + else + print '<h3><a href=?v=post&t='. $thread[0]['tid'] .'>'. getLang('NEWREPLY') .'</a></h3>'; + + } else { + + // If not return NONEXISTENT and stop + print getLang('NONEXISTENT'); break; - - // Submitting posts - case 'submit': - if($banCheck) { - print '<h2>'.L_USERBANNED.'</h2>'; - break; - } - - $submitData = array(); // Assign array to variable so we can store things in it later - - // Check reCaptcha - $fucked = false; - if($ninechan['reCaptcha']) { - $reCaptcha = recaptcha_check_answer($ninechan['reCaptchaPrivate'], $_SERVER['REMOTE_ADDR'], $_POST['recaptcha_challenge_field'], $_POST['recaptcha_response_field']); // reCaptcha data - - if(!$reCaptcha->is_valid) { // If reCaptcha is invalid die and display error message - print '<h2>'.L_INVALIDCAPTCHA.'</h2><meta http-equiv="refresh" content="2; URL='.$_SERVER['PHP_SELF'].'" />'; - $fucked = true; - } - } - - if($fucked) - break; - - // Assign variables - $submitData['title'] = removeSpecialChars($_POST['title']); - $submitData['content'] = removeSpecialChars($_POST['content']); - $submitData['name'] = removeSpecialChars($_POST['name']); - $submitData['nameNT'] = (strlen(strstr($submitData['name'], "#", true)) ? strstr($submitData['name'], "#", true) : $submitData['name']); - $submitData['trip'] = parseTrip($_POST['name']); - $submitData['email'] = ($_POST['email'] == 'noko' ? null : removeSpecialChars($_POST['email'])); - $submitData['date'] = time(); - $submitData['password'] = md5(strlen($_POST['password']) ? $_POST['password'] : generatePassword()); - $submitData['ip'] = base64_encode($_SERVER['REMOTE_ADDR']); - $submitData['op'] = (isset($_POST['tid']) ? 0 : 1); - $submitData['id'] = ($submitData['op'] ? ($sqldb->query("SELECT MAX(tid) AS `tid` FROM `".$sql['table']."` LIMIT 1")->fetch()['tid'] + 1) : removeSpecialChars($_POST['tid'])); - $submitData['noredir'] = ($submitData['email'] == 'noko' ? true : false); - // Assign cookies - setcookie( - $ninechan['cookiePrefix'] . "name", - $submitData['name'], - time() + $ninechan['cookieLifetime'], - $ninechan['cookiePath'], - $_SERVER['SERVER_NAME'] - ); - setcookie( - $ninechan['cookiePrefix'] . "email", - $submitData['email'], - time() + $ninechan['cookieLifetime'], - $ninechan['cookiePath'], - $_SERVER['SERVER_NAME'] - ); - setcookie( - $ninechan['cookiePrefix'] . "pass", - $submitData['password'], - time() + $ninechan['cookieLifetime'], - $ninechan['cookiePath'], - $_SERVER['SERVER_NAME'] - ); - - // Check if title is valid - if(empty($submitData['title']) || strlen($submitData['title']) < $ninechan['titleMinLength']) { // Check if too short - print '<h2>'. L_TITLETOOSHORT .'</h2>'; - print '<meta http-equiv="refresh" content="2; URL='.$_SERVER['PHP_SELF'].'" />'; - break; - } - if(strlen($submitData['title']) > $ninechan['titleMaxLength']) { // Check if too long - print '<h2>'. L_TITLETOOLONG .'</h2>'; - print '<meta http-equiv="refresh" content="2; URL='.$_SERVER['PHP_SELF'].'" />'; - break; - } - - // Check if comment is valid - if(empty($submitData['title']) || strlen($submitData['content']) < $ninechan['commentMinLength']) { // Check if too short - print '<h2>'. L_COMMENTTOOSHORT .'</h2>'; - print '<meta http-equiv="refresh" content="2; URL='.$_SERVER['PHP_SELF'].'" />'; - break; - } - if(strlen($submitData['content']) > $ninechan['commentMaxLength']) { // Check if too long - print '<h2>'.L_COMMENTTOOLONG.'</h2>'; - print '<meta http-equiv="refresh" content="2; URL='.$_SERVER['PHP_SELF'].'" />'; - break; - } - - $submitPost = $sqldb->prepare("INSERT INTO `". $sql['table'] ."` (`title`, `name`, `trip`, `email`, `date`, `content`, `password`, `ip`, `op`, `tid`) VALUES (:title, :name, :trip, :email, :date, :content, :password, :ipaddr, :op, :threadid)"); - - $submitPost->bindParam(':title', $submitData['title']); - $submitPost->bindParam(':name', $submitData['nameNT']); - $submitPost->bindParam(':trip', $submitData['trip']); - $submitPost->bindParam(':email', $submitData['email']); - $submitPost->bindParam(':date', $submitData['date']); - $submitPost->bindParam(':content', $submitData['content']); - $submitPost->bindParam(':password', $submitData['password']); - $submitPost->bindParam(':ipaddr', $submitData['ip']); - $submitPost->bindParam(':op', $submitData['op']); - $submitPost->bindParam(':threadid', $submitData['id']); - - $submitPost->execute(); - - print '<h1>'.L_POSTED.'</h1>'; - - //print '<meta http-equiv="refresh" content="1; URL='.($submitData['noredir'] ? '?v=index' : '?v=thread&t='.$submitData['id']).'" />'; - break; - - case 'del': - if($banCheck) { - print '<h2>'.L_USERBANNED.'</h2>'; - break; - } - - $deletionData = array(); // Assign array to variable so we can store things in it later - - if(isset($_POST['id'])) { - $getPostData = $sqldb->prepare("SELECT * FROM `". $sql['table'] ." WHERE `id` = :pid LIMIT 1"); - - $getPostData->bindParam(':pid', $_POST['id'], PDO::PARAM_INT); - - $getPostData->execute(); - - $getData = $getPostData->fetchAll(); - - if(!count($getData)) { - header('Location: ./'); - print '<meta http-equiv="refresh" content="0; url='. $_SERVER['PHP_SELF'] .'?v=index" />'; // fallback - } - - if($getData[0]['locked']) { - print '<h2>'.L_LOCKEDMSG_2.'</h2>'; - print '<meta http-equiv="refresh" content="2; URL='. $_SERVER['PHP_SELF'] .'?v=index" />'; - } else { - if($getData[0]['password'] == md5($_POST['password'])) { - nMod('del', $getData['id'], true); - print '<h2>'.L_DEL_SUCCEED.'</h2>'; - print '<meta http-equiv="refresh" content="2; URL='. $_SERVER['PHP_SELF'] .'?v=index" />'; - } else { - print '<h2>'.L_DEL_FAILED.'</h2>'; - //print '<meta http-equiv="refresh" content="2; URL='. $_SERVER['PHP_SELF'] .'?v=index" />'; - } - } - } elseif(isset($_GET['id'])) { - if(!is_numeric($_GET['id'])) { - header('Location: ./'); - print '<meta http-equiv="refresh" content="0; url='. $_SERVER['PHP_SELF'] .'?v=index" />'; // fallback - } - - $getPostData = $sqldb->prepare("SELECT * FROM `". $sql['table'] ." WHERE `id` = :pid LIMIT 1"); - - $getPostData->bindParam(':pid', $_POST['id'], PDO::PARAM_INT); - - $getPostData->execute(); - - $getData = $getPostData->fetch(); - - if(!count($getData)) { - header('Location: ./'); - print '<meta http-equiv="refresh" content="0; url='. $_SERVER['PHP_SELF'] .'?v=index" />'; // fallback - } - - print '<form method="post" action="'. $_SERVER['PHP_SELF'] .'?v=del">'; - - if($getData['locked']) { - print '<h2>'.L_LOCKEDMSG_2.'</h2>'; - print '<meta http-equiv="refresh" content="2; URL='. $_SERVER['PHP_SELF'] .'?v=index" />'; - } else { - print '<h2>'.L_DELPOST.' '.$getData['id'].'</h2>'; - print '<input type="hidden" name="id" value="'. $_GET['id'] .'" />'; - } - - print '<table id="postForm" class="postForm">'; - - print '<tr><td>'.L_PASSWORD.'</td>'; - print '<td><input name="password" type="password" placeholder="'.L_PASSWORDCONTEXT.'" value="'.@$_COOKIE[$ninechan['cookiePrefix'].'pass'].'" /> '; - print '<input value="'.L_SUBMIT.'" type="submit" /></td></tr>'; - - print '</table>'; - print '</form>'; - } - break; - - // Moderator Authentication - case 'mod': - if($auth == $ninechan['modPass']) { // Check if authenticated - if(isset($_POST['modkill'])) { // POST request modkill is set... - session_destroy(); // ...kill moderator session... - header('Location: ?v=mod'); // ...and redirect to ?v=mod - print '<meta http-equiv="refresh" content="0; url=?v=mod" />'; // fallback - } - - print '<h2>'.L_MODLOGOUT.'</h2>'; // Page title - - print '<form method="post" action="'.$_SERVER['PHP_SELF'].'?v=mod">'; // Print logout form - print L_MODTOOLS.'<br />'; - print '<input type="submit" value="'.L_LOGOUT.'" name="modkill" />'; - print '</form>'; - - if(isset($_GET['ban']) && isset($_GET['id']) && isset($_GET['t'])) { // Ban handler - if($_GET['ban'] == "true") - banPost($_GET['id'], true); - else - banPost($_GET['id'], false); + } + break; - header('Location: ?v=thread&t='.$_GET['t']); - print '<meta http-equiv="refresh" content="0; url=?v=thread&t='.$_GET['t'].'" />'; // fallback - } - if(isset($_GET['del']) && isset($_GET['id'])) { // Deletion handler - if($_GET['del'] == "purge") { - pruneThread($_GET['id'], true); - - header('Location: ?v=index'); - print '<meta http-equiv="refresh" content="0; url=?v=index" />'; // fallback - } else { - if($_GET['del'] == "true") - delPost($_GET['id'], true); - else - delPost($_GET['id'], false); + // Posting + case 'post': - header('Location: ?v=thread&t='.$_GET['t']); - print '<meta http-equiv="refresh" content="0; url=?v=thread&t='.$_GET['t'].'" />'; // fallback - } - } - if(isset($_GET['lock']) && isset($_GET['id'])) { // Lock handler - if($_GET['lock'] == "true") - lockThread($_GET['id'], true); - else - lockThread($_GET['id'], false); - - header('Location: ?v=thread&t='.$_GET['id']); - print '<meta http-equiv="refresh" content="0; url=?v=thread&t='.$_GET['id'].'" />'; // fallback - } - } else { // Else display login screen - if(isset($_POST['modPass'])) { - if($_POST['modPass'] == $ninechan['modPass']) - $_SESSION['mod'] = $ninechan['modPass']; - - header('Location: ?v=mod'); - print '<meta http-equiv="refresh" content="0; url=?v=mod" />'; // fallback - } - - print '<h2>'.L_MODLOGIN.'</h2>'; - print '<form method="post" action="'.$_SERVER['PHP_SELF'].'?v=mod">'; - print '<input type="password" name="modPass" /><input type="submit" value="'.L_LOGIN.'" />'; - print '</form>'; - } - break; - - // Default action - default: - header('Location: ?v=index'); // If invalid option is set redirect to index - print '<meta http-equiv="refresh" content="0; url=?v=index" />'; // Fallback because I've had experiences where header() didn't work properly + // Check if user is banned and if so don't display the form at all + if(checkBan($_SERVER['REMOTE_ADDR'])) { + print '<h2>'. getLang('USERBANNED') .'</h2>'; break; } - } else { + + // Print "global" form elements + print '<form method="post" action="'. $_SERVER['PHP_SELF'] .'?v=submit">'; + print '<table id="postForm" class="postForm">'; + + // Predefine that we're creating a new thread + $newThread = true; + + // Predefine that the thread isn't locked + $locked = false; + + // Predefine $threadTitle to avoid E_WARNINGs + $threadTitle = ''; + + // Check if a thread ID is set + if(isset($_GET['t'])) { + + // If so make sure it's numeric + if(!is_numeric($_GET['t'])) { + + print '<h2>'. getLang('NOTNUMERIC') .'</h2>'; + print '<a href="'. $_SERVER['PHP_SELF'] .'?v=index">'. getLang('RETURN') .'</a>'; + break; + + } + + // Strip non-numerical characters from the string + $threadId = preg_replace('/\D/', '', $_GET['t']); + + // Get the thread data + $thread = getPosts($threadId); + + if(!$thread) { + print '<h2>'. getLang('NONEXISTENT') .'</h2>'; + print '<a href="'. $_SERVER['PHP_SELF'] .'?v=index">'. getLang('RETURN') .'</a>'; + break; + } + + // Reassign $thread + $thread = $thread[0]; + + // Since we're not creating a thread set newThread to false + $newThread = false; + + // Reassign $locked + $locked = $thread['locked']; + + // Don't display posting form if thread is locked + if($locked) { + + print '<h2>'. getLang('LOCKEDMSG') .'</h2>'; + print '<meta http-equiv="refresh" content="2; URL="./?v=thread&t='. $thread['tid'] .'" />'; + + } else { + + print '<h2>'. getLang('RETO') .' '. $thread['title'] .' ['. $thread['tid'] .']</h2>'; + print '<input type="hidden" name="tid" value="'. $thread['tid'] .'" />'; + + $threadTitle = 'Re: '. $thread['title']; + + } + } else + print '<h2>'. getLang('NEWTHREAD') .'</h2>'; + + // Predefine the comment + $comment = isset($_GET['text']) ? $_GET['text']."\r\n" : ''; + + if(!$locked) { //-- Only display post page if thread isn't locked + print '<tr><td>'. getLang('NAME') .'</td><td><input name="name" type="text" value="'. @$_COOKIE[getConfig('cookiePrefix') .'name'] .'" /></td></tr>'; + print '<tr><td>'. getLang('EMAIL') .'</td><td><input name="email" type="text" value="'. @$_COOKIE[getConfig('cookiePrefix') .'email'] .'" /></td></tr>'; + print '<tr><td>'. getLang('TITLE') .'</td><td><input name="title" type="text" value="'. $threadTitle .'" /></td></tr>'; + print '<tr><td>'. getLang('COMMENT') .'</td><td><textarea name="content" rows="6" cols="48">'. $comment .'</textarea></td></tr>'; + + if(getConfig('reCaptcha')) { // Display reCaptcha if enabled in config + + print '<tr><td>'. getLang('VERIFICATION') .'</td><td> + <script src="https://www.google.com/recaptcha/api.js" async defer></script> + <div class="g-recaptcha" data-sitekey="'. getConfig('reCaptchaPublic') .'" style="margin: auto; display: inline-block;"></div> + <noscript> + <div style="width: 302px; height: 352px; margin: auto; display: inline-block;"> + <div style="width: 302px; height: 352px; position: relative;"> + <div style="width: 302px; height: 352px; position: absolute;"> + <iframe src="https://www.google.com/recaptcha/api/fallback?k='. getConfig('reCaptchaPublic') .'" frameborder="0" scrolling="no" style="width: 302px; height:352px; border-style: none;"></iframe> + </div> + <div style="width: 250px; height: 80px; position: absolute; border-style: none; bottom: 21px; left: 25px; margin: 0px; padding: 0px; right: 25px;"> + <textarea id="g-recaptcha-response" name="g-recaptcha-response" class="g-recaptcha-response" style="width: 250px; height: 80px; border: 1px solid #c1c1c1; margin: 0px; padding: 0px; resize: none;" value=""></textarea> + </div> + </div> + </div> + </noscript></td></tr>'; + + } + + print '<tr><td>'. getLang('PASSWORD') .'</td><td><input name="password" type="password" placeholder="'. getLang('PASSWORDCONTEXT') .'" value="'. @$_COOKIE[getConfig('cookiePrefix') .'pass'] .'" /> <input value="'. getLang('SUBMIT') .'" type="submit" /></td></tr>'; + print '</table></form>'; + + } + break; + + // Submitting posts + case 'submit': + + // Check if IP banned + if(checkBan($_SERVER['REMOTE_ADDR'])) { + print '<h2>'. getLang('USERBANNED') .'</h2>'; + break; + } + + // Check reCaptcha + if(getConfig('reCaptcha')) { + + // Verify the captcha + $reCaptcha = verifyCaptcha($_POST['g-recaptcha-response']); + + // If reCaptcha is invalid die and display error message + if(!$reCaptcha['success']) { + + print '<h2>'. getLang('INVALIDCAPTCHA') .'</h2><meta http-equiv="refresh" content="2; URL='. $_SERVER['PHP_SELF'] .'" />'; + print nFoot(); + exit; + + } + + } + + // Assign variables + $submitData = [ + + 'title' => cleanString($_POST['title']), + 'content' => cleanString($_POST['content']), + 'name' => ($_N_NAME = cleanString($_POST['name'])), + 'nameNT' => (strlen(strstr($_N_NAME, "#", true)) ? strstr($_N_NAME, "#", true) : $_N_NAME), + 'trip' => parseTrip($_POST['name']), + 'email' => ($_N_MAIL = ($_POST['email'] == 'noko' ? null : cleanString($_POST['email']))), + 'date' => time(), + 'password' => md5(strlen($_POST['password']) ? $_POST['password'] : generatePassword()), + 'ip' => base64_encode($_SERVER['REMOTE_ADDR']), + 'op' => ($_N_OP = (isset($_POST['tid']) ? 0 : 1)), + 'id' => ($_N_OP ? ($sqldb->query("SELECT MAX(tid) AS `tid` FROM `". $sql['table'] ."` LIMIT 1")->fetch()['tid'] + 1) : cleanString($_POST['tid'], true, true)), + 'noredir' => ($_N_MAIL == 'noko' ? true : false) + + ]; + + // Update last time replied + if(isset($_POST['tid'])) { + + // Prepare the statement + $updateLast = $sqldb->prepare("UPDATE `". $sql['table'] ."` SET `lastreply` = :lastreply WHERE `tid` = :tid AND `op` = 1"); + + // Bind the parameters + $updateLast->bindParam(':lastreply', $submitData['date'], PDO::PARAM_INT); + $updateLast->bindParam(':tid', $_POST['tid'], PDO::PARAM_INT); + + // Execute statement + $updateLast->execute(); + + } + + // Assign cookies + nCookie('name', $submitData['name']); + nCookie('email', $submitData['email']); + nCookie('pass', $submitData['password']); + + // Check if title is too short + if(empty($submitData['title']) || strlen($submitData['title']) < getConfig('titleMinLength')) { + print '<h2>'. getLang('TITLETOOSHORT') .'</h2>'; + print '<meta http-equiv="refresh" content="2; URL='. $_SERVER['PHP_SELF'] .'" />'; + break; + } + + // Check if title is too long + if(strlen($submitData['title']) > getConfig('titleMaxLength')) { + print '<h2>'. getLang('TITLETOOLONG') .'</h2>'; + print '<meta http-equiv="refresh" content="2; URL='. $_SERVER['PHP_SELF'] .'" />'; + break; + } + + // Check if comment is too short + if(empty($submitData['title']) || strlen($submitData['content']) < getConfig('commentMinLength')) { + print '<h2>'. getLang('COMMENTTOOSHORT') .'</h2>'; + print '<meta http-equiv="refresh" content="2; URL='. $_SERVER['PHP_SELF'] .'" />'; + break; + } + + // Check if comment is too long + if(strlen($submitData['content']) > getConfig('commentMaxLength')) { + print '<h2>'. getLang('COMMENTTOOLONG') .'</h2>'; + print '<meta http-equiv="refresh" content="2; URL='. $_SERVER['PHP_SELF'] .'" />'; + break; + } + + $submitPost = $sqldb->prepare("INSERT INTO `". $sql['table'] ."` (`title`, `name`, `trip`, `email`, `date`, `content`, `password`, `ip`, `op`, `tid`, `lastreply`) VALUES (:title, :name, :trip, :email, :date, :content, :password, :ipaddr, :op, :threadid, :lastrep)"); + + $submitPost->bindParam(':title', $submitData['title']); + $submitPost->bindParam(':name', $submitData['nameNT']); + $submitPost->bindParam(':trip', $submitData['trip']); + $submitPost->bindParam(':email', $submitData['email']); + $submitPost->bindParam(':date', $submitData['date']); + $submitPost->bindParam(':content', $submitData['content']); + $submitPost->bindParam(':password', $submitData['password']); + $submitPost->bindParam(':ipaddr', $submitData['ip']); + $submitPost->bindParam(':op', $submitData['op']); + $submitPost->bindParam(':threadid', $submitData['id']); + $submitPost->bindParam(':lastrep', $submitData['date']); + + $submitPost->execute(); + + print '<h1>'. getLang('POSTED') .'</h1>'; + + print '<meta http-equiv="refresh" content="1; URL='. ($submitData['noredir'] ? '?v=index' : '?v=thread&t='. $submitData['id']) .'" />'; + break; + + case 'del': + + // Check if IP banned + if(checkBan($_SERVER['REMOTE_ADDR'])) { + print '<h2>'. getLang('USERBANNED') .'</h2>'; + break; + } + + // Assign array to variable so we can store things in it later + $deletionData = array(); + + // If we're in _POST mode begin deletion preparation + if(isset($_POST['id'])) { + + // Prepare statement to get the post's data + $getPostData = $sqldb->prepare("SELECT * FROM `". $sql['table'] ." WHERE `id` = :pid LIMIT 1"); + + // Bind the ID + $getPostData->bindParam(':pid', $_POST['id'], PDO::PARAM_INT); + + // Execute the statement + $getPostData->execute(); + + // Fetch the data + $getData = $getPostData->fetch(); + + // Error if the post couldn't be found + if(!count($getData)) + error(getLang('NONEXISTENT') .'<meta http-equiv="refresh" content="0; url='. $_SERVER['PHP_SELF'] .'?v=index" />'); + + // Check if the post is locked + if($getData['locked']) { + + print '<h2>'. getLang('LOCKEDMSGDEL') .'</h2>'; + print '<meta http-equiv="refresh" content="2; URL='. $_SERVER['PHP_SELF'] .'?v=index" />'; + + } else { + + // Match the password + if($getData['password'] == md5($_POST['password'])) { + + // Use the moderator function to delete the post + nMod('del', $getData['id'], true); + print '<h2>'. getLang('DEL_SUCCEED') .'</h2>'; + print '<meta http-equiv="refresh" content="2; URL='. $_SERVER['PHP_SELF'] .'?v=index" />'; + + } else { + + // Else display an error message + print '<h2>'. getLang('DEL_FAILED') .'</h2>'; + print '<meta http-equiv="refresh" content="2; URL='. $_SERVER['PHP_SELF'] .'?v=index" />'; + + } + + } + + // Else enter _GET mode + } elseif(isset($_GET['id'])) { + + // Check if the post exists + if(!is_numeric($_GET['id'])) + error(getLang('NONEXISTENT') .'<meta http-equiv="refresh" content="0; url='. $_SERVER['PHP_SELF'] .'?v=index" />'); + + // Prepare statement to get post data + $getPostData = $sqldb->prepare("SELECT * FROM `". $sql['table'] ." WHERE `id` = :pid LIMIT 1"); + + // Bind ID + $getPostData->bindParam(':pid', $_GET['id'], PDO::PARAM_INT); + + // Execute statement + $getPostData->execute(); + + // Fetch data + $getData = $getPostData->fetch(); + + // Error if the post couldn't be found + if(!count($getData)) + error(getLang('NONEXISTENT') .'<meta http-equiv="refresh" content="0; url='. $_SERVER['PHP_SELF'] .'?v=index" />'); + + // Create form + print '<form method="post" action="'. $_SERVER['PHP_SELF'] .'?v=del">'; + + if($getData['locked']) { + print '<h2>'. getLang('LOCKEDMSGDEL') .'</h2>'; + print '<meta http-equiv="refresh" content="2; URL='. $_SERVER['PHP_SELF'] .'?v=index" />'; + } else { + print '<h2>'. getLang('DELPOST') .' '. $getData['id'] .'</h2>'; + print '<input type="hidden" name="id" value="'. $_GET['id'] .'" />'; + } + + print '<table id="postForm" class="postForm">'; + + print '<tr><td>'. getLang('PASSWORD') .'</td>'; + print '<td><input name="password" type="password" placeholder="'. getLang('PASSWORDCONTEXT') .'" value="'.@$_COOKIE[getConfig('cookiePrefix') .'pass'].'" /> '; + print '<input value="'. getLang('SUBMIT') .'" type="submit" /></td></tr>'; + + print '</table>'; + print '</form>'; + + } + break; + + // Moderator Authentication + case 'mod': + if($auth == getConfig('modPass')) { // Check if authenticated + + // Page title + print '<h2>'. getLang('MODLOGOUT') .'</h2>'; + + if(isset($_POST['modkill'])) { // POST request modkill is set... + + session_destroy(); // ...kill moderator session... + header('Location: ?v=mod'); // ...and redirect to ?v=mod + print '<meta http-equiv="refresh" content="0; url=?v=mod" />'; // fallback + exit; + + } + + // Print logout form + print '<form method="post" action="'.$_SERVER['PHP_SELF'].'?v=mod">'; + print getLang('MODTOOLS') .'<br />'; + print '<input type="submit" value="'. getLang('LOGOUT') .'" name="modkill" />'; + print '</form>'; + + // Ban handler + if(isset($_GET['ban']) && isset($_GET['id']) && isset($_GET['t'])) { + + if($_GET['ban'] == "true") + nMod('ban', $_GET['id'], true); + else + nMod('ban', $_GET['id'], false); + + header('Location: ?v=thread&t='.$_GET['t']); + print '<meta http-equiv="refresh" content="0; url=?v=thread&t='.$_GET['t'].'" />'; // fallback + exit; + + } + + // Deletion handler + if(isset($_GET['del']) && isset($_GET['id'])) { + + if($_GET['del'] == "purge") { + + nMod('prune', $_GET['id'], true); + + header('Location: ?v=index'); + print '<meta http-equiv="refresh" content="0; url=?v=index" />'; // fallback + exit; + + } else { + + if($_GET['del'] == "true") + nMod('del', $_GET['id'], true); + else + nMod('del', $_GET['id'], false); + + header('Location: ?v=thread&t='.$_GET['t']); + print '<meta http-equiv="refresh" content="0; url=?v=thread&t='.$_GET['t'].'" />'; // fallback + exit; + + } + + } + + // Lock handler + if(isset($_GET['lock']) && isset($_GET['id'])) { + + if($_GET['lock'] == "true") + nMod('lock', $_GET['id'], true); + else + nMod('lock', $_GET['id'], false); + + header('Location: ?v=thread&t='.$_GET['id']); + print '<meta http-equiv="refresh" content="0; url=?v=thread&t='.$_GET['id'].'" />'; // fallback + exit; + + } + + } else { + + // Else display login screen + if(isset($_POST['modPass'])) { + + if($_POST['modPass'] == $ninechan['modPass']) + $_SESSION['mod'] = $ninechan['modPass']; + + header('Location: ?v=mod'); + print '<meta http-equiv="refresh" content="0; url=?v=mod" />'; // fallback + exit; + + } + + print '<h2>'. getLang('MODLOGIN') .'</h2>'; + print '<form method="post" action="'.$_SERVER['PHP_SELF'].'?v=mod">'; + print '<input type="password" name="modPass" /><input type="submit" value="'. getLang('LOGIN') .'" />'; + print '</form>'; + + } + break; + + // Default action + default: header('Location: ?v=index'); // If invalid option is set redirect to index print '<meta http-equiv="refresh" content="0; url=?v=index" />'; // Fallback because I've had experiences where header() didn't work properly - } - if($ninechan['styles']) { // Check if styles are enabled - print '<h6>'; - foreach($ninechan['styles'] as $styleUrl => $styleName) { // Get styles from array - print '[<a href="javascript:;" onclick="ninechan.setStyle(\''.$styleName.'\');">'.$styleName.'</a>] '; // List every style - } - print '</h6>'; - } - ?> - <!-- - Please retain the full copyright notice below including the link to flash.moe. - This not only gives respect to the amount of time given freely by the developer - but also helps build interest, traffic and use of ninechan. - --> - <h6> - <a href="http://ninechan.flash.moe/" target="_blank">ninechan</a> - <?=($ninechan['showVersion'] ? N_VERSION : null);?> - © <a href="http://flash.moe/" target="_blank">Flashwave</a> - </h6> - </body> -</html> + break; + + } + +} else { + + header('Location: ?v=index'); // If invalid option is set redirect to index + print '<meta http-equiv="refresh" content="0; url=?v=index" />'; // Fallback because I've had experiences where header() didn't work properly + exit; + +} + +// Print footer +print nFoot(); diff --git a/lang/de.php b/lang/de.php index 518e5b5..1d06b81 100644 --- a/lang/de.php +++ b/lang/de.php @@ -1,63 +1,73 @@ <?php -// Ninechan german translation file by berserkingyadis <berserkingyadis@gmail.com> +/* + * German translation + * By Bers <https://github.com/berserkingyadis> + * (With slight updates by Flashwave <https://github.com/flashwave>) + */ -// Meta // -define('LDATA_VERSION', '1.11alpha2'); // Version of ninechan language file is made for +// Version of ninechan this language file is created for +$langVersion = '2.0'; -// Board // -define('L_THREADS', 'Threads'); // Threads -define('L_THREAD', 'Thread'); // Thread -define('L_NEWTHREAD', 'Neuer Thread'); // New Thread -define('L_NEWREPLY', 'Neuer Reply'); // New Reply -define('L_LOCKED', 'Gesperrt'); // Locked -define('L_BY', 'von'); // by +$language = [ -// Posting // -define('L_RETO', 'Antworten auf'); // Reply to -define('L_TITLE', 'Titel'); // Title -define('L_NAME', 'Name'); // Name -define('L_EMAIL', 'Email'); // Name -define('L_COMMENT', 'Kommentar'); // Comment -define('L_SUBMIT', 'Abschicken'); // Submit -define('L_VERIFICATION', 'Verifikation'); // Verification -define('L_PASSWORD', 'Passwort'); // Password -define('L_PASSWORDCONTEXT', 'zum post löschen'); // used for post deletion -define('L_DELPOST', 'Post löschen'); // Delete post + // Board + 'THREADS' => 'Threads', + 'THREAD' => 'Thread', + 'NEWTHREAD' => 'Neuer Thread', + 'NEWREPLY' => 'Neuer Reply', + 'LOCKED' => 'Gesperrt', + 'BY' => 'von', + 'RETURN' => 'Zurück nach Index', -// Messages // -define('L_BOARD_CLOSED', 'Die '.$ninechan['title'].' boards sind momentan geschlossen.'); // Boards are closed -define('L_REASON', 'Grund'); // Reason -define('L_BANNED', 'Du wurdest von diesem board gebannt.'); // Text displayed upon being banned -define('L_POSTBANNED', '(USER WURDE FÜR DIESEN POST GEBANNT)'); // Text displayed under banned post -define('L_EMPTY', 'Hier gibt es noch keine Threads.'); // Text displayed when the board is empty -define('L_NONEXISTENT', 'Nicht existerender Thread.'); // Text displayed when the board is empty -define('L_LOCKEDMSG', 'Reply nicht möglich, da der Thread gesperrt ist'); // Text displayed when the thread is locked and replying isn't possible -define('L_LOCKEDMSG_2', 'Löschen nicht möglich, da der Thread gesperrt ist'); // Text displayed when the thread is locked and deleting isn't possible -define('L_POSTED', 'Geposted!'); // Text displayed when the post is successful -define('L_MODTOOLS', 'Die Moderator Tools sollten nun neben den Posts angezeigt werden.'); // Mod tools message -define('L_TITLETOOSHORT', 'Dieser Titel ist zu kurz.'); // The given title is too short. -define('L_TITLETOOLONG', 'Dieser Titel ist zu lang.'); // The given title is too long. -define('L_COMMENTTOOSHORT', 'Dieser Kommentar ist zu kurz.'); // The given comment is too short. -define('L_COMMENTTOOLONG', 'Dieser Kommentar ist zu lang.'); // The given comment is too long. + // Posting + 'RETO' => 'Antworten auf', + 'TITLE' => 'Titel', + 'NAME' => 'Name', + 'EMAIL' => 'Email', + 'COMMENT' => 'Kommentar', + 'SUBMIT' => 'Abschicken', + 'VERIFICATION' => 'Verifikation', + 'PASSWORD' => 'Passwort', + 'PASSWORDCONTEXT' => 'zum post löschen', + 'DELPOST' => 'Post löschen', -// Warnings and errors // -define('L_PHP_OUTDATED', 'Deine PHP-Installation ist out of date. Bitte installiere mindestens PHP 5.3.'); // Outdated PHP version -define('L_SQL_FUNCTION', 'Deine PHP-Installation unterstützt kein PDO.'); // SQL connect function does not exist -define('L_SQL_CONNECT', 'SQL Connection - Fehler'); // Error while connecting to MySQL -define('L_INVALIDCAPTCHA', 'Falsches Captcha.'); // Message displayed when captcha is wrong -define('L_DEL_SUCCEED', 'Löschen erfolgreich!'); // Message displayed when post is deleted -define('L_DEL_FAILED', 'Löschen fehlgeschlagen.'); // Message displayed when post isn't deleted -define('L_USERBANNEDMSG', 'Du kannst in diesem Board nichts posten, da du gebannt bist.'); // Message displayed on top of the board when IP is banned -define('L_USERBANNED', 'Deine IP ist gebannt.'); // Message displayed when trying to access a restricted page + // Messages + 'BOARD_CLOSED' => 'Die boards sind momentan geschlossen.', + 'REASON' => 'Grund', + 'BANNED' => 'Du wurdest von diesem board gebannt.', + 'POSTBANNED' => '(USER WURDE FÜR DIESEN POST GEBANNT)', + 'EMPTY' => 'Hier gibt es noch keine Threads.', + 'NONEXISTENT' => 'Nicht existerender Thread.', + 'LOCKEDMSG' => 'Reply nicht möglich, da der Thread gesperrt ist.', + 'LOCKEDMSGDEL' => 'Löschen nicht möglich, da der Thread gesperrt ist.', + 'POSTED' => 'Geposted!', + 'MODTOOLS' => 'Die Moderator Tools sollten nun neben den Posts angezeigt werden.', + 'TITLETOOSHORT' => 'Dieser Titel ist zu kurz.', + 'TITLETOOLONG' => 'Dieser Titel ist zu lang.', + 'COMMENTTOOSHORT' => 'Dieser Kommentar ist zu kurz.', + 'COMMENTTOOLONG' => 'Dieser Kommentar ist zu lang.', + 'NOTNUMERIC' => 'Post-Daten konnten nicht abgerufen werden.', -// Moderator tools // -define('L_DELETE', 'Löschen'); // Delete button -define('L_PURGE', 'Thread löschen'); // Purge button -define('L_LOCK', 'Thread sperren'); // Lock button -define('L_UNLOCK', 'Thread entsperren'); // Unlock button -define('L_BAN', 'Bannen'); // Ban button -define('L_UNBAN', 'Entbannen'); // Unban button -define('L_MODLOGOUT', 'Moderator Logout'); // Moderator Logout -define('L_MODLOGIN', 'Moderator Login'); // Moderator Login -define('L_LOGOUT', 'Logout'); // Logout -define('L_LOGIN', 'Login'); // Login + // Warnings and errors + 'PHP_OUTDATED' => 'Deine PHP-Installation ist out of date. Bitte installiere mindestens PHP 5.3.', + 'SQL_FUNCTION' => 'Deine PHP-Installation unterstützt kein PDO.', + 'SQL_CONNECT' => 'SQL Connection - Fehler', + 'INVALIDCAPTCHA' => 'Falsches Captcha.', + 'DEL_SUCCEED' => 'Löschen erfolgreich!', + 'DEL_FAILED' => 'Löschen fehlgeschlagen.', + 'USERBANNEDMSG' => 'Du kannst in diesem Board nichts posten, da du gebannt bist.', + 'USERBANNED' => 'Deine IP ist gebannt.', + + // Moderator tools + 'DELETE' => 'Löschen', + 'PURGE' => 'Thread löschen', + 'LOCK' => 'Thread sperren', + 'UNLOCK' => 'Thread entsperren', + 'BAN' => 'Bannen', + 'UNBAN' => 'Entbannen', + 'MODLOGOUT' => 'Moderator Logout', + 'MODLOGIN' => 'Moderator Login', + 'LOGOUT' => 'Logout', + 'LOGIN' => 'Login' + +]; diff --git a/lang/en.php b/lang/en.php index b572664..7cbdcad 100644 --- a/lang/en.php +++ b/lang/en.php @@ -1,65 +1,72 @@ <?php -//// Ninechan Official English Language File //// +/* + * Default English translation + * By Flashwave <https://github.com/flashwave> + */ -// Meta // -define('LDATA_VERSION', '1.11alpha4'); // Version of ninechan language file is made for +// Version of ninechan this language file is created for +$langVersion = '2.0'; -// Board // -define('L_THREADS', 'Threads'); // Threads -define('L_THREAD', 'Thread'); // Thread -define('L_NEWTHREAD', 'New Thread'); // New Thread -define('L_NEWREPLY', 'New Reply'); // New Reply -define('L_LOCKED', 'Locked'); // Locked -define('L_BY', 'by'); // by -define('L_RETURN', 'Return to Index'); // Return to Index +$language = [ -// Posting // -define('L_RETO', 'Reply to'); // Reply to -define('L_TITLE', 'Title'); // Title -define('L_NAME', 'Name'); // Name -define('L_EMAIL', 'E-mail'); // E-mail -define('L_COMMENT', 'Comment'); // Comment -define('L_SUBMIT', 'Submit'); // Submit -define('L_VERIFICATION', 'Verification'); // Verification -define('L_PASSWORD', 'Password'); // Password -define('L_PASSWORDCONTEXT', 'used for post deletion'); // used for post deletion -define('L_DELPOST', 'Delete post'); // Delete post + // Board + 'THREADS' => 'Threads', + 'THREAD' => 'Thread', + 'NEWTHREAD' => 'New Thread', + 'NEWREPLY' => 'New Reply', + 'LOCKED' => 'Locked', + 'BY' => 'by', + 'RETURN' => 'Return to Index', -// Messages // -define('L_BOARD_CLOSED', 'The board is closed at the moment.'); // The board is closed at the moment. -define('L_REASON', 'Reason'); // Reason -define('L_BANNED', 'You have been banned from this board.'); // You have been banned from this board. -define('L_POSTBANNED', '(USER WAS BANNED FOR THIS POST)'); // (USER WAS BANNED FOR THIS POST) -define('L_EMPTY', 'There are no threads.'); // There are no threads. -define('L_NONEXISTENT', 'The requested thread does not exist.'); // The requested thread does not exist. -define('L_LOCKEDMSG', "The thread you're trying to reply to is locked."); // The thread you're trying to reply to is locked. -define('L_LOCKEDMSG_2', "The thread your post was in is locked and deletion isn't possible."); // The thread your post was in is locked and deletion isn't possible. -define('L_POSTED', 'Posted!'); // Posted! -define('L_MODTOOLS', 'The moderator tools should now appear next to posts.'); // The moderator tools should now appear next to posts. -define('L_TITLETOOSHORT', 'The given title is too short.'); // The given title is too short. -define('L_TITLETOOLONG', 'The given title is too long.'); // The given title is too long. -define('L_COMMENTTOOSHORT', 'The given comment is too short.'); // The given comment is too short. -define('L_COMMENTTOOLONG', 'The given comment is too long.'); // The given comment is too long. -define('L_NOTNUMERIC', 'Could not retrieve post data because the ID you requested is not numeric, check your URL and try again.'); // Could not retrieve post data because the ID you requested is not numeric, check your URL and try again. + // Posting + 'RETO' => 'Reply to', + 'TITLE' => 'Title', + 'NAME' => 'Name', + 'EMAIL' => 'E-mail', + 'COMMENT' => 'Comment', + 'SUBMIT' => 'Submit', + 'VERIFICATION' => 'Verification', + 'PASSWORD' => 'Password', + 'PASSWORDCONTEXT' => 'used for post deletion', + 'DELPOST' => 'Delete post', -// Warnings and errors // -define('L_PHP_OUTDATED', 'Please upgrade your PHP installation to at least 5.3 or higher.'); // Please upgrade your PHP installation to at least 5.3 or higher. -define('L_SQL_FUNCTION', 'Your PHP installation does not support PDO.'); // Your PHP installation does not support PDO. -define('L_SQL_CONNECT', 'SQL Connection Error'); // SQL Connection Error -define('L_INVALIDCAPTCHA', 'Verification failed'); // Verification failed -define('L_DEL_SUCCEED', 'Successfully deleted!'); // Successfully deleted! -define('L_DEL_FAILED', 'Failed to delete.'); // Failed to delete. -define('L_USERBANNEDMSG', 'You are banned from posting on this board.'); // You are banned from posting on this board. -define('L_USERBANNED', "Couldn't complete this action because IP is banned."); // Couldn't complete this action because IP is banned. + // Messages + 'BOARD_CLOSED' => 'The board is closed at the moment.', + 'REASON' => 'Reason', + 'BANNED' => 'You have been banned from this board.', + 'POSTBANNED' => '(USER WAS BANNED FOR THIS POST)', + 'EMPTY' => 'No threads have been made yet.', + 'NONEXISTENT' => 'The requested thread does not exist.', + 'LOCKEDMSG' => 'The thread you are trying to reply to is locked.', + 'LOCKEDMSGDEL' => 'The thread your post was in is locked and deletion is not possible.', + 'POSTED' => 'Posted!', + 'MODTOOLS' => 'The moderator tools should now appear next to posts.', + 'TITLETOOSHORT' => 'The given title is too short.', + 'TITLETOOLONG' => 'The given title is too long.', + 'COMMENTTOOSHORT' => 'The given comment is too short.', + 'COMMENTTOOLONG' => 'The given comment is too long.', + 'NOTNUMERIC' => 'Could not retrieve post data because the ID you requested is not numeric, check your URL and try again.', -// Moderator tools // -define('L_DELETE', 'Delete'); // Delete -define('L_PURGE', 'Purge Thread'); // Purge Thread -define('L_LOCK', 'Lock Thread'); // Lock Thread -define('L_UNLOCK', 'Unlock Thread'); // Unlock Thread -define('L_BAN', 'Ban'); // Ban -define('L_UNBAN', 'Un-ban'); // Un-ban -define('L_MODLOGOUT', 'Moderator Logout'); // Moderator Logout -define('L_MODLOGIN', 'Moderator Login'); // Moderator Login -define('L_LOGOUT', 'Logout'); // Logout -define('L_LOGIN', 'Login'); // Login + // Warnings and errors + 'PHP_OUTDATED' => 'Please upgrade your PHP installation to at least 5.3 or higher.', + 'SQL_FUNCTION' => 'Your PHP installation does not support PDO.', + 'SQL_CONNECT' => 'SQL Connection Error', + 'INVALIDCAPTCHA' => 'Verification failed', + 'DEL_SUCCEED' => 'Successfully deleted!', + 'DEL_FAILED' => 'Failed to delete.', + 'USERBANNEDMSG' => 'You are banned from posting on this board.', + 'USERBANNED' => 'Could not complete this action because your IP is banned.', + + // Moderator tools + 'DELETE' => 'Delete', + 'PURGE' => 'Purge Thread', + 'LOCK' => 'Lock Thread', + 'UNLOCK' => 'Unlock Thread', + 'BAN' => 'Ban IP', + 'UNBAN' => 'Unban IP', + 'MODLOGOUT' => 'Moderator Logout', + 'MODLOGIN' => 'Moderator Login', + 'LOGOUT' => 'Logout', + 'LOGIN' => 'Login' + +]; diff --git a/lang/es.php b/lang/es.php index fb79d7c..eab7276 100644 --- a/lang/es.php +++ b/lang/es.php @@ -1,58 +1,72 @@ <?php -//// Ninechan Official Spanish Language File //// +/* + * Spanish translation + * By Kevin Lopez Brante <https://github.com/kddlb> + */ -// Meta // -define('LDATA_VERSION', '1.9'); // Version of ninechan language file is made for +// Version of ninechan this language file is created for +$langVersion = '2.0'; -// Board // -define('L_THREADS', 'Hilos'); // Threads -define('L_THREAD', 'Hilo'); // Thread -define('L_NEWTHREAD', 'Nuevo hilo'); // New Thread -define('L_NEWREPLY', 'Nueva respuesta'); // New Reply -define('L_LOCKED', 'Bloqueado'); // Locked -define('L_BY', 'por'); // by +$language = [ -// Posting // -define('L_RETO', 'Responder a'); // Reply to -define('L_TITLE', 'Título'); // Title -define('L_NAME', 'Nombre'); // Name -define('L_EMAIL', 'Email'); // Name -define('L_COMMENT', 'Comentario'); // Comment -define('L_SUBMIT', 'Enviar'); // Submit -define('L_VERIFICATION', 'Verificación'); // Verification -define('L_PASSWORD', 'Contraseña'); // Password -define('L_PASSWORDCONTEXT', 'utilizada para poder eliminar posts'); // used for post deletion -define('L_DELPOST', 'Eliminar post'); // Delete post + // Board + 'THREADS' => 'Hilos', + 'THREAD' => 'Hilo', + 'NEWTHREAD' => 'Nuevo hilo', + 'NEWREPLY' => 'Nueva respuesta', + 'LOCKED' => 'Bloqueado', + 'BY' => 'por', + 'RETURN' => 'Return to Index', -// Messages // -define('L_BOARD_CLOSED', 'Los foros '.$ninechan['title'].' están cerrados en estos momentos.'); // Boards are closed -define('L_REASON', 'Razón'); // Reason -define('L_BANNED', 'Has sido baneado de este foro.'); // Text displayed upon being banned -define('L_EMPTY', 'No hay hilos.'); // Text displayed when the board is empty -define('L_NONEXISTENT', 'No existe el hilo.'); // Text displayed when the board is empty -define('L_LOCKEDMSG', 'El hilo al que intentaste responder está bloqueado.'); // Text displayed when the thread is locked and replying isn't possible -define('L_LOCKEDMSG_2', 'No se pueden eliminar posts en hilos bloqueados.'); // Text displayed when the thread is locked and deleting isn't possible -define('L_POSTED', '¡Posteado!'); // Text displayed when the post is successful -define('L_INVALIDTITLE', '¡Título inválido!'); // Text displayed when the name field is empty or invalid -define('L_NOCOMMENT', '¡Comentario inválido!'); // Text displayed when the comment field is empty or invalid -define('L_MODTOOLS', 'Las herramientas de moderación deberían empezar a aparecer al lado de los posts.'); // Mod tools message + // Posting + 'RETO' => 'Responder a', + 'TITLE' => 'Título', + 'NAME' => 'Nombre', + 'EMAIL' => 'Email', + 'COMMENT' => 'Comentario', + 'SUBMIT' => 'Enviar', + 'VERIFICATION' => 'Verificación', + 'PASSWORD' => 'Contraseña', + 'PASSWORDCONTEXT' => 'utilizada para poder eliminar posts', + 'DELPOST' => 'Eliminar post', -// Warnings and errors // -define('L_PHP_OUTDATED', 'Por favor, actualiza tu instalación de PHP a por lo menos 5.3 o superior.'); // Outdated PHP version -define('L_SQL_FUNCTION', 'Tu instalación de PHP no soporta PDO.'); // SQL connect function does not exist -define('L_SQL_CONNECT', 'Error de conexión SQL'); // Error while connecting to MySQL -define('L_INVALIDCAPTCHA', 'La verificación falló'); // Message displayed when captcha is wrong -define('L_DEL_SUCCEED', '¡Eliminado satisfactoriamente!'); // Message displayed when post is deleted -define('L_DEL_FAILED', 'No se pudo eliminar.'); // Message displayed when post isn't deleted + // Messages + 'BOARD_CLOSED' => 'Los foros están cerrados en estos momentos.', + 'REASON' => 'Razón', + 'BANNED' => 'Has sido baneado de este foro.', + 'POSTBANNED' => '(USER WAS BANNED FOR THIS POST)', + 'EMPTY' => 'No hay hilos.', + 'NONEXISTENT' => 'No existe el hilo.', + 'LOCKEDMSG' => 'El hilo al que intentaste responder está bloqueado.', + 'LOCKEDMSGDEL' => 'No se pueden eliminar posts en hilos bloqueados.', + 'POSTED' => '¡Posteado!', + 'MODTOOLS' => 'Las herramientas de moderación deberían empezar a aparecer al lado de los posts.', + 'TITLETOOSHORT' => 'The given title is too short.', + 'TITLETOOLONG' => 'The given title is too long.', + 'COMMENTTOOSHORT' => 'The given comment is too short.', + 'COMMENTTOOLONG' => 'The given comment is too long.', + 'NOTNUMERIC' => 'Could not retrieve post data because the ID you requested is not numeric, check your URL and try again.', -// Moderator tools // -define('L_DELETE', 'Eliminar'); // Delete button -define('L_PURGE', 'Purgar hilo'); // Purge button -define('L_LOCK', 'Bloquear hilo'); // Lock button -define('L_UNLOCK', 'Desbloquear hilo'); // Unlock button -define('L_BAN', 'Banear'); // Ban button -define('L_UNBAN', 'Desbanear'); // Unban button -define('L_MODLOGOUT', 'Salir'); // Moderator Logout -define('L_MODLOGIN', 'Entrar como moderador'); // Moderator Login -define('L_LOGOUT', 'Salir'); // Logout -define('L_LOGIN', 'Entrar'); // Login + // Warnings and errors + 'PHP_OUTDATED' => 'Por favor, actualiza tu instalación de PHP a por lo menos 5.3 o superior.', + 'SQL_FUNCTION' => 'Tu instalación de PHP no soporta PDO.', + 'SQL_CONNECT' => '¡Error de conexión SQL!', + 'INVALIDCAPTCHA' => 'La verificación falló.', + 'DEL_SUCCEED' => '¡Eliminado satisfactoriamente!', + 'DEL_FAILED' => 'No se pudo eliminar.', + 'USERBANNEDMSG' => 'You are banned from posting on this board.', + 'USERBANNED' => 'Could not complete this action because your IP is banned.', + + // Moderator tools + 'DELETE' => 'Eliminar', + 'PURGE' => 'Purgar hilo', + 'LOCK' => 'Bloquear hilo', + 'UNLOCK' => 'Desbloquear hilo', + 'BAN' => 'Banear IP', + 'UNBAN' => 'Desbanear IP', + 'MODLOGOUT' => 'Salir como moderador', + 'MODLOGIN' => 'Entrar como moderador', + 'LOGOUT' => 'Salir', + 'LOGIN' => 'Entrar' + +]; diff --git a/lang/in.php b/lang/in.php index d954b41..fd29db7 100644 --- a/lang/in.php +++ b/lang/in.php @@ -1,66 +1,72 @@ <?php /* - Semi-Correct Indonesian translation file for ninechan - Flappyzor - flappy@goat.si -*/ + * Semi-Correct Indonesian translation + * By Flappyzor <https://github.com/flappyzor> + */ -// Meta // -define('LDATA_VERSION', '1.11alpha2'); // Version of ninechan language file is made for +// Version of ninechan this language file is created for +$langVersion = '2.0'; -// Board // -define('L_THREADS', 'Threads'); // Threads -define('L_THREAD', 'Thread'); // Thread -define('L_NEWTHREAD', 'Thread Baru'); // New Thread -define('L_NEWREPLY', 'Membalas Baru'); // New Reply -define('L_LOCKED', 'Terkunci'); // Locked -define('L_BY', 'oleh'); // by +$language = [ -// Posting // -define('L_RETO', 'Membalas Ke'); // Reply to -define('L_TITLE', 'Judul'); // Title -define('L_NAME', 'Nama'); // Name -define('L_EMAIL', 'Email'); // Name -define('L_COMMENT', 'Komentar'); // Comment -define('L_SUBMIT', 'Menyerahkan'); // Submit -define('L_VERIFICATION', 'Verifikasi'); // Verification -define('L_PASSWORD', 'Password'); // Password -define('L_PASSWORDCONTEXT', 'digunakan untuk posting penghapusan'); // used for post deletion -define('L_DELPOST', 'Hapus pos'); // Delete post + // Board + 'THREADS' => 'Threads', + 'THREAD' => 'Thread', + 'NEWTHREAD' => 'Thread Baru', + 'NEWREPLY' => 'Membalas Baru', + 'LOCKED' => 'Terkunci', + 'BY' => 'oleh', + 'RETURN' => 'Return to Index', -// Messages // -define('L_BOARD_CLOSED', 'Papan '.$ninechan['title'].' sedang ditutup.'); // Boards are closed -define('L_REASON', 'Alasan'); // Reason -define('L_BANNED', 'Anda telah dilarang dari forum ini.'); // Text displayed upon being banned -define('L_POSTBANNED', '(PENGGUNA ADALAH DILARANG UNTUK POST INI)'); // Text displayed under banned post -define('L_EMPTY', 'Tidak ada threads.'); // Text displayed when the board is empty -define('L_NONEXISTENT', 'Tidak ada thread.'); // Text displayed when the board is empty -define('L_LOCKEDMSG', 'Thread Anda mencoba untuk membalas terkunci.'); // Text displayed when the thread is locked and replying isn't possible -define('L_LOCKEDMSG_2', 'Thread posting Anda di terkunci dan penghapusan tidak mungkin.'); // Text displayed when the thread is locked and deleting isn't possible -define('L_POSTED', 'Menyampaikan!'); // Text displayed when the post is successful -define('L_MODTOOLS', 'Alat moderator seharusnya sekarang muncul di samping tulisan.'); // Mod tools message -define('L_TITLETOOSHORT', 'Judul yang diberikan terlalu singkat.'); // The given title is too short. -define('L_TITLETOOLONG', 'Judul yang diberikan terlalu panjang.'); // The given title is too long. -define('L_COMMENTTOOSHORT', 'Komentar yang diberikan terlalu singkat.'); // The given comment is too short. -define('L_COMMENTTOOLONG', 'Komentar yang diberikan terlalu panjang.'); // The given comment is too long. + // Posting + 'RETO' => 'Membalas Ke', + 'TITLE' => 'Judul', + 'NAME' => 'Nama', + 'EMAIL' => 'Email', + 'COMMENT' => 'Komentar', + 'SUBMIT' => 'Menyerahkan', + 'VERIFICATION' => 'Verifikasi', + 'PASSWORD' => 'Password', + 'PASSWORDCONTEXT' => 'digunakan untuk posting penghapusan', + 'DELPOST' => 'Hapus pos', -// Warnings and errors // -define('L_PHP_OUTDATED', 'Silakan meng-upgrade instalasi PHP Anda untuk setidaknya 5,3 atau lebih tinggi.'); // Outdated PHP version -define('L_SQL_FUNCTION', 'Instalasi PHP Anda tidak mendukung PDO.'); // SQL connect function does not exist -define('L_SQL_CONNECT', 'Kesalahan Connection SQL'); // Error while connecting to MySQL -define('L_INVALIDCAPTCHA', 'Verifikasi gagal'); // Message displayed when captcha is wrong -define('L_DEL_SUCCEED', 'Berhasil dihapus!'); // Message displayed when post is deleted -define('L_DEL_FAILED', 'Gagal menghapus.'); // Message displayed when post isn't deleted -define('L_USERBANNEDMSG', 'Anda dilarang posting di forum ini.'); // Message displayed on top of the board when IP is banned -define('L_USERBANNED', 'Tidak bisa menyelesaikan tindakan ini karena IP dilarang.'); // Message displayed when trying to access a restricted page + // Messages + 'BOARD_CLOSED' => 'Papan sedang ditutup.', + 'REASON' => 'Alasan', + 'BANNED' => 'Anda telah dilarang dari forum ini.', + 'POSTBANNED' => '(PENGGUNA ADALAH DILARANG UNTUK POST INI)', + 'EMPTY' => 'Tidak ada threads.', + 'NONEXISTENT' => 'Tidak ada thread.', + 'LOCKEDMSG' => 'Thread Anda mencoba untuk membalas terkunci.', + 'LOCKEDMSGDEL' => 'Thread posting Anda di terkunci dan penghapusan tidak mungkin.', + 'POSTED' => 'Menyampaikan!', + 'MODTOOLS' => 'Alat moderator seharusnya sekarang muncul di samping tulisan.', + 'TITLETOOSHORT' => 'Judul yang diberikan terlalu singkat.', + 'TITLETOOLONG' => 'Judul yang diberikan terlalu panjang.', + 'COMMENTTOOSHORT' => 'Komentar yang diberikan terlalu singkat.', + 'COMMENTTOOLONG' => 'Komentar yang diberikan terlalu panjang.', + 'NOTNUMERIC' => 'Could not retrieve post data because the ID you requested is not numeric, check your URL and try again.', -// Moderator tools // -define('L_DELETE', 'Hapus'); // Delete button -define('L_PURGE', 'Bersihkan Thread'); // Purge button -define('L_LOCK', 'Lock Thread'); // Lock button -define('L_UNLOCK', 'Membuka Thread'); // Unlock button -define('L_BAN', 'Departemen'); // Ban button -define('L_UNBAN', 'Unban'); // Unban button -define('L_MODLOGOUT', 'Moderator Logout'); // Moderator Logout -define('L_MODLOGIN', 'Moderator Login'); // Moderator Login -define('L_LOGOUT', 'Logout'); // Logout -define('L_LOGIN', 'Login'); // Login + // Warnings and errors + 'PHP_OUTDATED' => 'Silakan meng-upgrade instalasi PHP Anda untuk setidaknya 5,3 atau lebih tinggi.', + 'SQL_FUNCTION' => 'Instalasi PHP Anda tidak mendukung PDO.', + 'SQL_CONNECT' => 'Kesalahan Connection SQL', + 'INVALIDCAPTCHA' => 'Verifikasi gagal!', + 'DEL_SUCCEED' => 'Berhasil dihapus!', + 'DEL_FAILED' => 'Gagal menghapus!', + 'USERBANNEDMSG' => 'Anda dilarang posting di forum ini.', + 'USERBANNED' => 'Tidak bisa menyelesaikan tindakan ini karena IP dilarang.', + + // Moderator tools + 'DELETE' => 'Hapus', + 'PURGE' => 'Bersihkan Thread', + 'LOCK' => 'Lock Thread', + 'UNLOCK' => 'Membuka Thread', + 'BAN' => 'Departemen', + 'UNBAN' => 'Unban', + 'MODLOGOUT' => 'Moderator Logout', + 'MODLOGIN' => 'Moderator Login', + 'LOGOUT' => 'Logout', + 'LOGIN' => 'Login' + +]; diff --git a/lang/nl.php b/lang/nl.php index 894a341..c6cec42 100644 --- a/lang/nl.php +++ b/lang/nl.php @@ -1,63 +1,72 @@ <?php -//// Ninechan Official Dutch Language File //// +/* + * Dutch translation + * By Flashwave <https://github.com/flashwave> + */ -// Meta // -define('LDATA_VERSION', '1.11alpha2'); // Version of ninechan language file is made for +// Version of ninechan this language file is created for +$langVersion = '2.0'; -// Board // -define('L_THREADS', 'Threads'); // Threads -define('L_THREAD', 'Thread'); // Thread -define('L_NEWTHREAD', 'Nieuwe Thread'); // New Thread -define('L_NEWREPLY', 'Nieuwe Reactie'); // New Reply -define('L_LOCKED', 'Gesloten'); // Locked -define('L_BY', 'door'); // by +$language = [ -// Posting // -define('L_RETO', 'Reactie naar'); // Reply to -define('L_TITLE', 'Titel'); // Title -define('L_NAME', 'Naam'); // Name -define('L_EMAIL', 'Email'); // Name -define('L_COMMENT', 'Bericht'); // Comment -define('L_SUBMIT', 'Stuur'); // Submit -define('L_VERIFICATION', 'Verificatie'); // Verification -define('L_PASSWORD', 'Wachtwoord'); // Password -define('L_PASSWORDCONTEXT', 'gebruikt voor post verwijdering'); // used for post deletion -define('L_DELPOST', 'Verwijder post'); // Delete post + // Board + 'THREADS' => 'Threads', + 'THREAD' => 'Thread', + 'NEWTHREAD' => 'Nieuwe Thread', + 'NEWREPLY' => 'Beantwoord', + 'LOCKED' => 'Gesloten', + 'BY' => 'door', + 'RETURN' => 'Terug naar de Index', -// Messages // -define('L_BOARD_CLOSED', 'Het '.$ninechan['title'].' forum is gesloten op het moment.'); // Boards are closed -define('L_REASON', 'Reden'); // Reason -define('L_BANNED', 'U bent verbannen van dit forum.'); // Text displayed upon being banned -define('L_POSTBANNED', '(GEBRUIKER WAS VERBANNEN VOOR DIT BERICHT)'); // Text displayed under banned post -define('L_EMPTY', 'Er zijn geen threads.'); // Text displayed when the board is empty -define('L_NONEXISTENT', 'Niet bestaande thread.'); // Text displayed when the board is empty -define('L_LOCKEDMSG', 'De thread waarop u probeert te reageren is gesloten.'); // Text displayed when the board is empty -define('L_LOCKEDMSG_2', 'De thread waarin jouw bericht was is gelockt en je kunt je bericht niet verwijderen.'); // Text displayed when the thread is locked and deleting isn't possible -define('L_POSTED', 'Verstuurd!'); // Text displayed when the post is successful -define('L_MODTOOLS', 'De moderator hulpmiddelen moeten nu bij de berichten staan.'); // Mod tools message -define('L_TITLETOOSHORT', 'De gegeven titel is te kort.'); // The given title is too short. -define('L_TITLETOOLONG', 'De gegeven titel is te lang.'); // The given title is too long. -define('L_COMMENTTOOSHORT', 'Het gegeven bericht is te kort.'); // The given comment is too short. -define('L_COMMENTTOOLONG', 'Het gegeven bericht is te lang.'); // The given comment is too long. + // Posting + 'RETO' => 'Antwoord op', + 'TITLE' => 'Titel', + 'NAME' => 'Naam', + 'EMAIL' => 'E-mail', + 'COMMENT' => 'Commentaar', + 'SUBMIT' => 'Versturen', + 'VERIFICATION' => 'Verificatie', + 'PASSWORD' => 'Wachtwoord', + 'PASSWORDCONTEXT' => 'voor het verwijderen van dit bericht', + 'DELPOST' => 'Verwijder bericht', -// Warnings and errors // -define('L_PHP_OUTDATED', 'Upgrade uw PHP versie naar ten minste 5.3.'); // Outdated PHP version -define('L_SQL_FUNCTION', 'Uw PHP installatie mist de PDO plugin.'); // SQL connect function does not exist -define('L_SQL_CONNECT', 'SQL Verbindings Fout'); // Error while connecting to MySQL -define('L_INVALIDCAPTCHA', 'Verification mislukt'); // Message displayed when captcha is wrong -define('L_DEL_SUCCEED', 'Successvol verwijdert!'); // Message displayed when post is deleted -define('L_DEL_FAILED', 'Verwijderen mislukt.'); // Message displayed when post isn't deleted -define('L_USERBANNEDMSG', 'Je bent verbannen van posten op dit forum'); // Message displayed on top of the board when IP is banned -define('L_USERBANNED', 'Kan de actie niet voltooien omdat je IP verbannen.'); // Message displayed when trying to access a restricted page + // Messages + 'BOARD_CLOSED' => 'Het forum is gesloten.', + 'REASON' => 'Reden', + 'BANNED' => 'Je bent verbannen van dit forum!', + 'POSTBANNED' => '(GEBRUIKER WAS VERBANNEN VOOR DIT BERICHT)', + 'EMPTY' => 'Er zijn nog geen threads om the weergeven.', + 'NONEXISTENT' => 'De opgevraagde thread bestaat niet.', + 'LOCKEDMSG' => 'De thread waarop jij probeert te antwoorden is gesloten.', + 'LOCKEDMSGDEL' => 'Je kunt deze post niet verwijderen omdat de thread waarin deze zit gesloten is.', + 'POSTED' => 'Gepost!', + 'MODTOOLS' => 'De moderator tools verschijnen nu naast berichten.', + 'TITLETOOSHORT' => 'De gegeven titel is te kort.', + 'TITLETOOLONG' => 'De gegeven titel is te lang.', + 'COMMENTTOOSHORT' => 'Het gegeven commentaar is te lang.', + 'COMMENTTOOLONG' => 'Het gegeven commentaar is te kort.', + 'NOTNUMERIC' => 'De gevraagde bericht gegevens konden niet opgeroept worden.', -// Moderator tools // -define('L_DELETE', 'Verwijder'); // Delete button -define('L_PURGE', 'Verwijder Thread'); // Purge button -define('L_LOCK', 'Sluit Thread'); // Lock button -define('L_UNLOCK', 'Heropen Thread'); // Unlock button -define('L_BAN', 'Ban'); // Ban button -define('L_UNBAN', 'Ontban'); // Unban button -define('L_MODLOGOUT', 'Moderator Logout'); // Moderator Logout -define('L_MODLOGIN', 'Moderator Login'); // Moderator Login -define('L_LOGOUT', 'Uitloggen'); // Logout -define('L_LOGIN', 'Inloggen'); // Login + // Warnings and errors + 'PHP_OUTDATED' => 'Upgrade je PHP versie naar op zijn minst 5.3.', + 'SQL_FUNCTION' => 'Jou PHP installatie heeft geen ondersteuning voor PDO.', + 'SQL_CONNECT' => 'SQL Verbindings Fout', + 'INVALIDCAPTCHA' => 'Verificatie mislukt!', + 'DEL_SUCCEED' => 'Succesvol verwijderd!', + 'DEL_FAILED' => 'Verwijderen mislukt.', + 'USERBANNEDMSG' => 'Je bent verbannen van dit forum.', + 'USERBANNED' => 'Kon de actie niet voltooien omdat je IP verbannen is.', + + // Moderator tools + 'DELETE' => 'Verwijder', + 'PURGE' => 'Verwijder Thread', + 'LOCK' => 'Sluit Thread', + 'UNLOCK' => 'Open Thread', + 'BAN' => 'Verban IP', + 'UNBAN' => 'Ontban IP', + 'MODLOGOUT' => 'Moderator Authenticatie', + 'MODLOGIN' => 'Moderator Authenticatie', + 'LOGOUT' => 'Uitloggen', + 'LOGIN' => 'Inloggen' + +]; diff --git a/lang/pl.php b/lang/pl.php index d01b680..bc502b8 100644 --- a/lang/pl.php +++ b/lang/pl.php @@ -1,66 +1,72 @@ <?php -/** - Ninechan Polish Translation - By Kamil Rakowski <kamilrakowski1@interia.pl> -**/ +/* + * Polish translation + * By Kamil Rakowski <https://github.com/kamil0> + */ -// Meta // -define('LDATA_VERSION', '1.11alpha2'); // Version of ninechan language file is made for +// Version of ninechan this language file is created for +$langVersion = '2.0'; -// Board // -define('L_THREADS', 'Wątki'); // Threads -define('L_THREAD', 'Wątek'); // Thread -define('L_NEWTHREAD', 'Nowy Wątek'); // New Thread -define('L_NEWREPLY', 'Nowa Odpowiedz'); // New Reply -define('L_LOCKED', 'Zamknięty'); // Locked -define('L_BY', 'z'); // by +$language = [ -// Posting // -define('L_RETO', 'Odpowiedzi do'); // Reply to -define('L_TITLE', 'Tytuł'); // Title -define('L_NAME', 'Nazwa'); // Name -define('L_EMAIL', 'Email'); // Name -define('L_COMMENT', 'Komentarz'); // Comment -define('L_SUBMIT', 'Prześlij'); // Submit -define('L_VERIFICATION', 'Weryfikacja'); // Verification -define('L_PASSWORD', 'Hasło'); // Password -define('L_PASSWORDCONTEXT', 'Służy do usuwania postów'); // used for post deletion -define('L_DELPOST', 'Usun Post'); // Delete post + // Board + 'THREADS' => 'Wątki', + 'THREAD' => 'Wątek', + 'NEWTHREAD' => 'Nowy Wątek', + 'NEWREPLY' => 'Nowa Odpowiedz', + 'LOCKED' => 'Zamknięty', + 'BY' => 'z', + 'RETURN' => 'Return to Index', -// Messages // -define('L_BOARD_CLOSED', $ninechan['title'].' forumy są teraz zamknięte.'); // Boards are closed -define('L_REASON', 'Powód'); // Reason -define('L_BANNED', 'Ty zostałeś zbanowany z tego forum.'); // Text displayed upon being banned -define('L_POSTBANNED', '(UŻYTKOWNIK ZOSTAŁ ZBANOWANY ZA TEN POST)'); // Text displayed under banned post -define('L_EMPTY', 'Istnieją nie ma wątków.'); // Text displayed when the board is empty -define('L_NONEXISTENT', 'Wątek nie istnieje.'); // Text displayed when the board is empty -define('L_LOCKEDMSG', 'Wątek który próbowano odpowiedzieć jest zamknięta.'); // Text displayed when the thread is locked and replying isn't possible -define('L_LOCKEDMSG_2', 'Twój post w wątku jest zablokowany i nie jest już możliwe jest usunięcie.'); // Text displayed when the thread is locked and deleting isn't possible -define('L_POSTED', 'Wysłany pomyślnie!'); // Text displayed when the post is successful -define('L_MODTOOLS', 'Narzędzia moderatorów powinien pojawić się obok postów.'); // Mod tools message -define('L_TITLETOOSHORT', 'Dany tytuł jest za krótki.'); // The given title is too short. -define('L_TITLETOOLONG', 'Dany tytuł jest za długi.'); // The given title is too long. -define('L_COMMENTTOOSHORT', 'Dany komentarz jest za krótki.'); // The given comment is too short. -define('L_COMMENTTOOLONG', 'Dany komentarz jest za długi.'); // The given comment is too long. + // Posting + 'RETO' => 'Odpowiedzi do', + 'TITLE' => 'Tytuł', + 'NAME' => 'Nazwa', + 'EMAIL' => 'Email', + 'COMMENT' => 'Komentarz', + 'SUBMIT' => 'Prześlij', + 'VERIFICATION' => 'Weryfikacja', + 'PASSWORD' => 'Hasło', + 'PASSWORDCONTEXT' => 'służy do usuwania postów', + 'DELPOST' => 'Usun Post', -// Warnings and errors // -define('L_PHP_OUTDATED', 'Uaktualnij PHP do wersji 5.3 lub wyższej.'); // Outdated PHP version -define('L_SQL_FUNCTION', 'PDO nie jest włączona w twoje instalacji PHP.'); // SQL connect function does not exist -define('L_SQL_CONNECT', 'Błąd Połączenia SQL'); // Error while connecting to MySQL -define('L_INVALIDCAPTCHA', 'Weryfikacja nieudany!'); // Message displayed when captcha is wrong -define('L_DEL_SUCCEED', 'Usunięcie udane!'); // Message displayed when post is deleted -define('L_DEL_FAILED', 'Usunięcie nieudany!'); // Message displayed when post isn't deleted -define('L_USERBANNEDMSG', 'Są zbanowany od księgowania na tym forum.'); // Message displayed on top of the board when IP is banned -define('L_USERBANNED', 'Nie można ukończyć funkcji, ponieważ adres IP jest zbanowany.'); // Message displayed when trying to access a restricted page + // Messages + 'BOARD_CLOSED' => 'Forumy są teraz zamknięte.', + 'REASON' => 'Powód', + 'BANNED' => 'Ty zostałeś zbanowany z tego forum.', + 'POSTBANNED' => '(UŻYTKOWNIK ZOSTAŁ ZBANOWANY ZA TEN POST)', + 'EMPTY' => 'Istnieją nie ma wątków.', + 'NONEXISTENT' => 'Wątek nie istnieje.', + 'LOCKEDMSG' => 'Wątek który próbowano odpowiedzieć jest zamknięta.', + 'LOCKEDMSGDEL' => 'Twój post w wątku jest zablokowany i nie jest już możliwe jest usunięcie.', + 'POSTED' => 'Wysłany pomyślnie!', + 'MODTOOLS' => 'Narzędzia moderatorów powinien pojawić się obok postów.', + 'TITLETOOSHORT' => 'Dany tytuł jest za krótki.', + 'TITLETOOLONG' => 'Dany tytuł jest za długi.', + 'COMMENTTOOSHORT' => 'Dany komentarz jest za krótki.', + 'COMMENTTOOLONG' => 'Dany komentarz jest za długi.', + 'NOTNUMERIC' => 'Could not retrieve post data because the ID you requested is not numeric, check your URL and try again.', -// Moderator tools // -define('L_DELETE', 'Usuń'); // Delete button -define('L_PURGE', 'Oczyścić Wątek'); // Purge button -define('L_LOCK', 'Zamknij Wątek'); // Lock button -define('L_UNLOCK', 'Otwórz Wątek'); // Unlock button -define('L_BAN', 'Zbanuj'); // Ban button -define('L_UNBAN', 'Anuluj Zbanów'); // Unban button -define('L_MODLOGOUT', 'Moderatora Wyloguj'); // Moderator Logout -define('L_MODLOGIN', 'Moderatora Zaloguj'); // Moderator Login -define('L_LOGOUT', 'Wyloguj'); // Logout -define('L_LOGIN', 'Zaloguj'); // Login + // Warnings and errors + 'PHP_OUTDATED' => 'Uaktualnij PHP do wersji 5.3 lub wyższej.', + 'SQL_FUNCTION' => 'PDO nie jest włączona w twoje instalacji PHP.', + 'SQL_CONNECT' => 'Błąd Połączenia SQL', + 'INVALIDCAPTCHA' => 'Weryfikacja nieudany!', + 'DEL_SUCCEED' => 'Usunięcie udane!', + 'DEL_FAILED' => 'Usunięcie nieudany!', + 'USERBANNEDMSG' => 'Są zbanowany od księgowania na tym forum.', + 'USERBANNED' => 'Nie można ukończyć funkcji, ponieważ adres IP jest zbanowany.', + + // Moderator tools + 'DELETE' => 'Usuń', + 'PURGE' => 'Oczyścić Wątek', + 'LOCK' => 'Zamknij Wątek', + 'UNLOCK' => 'Otwórz Wątek', + 'BAN' => 'Zbanuj', + 'UNBAN' => 'Anuluj Zbanów', + 'MODLOGOUT' => 'Moderatora Wyloguj', + 'MODLOGIN' => 'Moderatora Zaloguj', + 'LOGOUT' => 'Wyloguj', + 'LOGIN' => 'Zaloguj' + +]; diff --git a/ninechan.css b/ninechan.css index 57b1cfa..c921629 100644 --- a/ninechan.css +++ b/ninechan.css @@ -91,4 +91,4 @@ table.postForm > tbody > tr > td:first-child { } .modcap { color: #660099 !important; -} +} \ No newline at end of file diff --git a/ninechan2.css b/ninechan2.css index 48c5528..530fcba 100644 --- a/ninechan2.css +++ b/ninechan2.css @@ -91,4 +91,4 @@ table.postForm > tbody > tr > td:first-child { } .modcap { color: #660099 !important; -} +} \ No newline at end of file diff --git a/recaptcha.php b/recaptcha.php deleted file mode 100644 index 81fb94b..0000000 --- a/recaptcha.php +++ /dev/null @@ -1,277 +0,0 @@ -<?php -/* - * This is a PHP library that handles calling reCAPTCHA. - * - Documentation and latest version - * http://recaptcha.net/plugins/php/ - * - Get a reCAPTCHA API Key - * https://www.google.com/recaptcha/admin/create - * - Discussion group - * http://groups.google.com/group/recaptcha - * - * Copyright (c) 2007 reCAPTCHA -- http://recaptcha.net - * AUTHORS: - * Mike Crawford - * Ben Maurer - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -/** - * The reCAPTCHA server URL's - */ -define("RECAPTCHA_API_SERVER", "http://www.google.com/recaptcha/api"); -define("RECAPTCHA_API_SECURE_SERVER", "https://www.google.com/recaptcha/api"); -define("RECAPTCHA_VERIFY_SERVER", "www.google.com"); - -/** - * Encodes the given data into a query string format - * @param $data - array of string elements to be encoded - * @return string - encoded request - */ -function _recaptcha_qsencode ($data) { - $req = ""; - foreach ( $data as $key => $value ) - $req .= $key . '=' . urlencode( stripslashes($value) ) . '&'; - - // Cut the last '&' - $req=substr($req,0,strlen($req)-1); - return $req; -} - - - -/** - * Submits an HTTP POST to a reCAPTCHA server - * @param string $host - * @param string $path - * @param array $data - * @param int port - * @return array response - */ -function _recaptcha_http_post($host, $path, $data, $port = 80) { - - $req = _recaptcha_qsencode ($data); - - $http_request = "POST $path HTTP/1.0\r\n"; - $http_request .= "Host: $host\r\n"; - $http_request .= "Content-Type: application/x-www-form-urlencoded;\r\n"; - $http_request .= "Content-Length: " . strlen($req) . "\r\n"; - $http_request .= "User-Agent: reCAPTCHA/PHP\r\n"; - $http_request .= "\r\n"; - $http_request .= $req; - - $response = ''; - if( false == ( $fs = @fsockopen($host, $port, $errno, $errstr, 10) ) ) { - die ('Could not open socket'); - } - - fwrite($fs, $http_request); - - while ( !feof($fs) ) - $response .= fgets($fs, 1160); // One TCP-IP packet - fclose($fs); - $response = explode("\r\n\r\n", $response, 2); - - return $response; -} - - - -/** - * Gets the challenge HTML (javascript and non-javascript version). - * This is called from the browser, and the resulting reCAPTCHA HTML widget - * is embedded within the HTML form it was called from. - * @param string $pubkey A public key for reCAPTCHA - * @param string $error The error given by reCAPTCHA (optional, default is null) - * @param boolean $use_ssl Should the request be made over ssl? (optional, default is false) - - * @return string - The HTML to be embedded in the user's form. - */ -function recaptcha_get_html ($pubkey, $error = null, $use_ssl = false) -{ - if ($pubkey == null || $pubkey == '') { - die ("To use reCAPTCHA you must get an API key from <a href='https://www.google.com/recaptcha/admin/create'>https://www.google.com/recaptcha/admin/create</a>"); - } - - if ($use_ssl) { - $server = RECAPTCHA_API_SECURE_SERVER; - } else { - $server = RECAPTCHA_API_SERVER; - } - - $errorpart = ""; - if ($error) { - $errorpart = "&error=" . $error; - } - return '<script type="text/javascript" src="'. $server . '/challenge?k=' . $pubkey . $errorpart . '"></script> - - <noscript> - <iframe src="'. $server . '/noscript?k=' . $pubkey . $errorpart . '" height="300" width="500" frameborder="0"></iframe><br/> - <textarea name="recaptcha_challenge_field" rows="3" cols="40"></textarea> - <input type="hidden" name="recaptcha_response_field" value="manual_challenge"/> - </noscript>'; -} - - - - -/** - * A ReCaptchaResponse is returned from recaptcha_check_answer() - */ -class ReCaptchaResponse { - var $is_valid; - var $error; -} - - -/** - * Calls an HTTP POST function to verify if the user's guess was correct - * @param string $privkey - * @param string $remoteip - * @param string $challenge - * @param string $response - * @param array $extra_params an array of extra variables to post to the server - * @return ReCaptchaResponse - */ -function recaptcha_check_answer ($privkey, $remoteip, $challenge, $response, $extra_params = array()) -{ - if ($privkey == null || $privkey == '') { - die ("To use reCAPTCHA you must get an API key from <a href='https://www.google.com/recaptcha/admin/create'>https://www.google.com/recaptcha/admin/create</a>"); - } - - if ($remoteip == null || $remoteip == '') { - die ("For security reasons, you must pass the remote ip to reCAPTCHA"); - } - - - - //discard spam submissions - if ($challenge == null || strlen($challenge) == 0 || $response == null || strlen($response) == 0) { - $recaptcha_response = new ReCaptchaResponse(); - $recaptcha_response->is_valid = false; - $recaptcha_response->error = 'incorrect-captcha-sol'; - return $recaptcha_response; - } - - $response = _recaptcha_http_post (RECAPTCHA_VERIFY_SERVER, "/recaptcha/api/verify", - array ( - 'privatekey' => $privkey, - 'remoteip' => $remoteip, - 'challenge' => $challenge, - 'response' => $response - ) + $extra_params - ); - - $answers = explode ("\n", $response [1]); - $recaptcha_response = new ReCaptchaResponse(); - - if (trim ($answers [0]) == 'true') { - $recaptcha_response->is_valid = true; - } - else { - $recaptcha_response->is_valid = false; - $recaptcha_response->error = $answers [1]; - } - return $recaptcha_response; - -} - -/** - * gets a URL where the user can sign up for reCAPTCHA. If your application - * has a configuration page where you enter a key, you should provide a link - * using this function. - * @param string $domain The domain where the page is hosted - * @param string $appname The name of your application - */ -function recaptcha_get_signup_url ($domain = null, $appname = null) { - return "https://www.google.com/recaptcha/admin/create?" . _recaptcha_qsencode (array ('domains' => $domain, 'app' => $appname)); -} - -function _recaptcha_aes_pad($val) { - $block_size = 16; - $numpad = $block_size - (strlen ($val) % $block_size); - return str_pad($val, strlen ($val) + $numpad, chr($numpad)); -} - -/* Mailhide related code */ - -function _recaptcha_aes_encrypt($val,$ky) { - if (! function_exists ("mcrypt_encrypt")) { - die ("To use reCAPTCHA Mailhide, you need to have the mcrypt php module installed."); - } - $mode=MCRYPT_MODE_CBC; - $enc=MCRYPT_RIJNDAEL_128; - $val=_recaptcha_aes_pad($val); - return mcrypt_encrypt($enc, $ky, $val, $mode, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"); -} - - -function _recaptcha_mailhide_urlbase64 ($x) { - return strtr(base64_encode ($x), '+/', '-_'); -} - -/* gets the reCAPTCHA Mailhide url for a given email, public key and private key */ -function recaptcha_mailhide_url($pubkey, $privkey, $email) { - if ($pubkey == '' || $pubkey == null || $privkey == "" || $privkey == null) { - die ("To use reCAPTCHA Mailhide, you have to sign up for a public and private key, " . - "you can do so at <a href='http://www.google.com/recaptcha/mailhide/apikey'>http://www.google.com/recaptcha/mailhide/apikey</a>"); - } - - - $ky = pack('H*', $privkey); - $cryptmail = _recaptcha_aes_encrypt ($email, $ky); - - return "http://www.google.com/recaptcha/mailhide/d?k=" . $pubkey . "&c=" . _recaptcha_mailhide_urlbase64 ($cryptmail); -} - -/** - * gets the parts of the email to expose to the user. - * eg, given johndoe@example,com return ["john", "example.com"]. - * the email is then displayed as john...@example.com - */ -function _recaptcha_mailhide_email_parts ($email) { - $arr = preg_split("/@/", $email ); - - if (strlen ($arr[0]) <= 4) { - $arr[0] = substr ($arr[0], 0, 1); - } else if (strlen ($arr[0]) <= 6) { - $arr[0] = substr ($arr[0], 0, 3); - } else { - $arr[0] = substr ($arr[0], 0, 4); - } - return $arr; -} - -/** - * Gets html to display an email address given a public an private key. - * to get a key, go to: - * - * http://www.google.com/recaptcha/mailhide/apikey - */ -function recaptcha_mailhide_html($pubkey, $privkey, $email) { - $emailparts = _recaptcha_mailhide_email_parts ($email); - $url = recaptcha_mailhide_url ($pubkey, $privkey, $email); - - return htmlentities($emailparts[0]) . "<a href='" . htmlentities ($url) . - "' onclick=\"window.open('" . htmlentities ($url) . "', '', 'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0,width=500,height=300'); return false;\" title=\"Reveal this e-mail address\">...</a>@" . htmlentities ($emailparts [1]); - -} - - -?> diff --git a/structure.sql b/structure.sql new file mode 100644 index 0000000..54c30cf --- /dev/null +++ b/structure.sql @@ -0,0 +1,26 @@ +-- Adminer 4.2.0 MySQL dump + +SET NAMES utf8mb4; +SET time_zone = '+00:00'; + +DROP TABLE IF EXISTS `ninechan`; +CREATE TABLE `ninechan` ( + `id` int(16) unsigned NOT NULL AUTO_INCREMENT, + `title` varchar(255) COLLATE utf8_bin NOT NULL, + `name` varchar(255) COLLATE utf8_bin DEFAULT NULL, + `trip` varchar(255) COLLATE utf8_bin DEFAULT NULL, + `email` varchar(255) COLLATE utf8_bin DEFAULT NULL, + `date` varchar(255) COLLATE utf8_bin NOT NULL, + `content` text COLLATE utf8_bin NOT NULL, + `password` varchar(255) COLLATE utf8_bin NOT NULL, + `ip` varchar(255) COLLATE utf8_bin NOT NULL, + `op` tinyint(1) unsigned NOT NULL DEFAULT '1', + `tid` int(16) unsigned NOT NULL DEFAULT '0', + `locked` tinyint(1) unsigned NOT NULL DEFAULT '0', + `ban` tinyint(1) unsigned NOT NULL DEFAULT '0', + `lastreply` int(11) unsigned NOT NULL DEFAULT '0', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; + + +-- 2015-05-12 19:19:23 diff --git a/todo.txt b/todo.txt deleted file mode 100644 index cbb21ef..0000000 --- a/todo.txt +++ /dev/null @@ -1,6 +0,0 @@ -Todo list -==================== -- Redo the projectile vomit from line 293 till 319 -- Ram some prepared statements in there -- Improve JavaScript(?) -- Make bbcode management more convenient \ No newline at end of file diff --git a/updatedb.php b/updatedb.php deleted file mode 100644 index 2b82e17..0000000 --- a/updatedb.php +++ /dev/null @@ -1,51 +0,0 @@ -<?php -/* - * Ninechan Board Script SQL Updater for Version 1.11 - * by Flashwave <http://flash.moe> - * Distributed under the MIT-License - */ - -// Require configuration -require_once 'config.php'; - -// Force enable error reporting -error_reporting(-1); - -// Check dependencies -if(version_compare(phpversion(), '5.3.0', '<')) // PHP 5.3 or higher - die('<h2>' . L_PHP_OUTDATED . '</h2>'); - -if(!extension_loaded('PDO')) // Check if PHP Data Objects is available - die('<h2>' . L_SQL_FUNCTION . '</h2>'); - - -// Connect to SQL using PDO -try { - $sqldb = new PDO($sql['dsn'], $sql['user'], $sql['pass']); -} catch(PDOException $e) { // Catch connection error - print '<h2>' . L_SQL_CONNECT . '</h2>'; - die($e->getMessage()); -} - -print '<html><head><title>ninechan db updater</title><link rel="stylesheet" type="text/css" href="./ninechan.css" /></head><body>'; -print '<h1>ninechan updater</h1> <i>For updating your database to ninechan 1.9/1.10 to 1.11</i><hr />'; - -if(isset($_POST['ready'])) { - print '<form method="post" action="'. $_SERVER['PHP_SELF'] .'">'; - print 'Database update successful!'; - print 'Now delete updatedb.php for security reasons, <u>unlike ninechan 1.9 this version will continue working while this file is present</u>.<br />'; - print '<input type="submit" name="kill" value="Delete updatedb.php" />'; - print '</form>'; - - $sqldb->query("ALTER TABLE `".$sql['table']."` CHANGE `name` `name` text;"); - $sqldb->query("ALTER TABLE `".$sql['table']."` CHANGE `trip` `trip` text;"); - $sqldb->query("ALTER TABLE `".$sql['table']."` CHANGE `email` `email` text;"); -} elseif(isset($_POST['kill'])) { - print 'Deleted updatedb.php, you will now be redirected to the board.'; - unlink("updatedb.php"); - print '<meta http-equiv="refresh" content="1; URL=./">'; -} else { - print '<form method="post" action="'. $_SERVER['PHP_SELF'] .'"><input type="submit" name="ready" value="Click this button once you\'re ready" /></form>'; -} - -print '<h6><a href="http://ninechan.flash.moe/" target="_blank">ninechan</a> updater 1.11 © <a href="http://flash.moe/" target="_blank">Flashwave</a></h6></body></html>';