Initial Commit
This commit is contained in:
commit
1d85bf6663
7 changed files with 377 additions and 0 deletions
129
README.md
Normal file
129
README.md
Normal file
|
|
@ -0,0 +1,129 @@
|
||||||
|
|
||||||
|
# 🧠 MentalNet Funnies
|
||||||
|
|
||||||
|
**A lightweight PHP + SQLite web app for hosting MentalNet Original comic strips.**
|
||||||
|
Built for simplicity, security, and self-hosting — no external dependencies, just pure PHP, HTML, and CSS.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚀 Overview
|
||||||
|
|
||||||
|
**MentalNet Funnies** is a micro-comic CMS that serves as the home for *Debian Osaka*, *Tux*, *Miku*, and other MentalNet.xyz comics.
|
||||||
|
It’s designed for local hosting on Apache + PHP setups and includes a tiny password-protected admin panel for uploads.
|
||||||
|
|
||||||
|
### ✨ Features
|
||||||
|
|
||||||
|
* 🖼 Upload, title, and describe new comics via a web form
|
||||||
|
* 💾 SQLite database — no external DB needed
|
||||||
|
* 🔐 Password-protected admin area
|
||||||
|
* 📱 Mobile-friendly front page (`index.php`)
|
||||||
|
* 🪶 Compact iframe version (`funnies-frame.php`) for embedding
|
||||||
|
* ⚙️ One-click database initializer (`init_db.php`)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📁 Directory Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
/var/www/html/funnies/
|
||||||
|
├── index.php # Main public comic viewer
|
||||||
|
├── funnies-frame.php # Small-width iframe-friendly viewer
|
||||||
|
├── uploads/ # Comic image storage
|
||||||
|
├── mentalnet_funnies.db # SQLite database file
|
||||||
|
├── admin/
|
||||||
|
│ ├── auth.php # Login handler
|
||||||
|
│ ├── config.php # Config & DB setup
|
||||||
|
│ ├── upload.php # Upload interface
|
||||||
|
│ ├── init_db.php # Manual DB table initializer
|
||||||
|
└── README.md # This file
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⚙️ Installation
|
||||||
|
|
||||||
|
1. **Create directory & set permissions**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo mkdir -p /var/www/html/funnies/uploads
|
||||||
|
sudo chown -R www-data:www-data /var/www/html/funnies
|
||||||
|
sudo chmod -R 755 /var/www/html/funnies
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Set up the admin password**
|
||||||
|
Generate a bcrypt hash:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
php -r 'echo password_hash("YourStrongPassword", PASSWORD_DEFAULT), PHP_EOL;'
|
||||||
|
```
|
||||||
|
|
||||||
|
Then place that hash inside `admin/config.php` under:
|
||||||
|
|
||||||
|
```php
|
||||||
|
$ADMIN_PASS_HASH = '$2y$10$replace_with_real_hash';
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Initialize the database**
|
||||||
|
Visit:
|
||||||
|
`https://yourdomain.com/funnies/admin/init_db.php`
|
||||||
|
Or run the init script via command-line:
|
||||||
|
`php init_db.php`
|
||||||
|
It will create the `comics` table or confirm if it already exists.
|
||||||
|
|
||||||
|
4. **Upload a comic**
|
||||||
|
Visit:
|
||||||
|
`https://yourdomain.com/funnies/admin/auth.php`
|
||||||
|
Log in and use the form to upload images and descriptions.
|
||||||
|
|
||||||
|
5. **View your comics**
|
||||||
|
|
||||||
|
* Main gallery: `https://yourdomain.com/funnies/`
|
||||||
|
* Iframe feed: `https://yourdomain.com/funnies/funnies-frame.php`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🪄 Embedding the Funnies Frame
|
||||||
|
|
||||||
|
The iframe viewer (`funnies-frame.php`) is optimized for small layouts (≈ 325 px).
|
||||||
|
Example embed:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<iframe src="https://mentalnet.xyz/funnies/funnies-frame.php"
|
||||||
|
width="325"
|
||||||
|
height="500"
|
||||||
|
frameborder="0"
|
||||||
|
scrolling="yes"
|
||||||
|
style="border-radius:8px;overflow:hidden;">
|
||||||
|
</iframe>
|
||||||
|
```
|
||||||
|
|
||||||
|
> 💡 You can adjust image width inside `funnies-frame.php` (default: 250 px for compact display).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🛡 Security Notes
|
||||||
|
|
||||||
|
* Only the admin section (`/admin/`) requires authentication.
|
||||||
|
* Use strong passwords and HTTPS.
|
||||||
|
* The upload form restricts to images only.
|
||||||
|
* SQLite DB and uploads folder should be owned by `www-data` with 755 perms.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🧩 Customization Ideas
|
||||||
|
|
||||||
|
* Add a “View All Comics →” link inside the iframe version.
|
||||||
|
* Include navigation buttons (Next / Previous comic).
|
||||||
|
* Implement tags or short titles for categorization.
|
||||||
|
* Add a JSON API endpoint for future integration with other MentalNet services.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🧰 License
|
||||||
|
|
||||||
|
MIT License — free to modify and self-host.
|
||||||
|
Created by **MarkMental** as part of the **mentalnet.xyz** web ecosystem.
|
||||||
|
|
||||||
|
> “In the MentalNet, Tux is root — and Miku too.” 🐧🎤
|
||||||
|
|
||||||
|
|
||||||
33
admin/auth.php
Normal file
33
admin/auth.php
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
<?php
|
||||||
|
session_start();
|
||||||
|
require_once __DIR__ . '/config.php';
|
||||||
|
|
||||||
|
if (isset($_POST['password'])) {
|
||||||
|
if (password_verify($_POST['password'], $ADMIN_PASS_HASH)) {
|
||||||
|
$_SESSION['auth'] = true;
|
||||||
|
header("Location: upload.php");
|
||||||
|
exit;
|
||||||
|
} else {
|
||||||
|
$error = "Invalid password.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($_SESSION['auth'])):
|
||||||
|
?>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head><title>Login - MentalNet Funnies Admin</title></head>
|
||||||
|
<body style="background:#111;color:#eee;font-family:monospace;text-align:center">
|
||||||
|
<h1>🔒 MentalNet Funnies Admin</h1>
|
||||||
|
<form method="post">
|
||||||
|
<input type="password" name="password" placeholder="Password" autofocus>
|
||||||
|
<button type="submit">Login</button>
|
||||||
|
</form>
|
||||||
|
<?php if (!empty($error)) echo "<p style='color:red;'>$error</p>"; ?>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
<?php
|
||||||
|
exit;
|
||||||
|
endif;
|
||||||
|
?>
|
||||||
|
|
||||||
22
admin/config.php
Normal file
22
admin/config.php
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
<?php
|
||||||
|
// --- basic config ---
|
||||||
|
$db_file = __DIR__ . '/../mentalnet_funnies.db';
|
||||||
|
|
||||||
|
// password hash (generate with: php -r "echo password_hash('yourpassword', PASSWORD_DEFAULT);")
|
||||||
|
$ADMIN_PASS_HASH = 'pwhashgoeshere';
|
||||||
|
|
||||||
|
// create db if not exists
|
||||||
|
if (!file_exists($db_file)) {
|
||||||
|
$db = new SQLite3($db_file);
|
||||||
|
$db->exec("CREATE TABLE comics (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
title TEXT NOT NULL,
|
||||||
|
filename TEXT NOT NULL,
|
||||||
|
description TEXT,
|
||||||
|
date_added DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||||
|
)");
|
||||||
|
} else {
|
||||||
|
$db = new SQLite3($db_file);
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
|
||||||
20
admin/init_db.php
Normal file
20
admin/init_db.php
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
<?php
|
||||||
|
$db = new SQLite3(__DIR__ . '/../mentalnet_funnies.db');
|
||||||
|
|
||||||
|
// Check if the table already exists
|
||||||
|
$result = $db->querySingle("SELECT name FROM sqlite_master WHERE type='table' AND name='comics'");
|
||||||
|
|
||||||
|
if ($result) {
|
||||||
|
echo "ℹ️ Table 'comics' already exists.";
|
||||||
|
} else {
|
||||||
|
$db->exec("CREATE TABLE comics (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
title TEXT NOT NULL,
|
||||||
|
filename TEXT NOT NULL,
|
||||||
|
description TEXT,
|
||||||
|
date_added DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||||
|
)");
|
||||||
|
echo "✅ Table 'comics' created.";
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
|
||||||
40
admin/upload.php
Normal file
40
admin/upload.php
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
<?php
|
||||||
|
require_once __DIR__ . '/auth.php'; // ensures login
|
||||||
|
require_once __DIR__ . '/config.php';
|
||||||
|
|
||||||
|
$msg = '';
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['comic'])) {
|
||||||
|
$title = trim($_POST['title']);
|
||||||
|
$desc = trim($_POST['description']);
|
||||||
|
$file = $_FILES['comic'];
|
||||||
|
|
||||||
|
if ($file['error'] === UPLOAD_ERR_OK && $title) {
|
||||||
|
$ext = pathinfo($file['name'], PATHINFO_EXTENSION);
|
||||||
|
$fname = uniqid('comic_') . '.' . $ext;
|
||||||
|
move_uploaded_file($file['tmp_name'], __DIR__ . '/../uploads/' . $fname);
|
||||||
|
|
||||||
|
$stmt = $db->prepare("INSERT INTO comics (title, filename, description) VALUES (:t,:f,:d)");
|
||||||
|
$stmt->bindValue(':t',$title,SQLITE3_TEXT);
|
||||||
|
$stmt->bindValue(':f',$fname,SQLITE3_TEXT);
|
||||||
|
$stmt->bindValue(':d',$desc,SQLITE3_TEXT);
|
||||||
|
$stmt->execute();
|
||||||
|
$msg = "✅ Uploaded '$title'";
|
||||||
|
} else $msg = "Upload failed.";
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head><title>Upload Comic - MentalNet Funnies</title></head>
|
||||||
|
<body style="background:#111;color:#eee;font-family:monospace;text-align:center">
|
||||||
|
<h1>🧠 Upload Comic</h1>
|
||||||
|
<p><?=htmlspecialchars($msg)?></p>
|
||||||
|
<form method="post" enctype="multipart/form-data">
|
||||||
|
<p><input type="text" name="title" placeholder="Title" required></p>
|
||||||
|
<p><textarea name="description" placeholder="Description"></textarea></p>
|
||||||
|
<p><input type="file" name="comic" accept="image/*" required></p>
|
||||||
|
<p><button type="submit">Upload</button></p>
|
||||||
|
</form>
|
||||||
|
<p><a href="../index.php" style="color:#0ff;">← View Site</a></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
72
funnies-frame.php
Normal file
72
funnies-frame.php
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
<?php
|
||||||
|
$db = new SQLite3(__DIR__ . '/mentalnet_funnies.db');
|
||||||
|
$res = $db->query('SELECT * FROM comics ORDER BY date_added DESC LIMIT 3'); // show latest 3 for compactness
|
||||||
|
?>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>MentalNet Funnies Frame</title>
|
||||||
|
<style>
|
||||||
|
html, body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
background: #111;
|
||||||
|
color: #eee;
|
||||||
|
font-family: monospace;
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
display: none; /* hide header for iframe context */
|
||||||
|
}
|
||||||
|
.comic {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
padding: 0.25rem 0.5rem;
|
||||||
|
}
|
||||||
|
h2 {
|
||||||
|
font-size: 0.9rem;
|
||||||
|
margin: 0.4rem 0;
|
||||||
|
color: #0ff;
|
||||||
|
text-align: center;
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
|
img {
|
||||||
|
width: 250px;
|
||||||
|
border-radius: 4px;
|
||||||
|
display: block;
|
||||||
|
margin: 0 auto;
|
||||||
|
box-shadow: 0 0 6px #000;
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
margin: 0.25rem auto;
|
||||||
|
text-align: center;
|
||||||
|
color: #bbb;
|
||||||
|
width: 95%;
|
||||||
|
line-height: 1.3;
|
||||||
|
}
|
||||||
|
small {
|
||||||
|
color: #666;
|
||||||
|
font-size: 0.7rem;
|
||||||
|
}
|
||||||
|
@media (max-width: 360px) {
|
||||||
|
img { width: 98%; }
|
||||||
|
h2 { font-size: 0.85rem; }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<?php while($row=$res->fetchArray()): ?>
|
||||||
|
<div class="comic">
|
||||||
|
<h2><?= htmlspecialchars($row['title']) ?></h2>
|
||||||
|
<img src="uploads/<?= htmlspecialchars($row['filename']) ?>" alt="<?= htmlspecialchars($row['title']) ?>">
|
||||||
|
<?php if($row['description']): ?>
|
||||||
|
<p><?= nl2br(htmlspecialchars($row['description'])) ?></p>
|
||||||
|
<?php endif; ?>
|
||||||
|
<p><small><?= htmlspecialchars(date('M j, Y', strtotime($row['date_added']))) ?></small></p>
|
||||||
|
</div>
|
||||||
|
<?php endwhile; ?>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
61
index.php
Normal file
61
index.php
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
<?php
|
||||||
|
$db = new SQLite3(__DIR__ . '/mentalnet_funnies.db');
|
||||||
|
$res = $db->query('SELECT * FROM comics ORDER BY date_added DESC');
|
||||||
|
?>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>MentalNet Funnies</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
background:#111;
|
||||||
|
color:#eee;
|
||||||
|
font-family: monospace;
|
||||||
|
text-align: center;
|
||||||
|
margin:0;
|
||||||
|
padding:0;
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
margin: 1rem 0;
|
||||||
|
font-size: 1.6rem;
|
||||||
|
}
|
||||||
|
h2 {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
margin: 0.5rem 0;
|
||||||
|
}
|
||||||
|
img {
|
||||||
|
width: 95%;
|
||||||
|
max-width: 640px;
|
||||||
|
border-radius: 8px;
|
||||||
|
margin: 0.75rem auto;
|
||||||
|
box-shadow: 0 0 10px #222;
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
margin: 0.5rem auto;
|
||||||
|
width: 90%;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
small {
|
||||||
|
color: #888;
|
||||||
|
}
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
h1 { font-size: 1.3rem; }
|
||||||
|
img { width: 98%; border-radius: 6px; }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>🧠 MentalNet Funnies</h1>
|
||||||
|
<?php while($row=$res->fetchArray()): ?>
|
||||||
|
<div>
|
||||||
|
<h2><?= htmlspecialchars($row['title']) ?></h2>
|
||||||
|
<img src="uploads/<?= htmlspecialchars($row['filename']) ?>" alt="<?= htmlspecialchars($row['title']) ?>">
|
||||||
|
<p><?= nl2br(htmlspecialchars($row['description'])) ?></p>
|
||||||
|
<p><small><?= htmlspecialchars($row['date_added']) ?></small></p>
|
||||||
|
</div>
|
||||||
|
<?php endwhile; ?>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue