Thank you for pointing it out, will fix. And now I've reached my boiling point, so here it is: the truth about Tinyboard, vichan, infinity, and any other imageboard software forked from them. Long story short: SLOPPY™
. Using vichan? – Memento mori.
I know I'm about to spew forth a technical tirade that little of you will be able to comprehend or care to read at all, but I just can't keep my boiling hatred inside anymore, my pain of dealing with vichan imageboard software is overwhelming. So, I have rewritten major portions of current GUROchan codebase after some profiling to speed up the whole thing. I know that I promised you all a brand new imageboard software, but it isn't going well enough due to my perma-apathetic mood and lack of motivation. It will happen someday, that's the most I can promise right now. Nevertheless, I've reached my boiling point with the current code in production: vichan. No words can describe just how bad it is technically. I'll give you this: 50% of my reasoning was ideological, running this software actually hurts
my feelings, literally, just thinking about our hardware executing its incredibly poorly written code insults me and pisses me off. I am ashamed
of using it, no kidding. vichan is just unbelievably shitty, it is one of the worst pieces of PHP software I've ever seen
, written by fucking kids who learned a few basics of PHP and MySQL and thought: "Hey wow, now I can write my own cool imageboard with it! New and improved! With blackjack and whores! Yay! Time to get busy!" You know, the usual train of thought of a hyped up overexcited dumbass teenager, utterly awkward. No shit, they did it. Did it with zero experience and not a fucking yota of knowledge of even basic computer science topics it takes to produce anything at least remotely good. You get this impression instantly by just glancing at the vichan source code. "For teenaged morons by teenaged morons" as their motto goes unspoken.
To those who wonder what might be wrong with the aforementioned approach, here's a hint: NO, that's not how software is written. First, you sit down and study computer science, algorithms (Knuth before all), programming ideas, principles, and paradigms. Then you analyze your task and explore and evaluate the tools needed to do it, google around, ask for tips and pointers. Then you pick your tools (PHP+SQL in our case) and study them thoroughly
by reading technical literature available in rich selection. Then you make up a complete plan of what you are going to do, and how exactly, usually employing the "divide and conquer" principle by breaking up the task into logically orthogonal interacting units. And only after all of that you actually start writing code unit by unit. And finish with testing (+ regress-testing for updates), debugging, profiling, and optimizing. At least that's how I've been taught... But apparently not this shitshow crew behind Tinyboard and vichan.
Here's a quick list that highlights some of the more blatant, awkward, and outright atrocious moments and topics the sorry authors of Tinyboard and vichan have no fucking clue about. "Doing it wrong" – heard this idiom? Here, know your meme:
– PHP. No, they don't know how to program in PHP properly. In fact, they just don't know how to program. Consider the most trivial thing: code reuse: their shitcode is ridiculously and horridly repetitive, they write the same shit all over and over again instead of packing it into a simple function or class method. Really, why bother with writing functions when I can just copypaste? So what if my source file is 1000+ lines of code when it could be 150? Why extract() associative arrays representing database table rows into the current scope for ease of use and one less level of Zend namespace lookups when we're trained to write array subscripts everywhere? Who cares if each unextracted array access results in two hash table lookups instead of one? Zend engine, PHP internals? Who cares what goes on behind the scenes, we simply pretend we didn't know that PHP was interpreted. Go eat some shit you little PHP wannabe kids.
– Object-oriented programming: they don't know how to write and use classes to their advantage, let alone such cryptic words as "encapsulation" or "inheritance", so they avoid them, and when they actually do use the OOP approach (Thread, Post, and Bans classes), they do it all wrong as usual. Really, why bother encapsulating entities as autonomous, self-contained objects when we can litter all our code with global variables and thus have no need to toss around data between functions. Why use objects instead of arrays, so what if you can encapsulate logic into them as methods? We're just fine littering the global namespace even more with plain functions. Look, inc/functions.php will soon be reaching 3000 lines of code, we're just that awesome! Irredeemable programmer failures.
– SQL: no idea about relational database architecture in general, about proper usage of SQL types and constraints, non-existent schema normalization, clueless about business logic encapsulation with stored procedures and triggers, they never heard of views that could make their queries in PHP compact and elegant, equally make no use of correlated subqueries where they should be used (instead doing it all manually from PHP query-by-query in loops, i.e. tons of wasteful and inherently slower PHP shitcode when it all could be expressed with a single correlated SQL subquery), they know literally nothing beyond primitive SELECT and INSERT/DELETE/UPDATE, which is like spitting in the faces of SQL inventors who took time to make it as powerful as it is in hands of those who actually know how to leverage its power. These guys think SQL is all about simplistic queries like "SELECT shit FROM code WHERE software = vichan"–no wonder they have to write tons over tons of absolutely meaningless, redundant code, reinventing the wheel again and again. Pathetic to the core, but really just a matter of a week of careful reading of an SQL textbook, but these youngsters don't have time to waste on something as old-fashioned as reading and learning–they must create
here and now.
– Data integrity: the database schema doesn't have a single foreign key when there are dozens of places where they should be used. Not to mention the completely idiotic "each-board-gets-its-own-posts-table" partitioning idea that prevents me as an end user to write generic, board-agnostic stored procedures and queries with static, pre-computed plans. Their approach to database schema reeks of premature optimization and total ignorance of what "relational" in "relational database" is all about.
– "Transactions? Unheard of." PHP and MySQL/InnoDB have all the means to provide full transactional integrity to all IB operations (including coherent cache invalidation by employing gumballs as described in a well-known academic paper), and at little cost code-wise, but the fuckers have no clue about such high topics. Combine this with their moronic way of issuing myriads of primitive SQL queries instead of one and stitching the results together manually, and you get a case where two concurrent operations can easily fuck each other in the ass by interleaving and yielding corrupted results, in certain places possibly leading to permanent database corruption, since none of the integrity insurance means provided by MySQL are being used.
– Oh, database corruption, yeah! We have some experience here. They sort threads in boards by fucking timestamps! Timestamps
, Carl! Very sloppy™ design decision. Not just short-sighted and foolish, but actually dangerous and potentially leading to data loss. Real production example: we once had a firmware CMOS battery fault that reset the server clock, making new threads date January 1970. Remember when many threads were suddenly gone?.. Now you know why. Hint: every time-sortable table row must
be sorted by a surrogate timestamp, that is, a unique numeric table column continuously increasing for each insertion or update, no exceptions. AUTO_INCREMENT for MySQL and SERIAL types and SEQUENCE objects for PostgreSQL with automatic updating by triggers is the only technically sound way of doing bulletproof sorting. Otherwise a system clock skew can easily lead to unforeseen and disastrous consequences, just like what happened to us.
– The HTTP protocol and server-gateway relationship: improper use of HTTP status codes, emulated "soft" error pages, no HTTP cache control whatsoever, doing shit in PHP that doesn't belong there and should be done on the HTTP server level (authentication, caching, and post flood protection among others.) Why the hell call PHP (a costly operation that in our setup involves establishing a UNIX domain socket connection to PHP-FPM and forking PHP-FPM itself) to execute a bunch of trivial math formulas to do flood control when you can leverage much better rate limiting means of your HTTP server? They aim to support many setups, as such not tying to particular software, but you've got to know where the responsibility border line goes: a PHP script is not supposed
to rate-limit itself, it is the job of whatever executes that script. Whoever doesn't understand this simple truth shouldn't be writing programs.
– Configuration in PHP. Sloppy™! There's parse_ini_file() designed specifically
for reading array-based configuration from INI files, you pitiful ignorant shitheads. Or JSON, if you want more flexibility. Or YAML. Or XML. You name it. While marginally slower, all of these methods are more appropriate from the logic/design standpoint. Did you know that vichan's stock example config file is about 70% of all of my new IB's code? But that's not the point: IB configuration should be stored in the database too, for fuck's sake, not some .php file. That's what the database is for, it is used to store data, everything
related to a particular instance or installation, i.e. precisely for the purpose in question. Yet these morons have no clue as usual, keeping part of data in the database and the rest in .php files. You can't just backup the database, you have to backup code itself, which is supposed to be plug-in downloadable from vendor repository when re-deploying from backup. Then again, MySQL supports LOBs for in-database storage of files–it takes as little as an extra table for LOBs, a table for post-to-LOB mapping, and two ON DELETE CASCADE foreign keys to make the entire thing self-contained (images in the database, easy backup), transactional, with data integrity guaranteed by database journal, and without all the shitty code vichan has in clean() for deleting files: a single DELETE SQL query, and files are gone along with their respective posts automatically, completely effortless and transparent.
– Security and cryptography: passwords for posts are stored in plaintext
(sic!) No hashing, not even UNIX crypt(3)! I'd rip the face of the moron who made it so should I meet him in streets. Moderator account passwords are hashed using one of the lamest homemade crypto combinations of hash functions I've ever seen (second only to UnrealIRCd IP address cloaking) that add exactly zero cryptographic merit to each other whereas a single moderate-rounds call to a decent, mature, proven cryptographically sound KDF like bcrypt, scrypt, Argon2, or even the aging PBKDF2 would make it flawlessly neat and stronger than any MD5/SHA soup by a vast margin. In other words, they attempt to roll their own crypto without knowing a fuck about it
–the worst antipattern in crypto ever, it's like a monkey playing with a hand grenade. But the biggest thing they don't realize is that crypto doesn't belong in PHP code at all
by definition and design. CGI scripts are nothing but a thin glue layer between the backend (database) and the frontend (HTTP server), their only tasks are relaying data between the two and rendering HTML, they're just not supposed to encrypt or hash anything as per proper WWW site engineering: (a) authentication crypto for moderator sessions (SSL/TLS client certificates and/or HTTP authentication) entirely belongs to the web server because it is the web server that actually manages those sessions, no reason to offload their handling to PHP, and (b) handling of user-supplied secrets like passwords is entirely the business of the RDBMS backend, those secrets must never be communicated across the database session. So, PHP's natural role in the website framework is inherently crypto- and security-agnostic; if it involves itself in crypto, then it is doing the wrong job, thereby the very design of the site is defective and flawed from birth.
– Moderator login sessions, another large fuck-up of the vichan team. Instead of using PHP's start_session()–the one tool, tweakable and proven, specifically designed to provide cross-request session support–they do it manually with setcookie() in their trademark sloppy™ way... Why? Apparently because they never cared to study the subject before implementing it, it seems to be their credo of sorts, they're like Chip'n'Dale: "We don't have a plan, but we're doing it!" Very brave, if a bit retarded. OK, but there's more to it: their CSRF protection is insecure.
Read any paper on CSRF (cross-site request forgery) protection, and they will highlight it up front: never use GET as it leaks the security token in a web browser's address bar, history, bookmarks, and God knows where else; always use POST to submit CSRF-protected requests. But what do they know, right? vichan knows better and does exactly the opposite: never POST, always GET. To add insult to injury, they do not generate random CSRF tokens for each session, instead using meaningless and mindless SHA-1 hashing operation on a single pre-generated server salt stored in $config plus request URI and moderator ID... It all means that a single hijacked session can compromise all
future sessions, since the attacker obtains the salt, and URIs and moderator IDs are easily guessable. And this is all happening in a GET request with tokens being only 8 characters long. So, anyone can just overlook the URL in your browser over your shoulder, memorize it and the token in it, spend a few weeks bruteforcing SHA-1 to get a hash collision, and that's it, you're fucked. God, let the bastards who wrote it die a horrible death and burn in hell forever for even attempting to do security and crypto without having the tiniest fucking clue, please! (For the curious: the right way is to generate a long enough random session token for each
request with random_bytes(), store it in $_SESSION, and use hash_equals() for validation.)
– Here's one bug I reported to vichan-devel and never received response on: when you delete posts by password, vichan compares passwords (a) in PHP instead of MySQL using data from a completely redundant SELECT when all it takes is a single DELETE, and (b) using a type-coercing == operator, which means that if you post with password " foo", then you can delete it with "foo"
, i.e. the comparison of password strings is broken and follows the defective by design rules of loose PHP comparison. If curious how to do it right: hash_equals(). But in that particular case password comparison must happen strictly inside MySQL (i.e. in a WHERE clause to DELETE) for security reasons lest the database leaks secret data over possibly unencrypted and untrusted communications channel between the MySQL server backend and the PHP client frontend. Mind you, this is common and trivial security knowledge... or at least supposed to be so.
– Algorithmic complexity (certain SQL plans yield linear tablescans on unkeyed columns whereas a properly constituted key could shrink it down on logarithmic scale.)
– HTML templating: the sloppy™ way. For such a small and primitive thing as an imageboard, using Twig (coincidentally the most bloated templater for PHP out there) is imbecilic. PHP as a template language itself suits much better in this particular niche, rendering HTML orders of magnitude faster (up to 500-600 times on PHP 7, real figures) than Twig, which is essentially "a template language written in a template language." Using Twig for an IB is like shooting down sparrows with a flak cannon when you can do the same with plain PHP in dedicated .phtml files.
– Common sense. Need to check if a file is readable? fopen() and fclose()? Unheard of. Here in Tinyboard Development Group (the shitcode factory behind it all) and vichan-devel (their accomplices in sin) we do it our way: read it all into memory with file_get_contents() and use an implicit boolean cast in an "if" statement... If people doing that sort of things don't deserve capital punishment, then who does? Another gag is right in their pretentious title of the vichan trunk on GitHub: "A lightweight and full featured PHP imageboard."
Hahaha, lightweight my ass, you braindead apes. Wishful thinking all over the place. Just who the fuck do they think they are, bullshitting everyone so openly and blatantly!?
And many, many more... You might as well just roll your own IB from scratch instead of trying to fix these countless shitlines of shitcode, which is exactly the motivation behind my primary project. Tinyboard code, and code of its derivatives such as vichan or infinity, is literally a nightmare for any skilled and educated programmer, and an insult for any computer science-literate person. It is a wretched and insecure pile of outright junk code written by uneducated script kiddies who dared to think of themselves as programmers. It rots and reeks as I'm writing this, I can smell it across the HTTP session. It is virtually unmanageable and unmaintainable, it is extraordinarily slow, bloated, and of course sloppy™. It boasts many features, and every single one of those features is done sloppily and wrong. Tinyboard/vichan is a vile and grotesque collection of various programming and design antipatterns, and I have enough knowledge and experience in all of the aforementioned topics to declare it out loud as undebatable truth. Its authors are shameless and clueless programmer wannabe fuckers, because publishing such shit of a software is no less shameful than displaying dirty underwear. Avoid it at all costs, or face the unsightly consequences I am facing right now with it.
I am sorry to run vichan on GUROchan. Using vichan for GUROchan was a terrible mistake on our part due to lack of experience with other IB software packages when we first started our project, and it keeps backfiring, again and again. I apologize, guys, we fucked up big time with our software choice, and what I'm doing now is sorting out the resulting mess. So, the least I can do right now is send a word of warning to everyone who wants to run an imageboard: don't even think of using vichan, infinity, or any other disgusting Tinyboard derivative, all of them are shitty beyond any description or belief. I repeat, never
touch those stillborn abominations, have some dignity. And remember that "Tinyboard", God forgive, is an utterly misleading and awkward oxymoron of a name–in reality it is one of the fattest, bulkiest, most fucking bloated IBs in existence; it has every feature that you don't and won't ever need. I mean it, every single word, beware of it, spread the word of warning if you care at all. Tinyboard/vichan must die a dishonorable death as the bastard brainchild deserves.
Had to take this shit out of my head, it's been corroding my mental wellness for a while now. It turned into a marvellous rant, even if I'm the only one enjoying it. I just hope that someone finds these topics interesting and fair. So, to conclude the soulcry: my replacement code may experience minor bugs and glitches–I was hasteful about it, wanting to do away with the rotten vichan code ASAP. Please take some time to report bugs whenever you spot them, your feedback will be much appreciated.