Skip to content

Commit

Permalink
v0.1.0 release!
Browse files Browse the repository at this point in the history
  • Loading branch information
5ynchrogazer committed Nov 29, 2024
1 parent 453dc77 commit 52b6e15
Show file tree
Hide file tree
Showing 53 changed files with 5,803 additions and 0 deletions.
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@

/__init/.smarty
*.env
/public_html/uploads
/software/parsedown
/software/smarty
public_html/assets/classic/js/jquery.min.js
/__init/.tmp
115 changes: 115 additions & 0 deletions README.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/–––––––––––––––––––––––––––––––––––––––––––––––––––––––\
| ##### ##### ##### # # #### ##### ##### #### # # |
| # # # # # ## # # # # # # # # # # # |
| # # ##### ### # # # #### # # # # #### # # |
| # # # # # ## # # # # # # # # # # |
| ##### # ##### # # #### ##### ##### # # ### |
\–––––––––––––––––––––––––––––––––––––––––––––––––––––––/

OpenBooru is an open-source Booru. It aims to enable users to host their own
image-library with an intuitive and extensive search, tagging-system and more.

Table of contents:
1. Installation
X. Credits

| LIVE DEMO

See OpenBooru in action at https://openbooru.net
It's running the latest version with close to no changes to the source.
Donate to keep it alive :D

| DONATIONS

I Have spent a considerable amount of time writing this. If you like this,
consider donating over at ko-fi: https://ko-fi.com/aetherwellen
It really helps me out and keeps the development going <3
(Regardless of your donation, I will keep working on this tho haha)

/–––––––––––––––––––––––––––––––––––––––––––––––––––––––\
| 1. INSTALLATION |
\–––––––––––––––––––––––––––––––––––––––––––––––––––––––/

First off, these are the requirements:
- PHP 8.x (built and tested on 8.3 but older versions should work as well)
- A MySQL Database

After downloading the latest OpenBooru release, drop it into your /var/www
folder (or whatever you use) and make sure your domain points to /public_html
so theoretically, it should only be accessable by domain.com/index.php
YOU DO NOT WANT TO ACCESS ANY FILES ABOVE FROM THE PUBLIC!
(Don't open it in the browser - you're not done yet)

OpenBooru depends on external libraries you need to install now.
Download the latest releases of Smarty, Parsedown and jQuery:
- https://github.com/smarty-php/smarty/releases/latest
- https://github.com/erusev/parsedown/releases/latest
- https://cdnjs.com/libraries/jquery

If you want to support videos, FFmpeg is also required:
- FFmpeg (https://ffmpeg.org/download.html)

Now dorp all of them in the /software directory (if it doesn't exist, create it).
The final structure should look something like this:
\ software
| \ parsedown
| | - Parsedown.php
| | - ...
| \ smarty
| | \ libs
| | | - Smarty.class.php
| | \ src
| | | - ...
\ public_html
| \ assets
| | \ classic
| | | \ js
| | | | - jquery.min.js

(For windows users)
\ software
| \ ffmpeg
| | - ffmpeg.exe
| | - ffplay.exe
| | - ffprobe.exe

After configuring your webserver (I hope you know how to do this, if not,
search the internet; I am no wiki nor do I want to teach you the basics of
your webserver), open the address and you should be redirected to install.php
(If not, you should see an error message)

| BLOCKING BOTS

By default, everything should work out of the box if you're using apache2/httpd.
If it doesn't, you've either messed up during the installation or you don't have
a specific module enabled/installed.

To block Bots on NGINX: (at least this is my guess... I use apache2)
location ~* \.(jpg|jpeg|png|gif|bmp|tiff)$ {
add_header X-Robots-Tag "noindex, nofollow";
}

/–––––––––––––––––––––––––––––––––––––––––––––––––––––––\
| X. CREDITS |
\–––––––––––––––––––––––––––––––––––––––––––––––––––––––/

As of now, everything (exceptions listed below) has been written by @5ynchrogazer.

OpenBooru makes use of following libraries:
- Smarty template engine (https://github.com/smarty-php/smarty)
- Parsedown (https://github.com/erusev/parsedown)
- jQuery
- FFmpeg

| FUN FACTS

... Every part of OpenBooru was created entirely on my ThinkPad T430 while
listening to the iCon Radio (https://iconradio.stream.laut.fm/icon_radio)
... I struggled a lot with the search-functions, they still haunt me
to this day
... Allowing guests to to upload/edit posts or make changes to the wiki will
result in the system breaking as it's not intended for users with no ID to do
anything at all, but I may fix this in the future... maybe
... Sometimes when tagging a post, it throws an error ranting about duplicate
entries... no idea what I'm supposed to do here now
... The Footer message has been inspired from Shish's Shimmie2 ;)
11 changes: 11 additions & 0 deletions TODO.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
| API KEY
Add an API key for every user that allows them to upload posts
externally, e.g. a Tampermonkey script.

| search_max_tags
Maybe make it level-based, so users with different levels can
have different amount of big searches. (English wow)

| LOCKED
Check if a Wiki tag is locked, that it really is not editable by
someone who isn't at least a moderator, idk and I'm lazy OwO
12 changes: 12 additions & 0 deletions __init/db.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

if (!defined('WORLD')) {
die("The World!");
}

$conn = new mysqli($db["host"], $db["user"], $db["pass"], $db["name"]);

// Try connecting and return error if failed
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
14 changes: 14 additions & 0 deletions __init/debug.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

if (!defined('WORLD')) {
die("The World!");
}

if ($config["debug"]) {
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
} else {
ini_set('display_errors', 0);
ini_set('display_startup_errors', 0);
}
15 changes: 15 additions & 0 deletions __init/external.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

if (!defined('WORLD')) {
die("The World!");
}

// This is fucking useless lol what is this piece of code??!
if ($config["externalapi"] == false) {
// Check if the request is coming from the same domain
if ($_SERVER['HTTP_ORIGIN'] != $_SERVER['HTTP_HOST']) {
//die("Invalid request");
}
}

//print_r($_SERVER);
59 changes: 59 additions & 0 deletions __init/language.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php

if (!defined('WORLD')) {
die("The World!");
}

$tmpDir = __DIR__ . "/.tmp";
$timestampFilePattern = $tmpDir . "/languages.json.*";
$languagesJsonURL = "https://raw.githubusercontent.com/5ynchrogazer/OpenBooru-Extras/refs/heads/master/locales.json";
$defaultLocaleFile = __DIR__ . "/../locales/en.json";
$languageFileString = __DIR__ . "/../locales/[lang].json";
$cacheDuration = 14400; // 4 hours

createTmpDir($tmpDir);
$latestFile = getLatestFile($timestampFilePattern, $cacheDuration);

if ($latestFile) {
$languagesJson = file_get_contents($latestFile);
if ($languagesJson === false) {
die("Failed to read languages JSON from temporary file.");
}
} else {
$languagesJson = fetchLanguagesJson($languagesJsonURL, $tmpDir);
}

$languagesArray = json_decode($languagesJson, true);
$locales = [];

foreach ($languagesArray as $langKey => $langValue) {
if (file_exists(str_replace("[lang]", $langKey, $languageFileString))) {
$locales[$langKey] = $langValue;
}
}

$defaultLocale = loadLocaleFile($defaultLocaleFile);
$configFile = __DIR__ . "/../locales/{$config["language"]}.json";
$locale = ($configFile == $defaultLocaleFile) ? $defaultLocale : loadLocaleFile($configFile);
$locale = array_replace_recursive($defaultLocale, $locale);

if (isset($_COOKIE["locale"]) && !empty($_COOKIE["locale"])) {
$cookieLocale = sanitize($_COOKIE["locale"]);
if (in_array($cookieLocale, array_keys($locales))) {
$cookieLocaleFile = __DIR__ . "/../locales/{$cookieLocale}.json";
if ($cookieLocaleFile != $defaultLocaleFile && $cookieLocaleFile != $configFile) {
$cookieLocaleArray = loadLocaleFile($cookieLocaleFile);
$locale = array_replace_recursive($locale, $cookieLocaleArray);
}
}
}

$lang = $locale;
$locale = $cookieLocale ?? $config["language"];
if (isset($smarty)) {
$smarty->assign('lang', $lang);
$smarty->assign("locale", $locale);
$smarty->assign("locales", $locales);
}

unset($tmpDir, $timestampFilePattern, $languagesJsonURL, $defaultLocaleFile, $languageFileString, $cacheDuration, $languagesJson, $languagesArray, $defaultLocale, $configFile, $cookieLocale, $cookieLocaleFile, $cookieLocaleArray);
13 changes: 13 additions & 0 deletions __init/parsedown.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

if (!defined('WORLD')) {
die("The World!");
}

require __DIR__ . "/../software/parsedown/Parsedown.php";

$parsedown = new Parsedown();
$parsedown->setSafeMode(true);
$parsedown->setMarkupEscaped(true);
$parsedown->setUrlsLinked(true);
$parsedown->setBreaksEnabled(true);
84 changes: 84 additions & 0 deletions __init/session.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<?php

if (!defined('WORLD')) {
die("The World!");
}

$logged = false;
$user = [];
$levelId = $levelIds["guest"];

if (isset($_COOKIE["token"]) && !empty($_COOKIE["token"])) {
$token = $conn->real_escape_string($_COOKIE["token"]);
if (strlen($token) == 64) {
$userAgent = $conn->real_escape_string($_SERVER["HTTP_USER_AGENT"]);
$_ipAddress = $conn->real_escape_string($_SERVER["REMOTE_ADDR"]);
$ipAddress = hash("sha256", $_ipAddress);

$sql = "SELECT * FROM sessions WHERE session_id = ? AND user_agent = ? AND ip_address = ? LIMIT 1";
$stmt = $conn->prepare($sql);
$stmt->bind_param("sss", $token, $userAgent, $ipAddress);
$stmt->execute();
$result = $stmt->get_result();
$session = $result->fetch_assoc();

if (empty($session)) {
setcookie("token", "", time() - 3600, "/", "", false, true);
header("Location: /account.php?a=l");
exit;
}

if ($session["ip_address"] == hash("sha256", $_SERVER["REMOTE_ADDR"])) {
if ($result->num_rows > 0) {
//print_r($session);
$sql = "SELECT * FROM users WHERE user_id = ? LIMIT 1";
$stmt = $conn->prepare($sql);
$stmt->bind_param("i", $session["user_id"]);
$stmt->execute();
$result = $stmt->get_result();
$user = $result->fetch_assoc();

if ($user["is_banned"] == 1) {
$sql = "DELETE FROM sessions WHERE session_id = ?";
$stmt = $conn->prepare($sql);
$stmt->bind_param("s", $token);
$stmt->execute();

setcookie("token", "", time() - 3600, "/", "", false, true);
header("Location: /extra.php?a=b");
exit;
}

$logged = true;
$levelId = $user["user_level"];
}
}
}
}

$tmpSql = "SELECT * FROM user_levels WHERE level_id = ? LIMIT 1";
$tmpStmt = $conn->prepare($tmpSql);
$tmpStmt->bind_param("i", $levelId);
$tmpStmt->execute();
$userLevel = $tmpStmt->get_result()->fetch_assoc();
$permissions = explode(",", $userLevel["permissions"]);
foreach ($permissions as $key => $p) {
$permissions[$key] = trim($p);
}

$showOriginal = false;
if (isset($_COOKIE["showOriginal"]) && !empty($_COOKIE["showOriginal"])) {
$showOriginal = true;
}
$hideOriginalMessage = false;
if (isset($_COOKIE["hideOriginalMessage"]) && !empty($_COOKIE["hideOriginalMessage"])) {
$hideOriginalMessage = true;
}

$smarty->assign("showOriginal", $showOriginal);
$smarty->assign("hideOriginalMessage", $hideOriginalMessage);
$smarty->assign("logged", $logged);
$smarty->assign("user", $user);
$smarty->assign("levelId", $levelId);
$smarty->assign("userLevel", $userLevel);
$smarty->assign("permissions", $permissions);
46 changes: 46 additions & 0 deletions __init/smarty.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

if (!defined('WORLD')) {
die("The World!");
}

require __DIR__ . "/../software/smarty/libs/Smarty.class.php";

use Smarty\Smarty;

$smarty = new Smarty();

$tmpDirs = [
__DIR__ . "/.smarty/config",
__DIR__ . "/.smarty/compile",
__DIR__ . "/.smarty/cache"
];

$error = false;
foreach ($tmpDirs as $dir) {
if (!file_exists($dir)) {
try {
mkdir($dir, 0755, true);
} catch (Exception $e) {
$error = true;
echo "<span style='color:red'>Error: Failed to create directory: $dir</span><br>";
}
}
}

if (!file_exists(__DIR__ . "/../templates/{$config["theme"]}")) {
$error = true;
echo "<span style='color:red'>Error: Theme not found</span><br>";
}

if ($error) {
exit;
}
$error = false;

$smarty->setTemplateDir(__DIR__ . "/../templates/{$config["theme"]}");
$smarty->setConfigDir(__DIR__ . "/.smarty/config");
$smarty->setCompileDir(__DIR__ . "/.smarty/compile");
$smarty->setCacheDir(__DIR__ . "/.smarty/cache");

unset($tmpDirs, $error, $dir);
Loading

0 comments on commit 52b6e15

Please sign in to comment.