Archived
1
0
Disbranĉigi 0

Only god knows what I've done.

This commit is contained in:
Jenga Phoenix 2019-02-15 08:32:58 -06:00
parent d230e857f4
commit 4060b1c913
19 changed files with 468 additions and 130 deletions

View File

@ -12,17 +12,8 @@ $depth = "";
$title = "About"; $title = "About";
include "res/lib/load.php"; include "res/lib/load.php";
// ------------------------------------
echo $GLOBALS['twig']->render('head.twig.html', display_page("about.twig.html", $depth, $title);
['theme' => $GLOBALS['theme'],
'depth' => $depth,
'title' =>$title]);
echo $GLOBALS['twig']->render('index.twig.html',
['animal'=> "cat"]);
echo $GLOBALS['twig']->render('foot.twig.html',
['theme' => $GLOBALS['theme'],
'depth' => $depth]);
?> ?>

View File

@ -12,18 +12,8 @@ $title = "Control Panel";
$depth = "../"; $depth = "../";
include "../res/lib/load.php"; include "../res/lib/load.php";
echo $GLOBALS['twig']->render('head.twig.html', // --------------------------------------
['theme' => $GLOBALS['theme'],
'depth' => $depth,
'title' =>$title]);
echo $GLOBALS['twig']->render('admin_index.twig.html', []);
echo $GLOBALS['twig']->render('foot.twig.html',
['theme' => $GLOBALS['theme'],
'depth' => $depth]);
display_page("admin_index.twig.html", $depth, $title);
?> ?>

View File

@ -11,7 +11,11 @@
$depth = "../../"; $depth = "../../";
include "../../res/lib/load.php"; include "../../res/lib/load.php";
$id = $_POST['id']; $auth_user = $_POST['auth_user'];
$auth_pass = $_POST['auth_pass'];
$auth_user_id = user_name_to_id($auth_user);
$id = intval($_POST['id']);
$name = $_POST['name']; $name = $_POST['name'];
$full_name = $_POST['full_name']; $full_name = $_POST['full_name'];
$bio = $_POST['bio']; $bio = $_POST['bio'];
@ -19,26 +23,31 @@ $email = $_POST['email'];
$url = $_POST['url']; $url = $_POST['url'];
$password = $_POST['password']; $password = $_POST['password'];
$login = $_POST['login']; $login = $_POST['login'];
$password = password_hash($password, PASSWORD_BCRYPT, array('cost' => 11));
// -------------------------------------
auth_enforce($auth_user_id, $auth_pass,
array("wizard", "archmage"), "make accounts");
$invalid = input_enforce(array($id, $name, $full_name, $bio, $email, $url, $invalid = input_enforce(array($id, $name, $full_name, $bio, $email, $url,
$password, $login), $password, $login),
array("ID", "username", "full name", "biography", "email", array("ID", "Username", "Full name", "Biography", "E-mail",
"url", "password", "login"), "URL", "Password", "Login class"),
array("int", "string", "string", "string", "email", array("free_user_id", "free_user_name", "string", "string",
"url", "password", "email", "url", "ne_string",
array("contributor", "spectator", "wizard", array("spectator", "wizard", "archmage",
"admin"))); "contributor")));
if (!is_bool($invalid)) { if (!empty($invalid)) {
input_error("Some input is invalid: " . $invalid); input_error("Some input is invalid: " . comma_sep($invalid));
} }
$result = user_create($id, $name, $password, $login, // -------------------------------------
$full_name, $email, $url, $bio);
if ($result) { user_create($id, $name, $password, $login,
header('Location: http://localhost/blagoblag/user.php?id=' . $id); $full_name, $email, $url, $bio);
} else {
general_error("<em>Something</em> went wrong."); root_redirect("user.php?name=" . $name);
}
?> ?>

View File

@ -0,0 +1,37 @@
<?php
/* This file is free software: you can redistribute it and/or modify
it under the terms of version 3 of the GNU Affero General Public
License as published by the Free Software Foundation.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details. */
$depth = "../../";
include "../../res/lib/load.php";
$auth_user = $_POST['auth_user'];
$auth_pass = $_POST['auth_pass'];
$auth_user_id = user_name_to_id($auth_user);
$id = intval($_POST['id']);
// -------------------------------------
auth_enforce($auth_user_id, $auth_pass,
array("wizard", "archmage"), "destroy users");
$invalid = input_enforce(array($id), array("ID"), array("user_id"));
if (!empty($invalid)) {
input_error("Some input is invalid: " . comma_sep($invalid));
}
// -------------------------------------
user_delete($id);
root_redirect("user.php?name=" . $name);
?>

View File

@ -12,22 +12,8 @@ $depth = "";
$title = ""; $title = "";
include "res/lib/load.php"; include "res/lib/load.php";
// global variable declaration // -------------------------------------
$users = user_ids();
$user = array_map(user_data, $users);
$posts = post_ids();
$post = array_map(post_data, $posts);
echo $GLOBALS['twig']->render('head.twig.html', display_page("index.twig.html", $depth, $title);
['theme' => $GLOBALS['theme'],
'depth' => $depth,
'title' =>$title]);
echo $GLOBALS['twig']->render('index.twig.html', []);
echo $GLOBALS['twig']->render('foot.twig.html',
['theme' => $GLOBALS['theme'],
'depth' => $depth]);
?> ?>

View File

@ -13,27 +13,17 @@ $title = "";
include "res/lib/load.php"; include "res/lib/load.php";
// ------------------------------------- // -------------------------------------
// post environment
$post_id = $_GET['id']; $id = $_GET['id'];
$text = post_text($post_id); $text = post_text($id);
$author = post_author($post_id); $author = post_author($id);
$date = post_data($post_id); $date = post_data($id);
$local_exports = array('id' => $id, 'text' => $text, 'author' => $author,
'data' => $data);
// ------------------------------------- // -------------------------------------
echo $GLOBALS['twig']->render('head.twig.html', display_page("post.twig.html", $depth, $title, $local_exports);
['theme' => $GLOBALS['theme'],
'depth' => $depth,
'title' =>$title]);
echo $GLOBALS['twig']->render('post.twig.html',
['id'=> $post_id,
'text' => $text,
'author' => $author,
'date' => $date]);
echo $GLOBALS['twig']->render('foot.twig.html',
['theme' => $GLOBALS['theme'],
'depth' => $depth]);
?> ?>

View File

@ -11,20 +11,35 @@
// ARRAY -- > STRING // ARRAY -- > STRING
// Turn a 1D array into a comma-seperated string // Turn a 1D array into a comma-seperated string
function comma_sep($array) { function comma_sep($array, $seperator=", ") {
global $string;
$string = $seperator;
global $stack; global $stack;
$stack = ""; $stack = "";
$comma_print = function($item) { $comma_print = function($item) {
$GLOBALS['stack'] = $GLOBALS['stack'] $GLOBALS['stack'] = $GLOBALS['stack']
. ", " . $item; . $GLOBALS['string'] . $item;
}; };
array_map($comma_print, $array); array_map($comma_print, $array);
$stack = preg_replace('/^, /', '', $stack); $stack = preg_replace('/^' . $string . '/', '', $stack);
return $stack; return $stack;
} }
// STRING STRING [ARRAY] --> ARRAY
// Return exports for Twig-- with the required global & local exports,
// along with any optional local ones.
function make_exports($depth, $title, $local = array()) {
$exports = $GLOBALS['twig_exports'];
$exports['depth'] = $depth;
$exports['title'] = $title;
return array_merge($exports, $local);
}
?> ?>

23
res/lib/blagoblag.php Normal file
View File

@ -0,0 +1,23 @@
<?php
/* This file is free software: you can redistribute it and/or modify
it under the terms of version 3 of the GNU Affero General Public
License as published by the Free Software Foundation.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details. */
// STRING STRING STRING [ARRAY] --> BOOLEAN
// Render and display a page, based on it's template-path, title, relative
// depth, and an optional array of more Twig variable exports.
function display_page($template, $depth, $title, $local_exports=array()) {
echo $GLOBALS['twig']->render("head.twig.html",
make_exports($depth, $title, $local_exports));
echo $GLOBALS['twig']->render($template,
make_exports($depth, $title, $local_exports));
echo $GLOBALS['twig']->render("foot.twig.html",
make_exports($depth, $title, $local_exports));
return true;
}

View File

@ -30,8 +30,8 @@ if (!db_table_existant("lusers")) {
db_create_table("lusers", db_create_table("lusers",
array("id int primary key","username varchar(20)", array("id int primary key","username varchar(20)",
"biography longtext","email varchar(50)","website varchar(50)", "biography longtext","email varchar(50)","website varchar(50)",
"password_hash varchar(80)","full_name varchar(50)", "hash char(60)","full_name varchar(50)",
"login varchar(20)")); } "class varchar(20)")); }
if (!db_table_existant("posts")) { if (!db_table_existant("posts")) {
db_create_table("posts", db_create_table("posts",
@ -51,10 +51,12 @@ if (!db_table_existant("comments")) {
// Execute a DB command // Execute a DB command
function db_cmd($query) { function db_cmd($query) {
$stmt = $GLOBALS['pdo']->query($query); $stmt = $GLOBALS['pdo']->query($query);
$stack = array();
if (is_bool($stmt)) { if (is_bool($stmt)) {
return $stmt; return $stmt;
} else { } else {
return $stmt->fetch(); return $stmt->fetchAll();
} }
} }
@ -63,7 +65,17 @@ function db_cmd($query) {
// STRING STRING --> ARRAY // STRING STRING --> ARRAY
// Return all values of a specific column // Return all values of a specific column
function db_get_columns($table, $column) { function db_get_columns($table, $column) {
return db_cmd("select " . $column . " from " . $table); $result = db_cmd("select " . $column . " from " . $table);
$result_nest = function($array) {
return $array[0];
};
if (is_array($result)) {
return array_map($result_nest, $result);
} else {
return $result;
}
} }
// STRING STRING VARYING --> ARRAY // STRING STRING VARYING --> ARRAY
@ -77,7 +89,7 @@ function db_get_rows($table, $identifier, $value) {
// Return the value of a specific column in a given row, identified by an // Return the value of a specific column in a given row, identified by an
// 'identifier' column set to the given value // 'identifier' column set to the given value
function db_get_cell($table, $identifier, $value, $cell) { function db_get_cell($table, $identifier, $value, $cell) {
return db_get_rows($table, $identifier, $value)[$cell]; return db_get_rows($table, $identifier, $value)[0][$cell];
} }
// -------------------------------------- // --------------------------------------

View File

@ -25,4 +25,12 @@ function input_error($string) {
exit; exit;
} }
// STRING --> NIL
// Print out a general error, with $string as it's error-message.
function perm_error($string) {
echo $GLOBALS['twig']->render('error.twig.html',
['error_message'=>$string]);
exit;
}
?> ?>

View File

@ -15,6 +15,7 @@ function root($path) {
return $GLOBALS['depth'] . $path; return $GLOBALS['depth'] . $path;
} }
// ------------------------------------- // -------------------------------------
include(root("config.php")); include(root("config.php"));
@ -23,12 +24,42 @@ require_once root("vendor/autoload.php");
include(root("res/lib/string.php")); include(root("res/lib/string.php"));
include(root("res/lib/array.php")); include(root("res/lib/array.php"));
include(root("res/lib/user.php")); include(root("res/lib/user.php"));
include(root("res/lib/post.php")); include(root("res/lib/error.php"));
include(root("res/lib/comment.php")); include(root("res/lib/sterilize.php"));
include(root("res/lib/db.php")); include(root("res/lib/db.php"));
include(root("res/lib/url.php"));
include(root("res/lib/blagoblag.php"));
$loader= new Twig_Loader_Filesystem(root("res/themes/default/html")); $loader= new Twig_Loader_Filesystem(root("res/themes/default/html"));
$twig = new Twig_Environment($loader, ['cache' => $twig = new Twig_Environment($loader, ['cache' =>
root('cache/')]); root('cache/')]);
// -------------------------------------
// global variable declaration
global $users; $users = user_ids();
global $user; $user = array();
$push_user_data = function($user_id) {
$user_name = user_name($user_id);
$GLOBALS['user'][$user_id] = user_data($user_id);
$GLOBALS['user'][$user_name] = user_data($user_id);
};
array_map($push_user_data, $users);
// global $posts; $posts = post_ids();
// global $post; $post = array();
// $post = array_map(post_data, $posts);
// -----------------
global $twig_exports;
$twig_exports = array('theme' => $GLOBALS['theme'],
'users' => $GLOBALS['users'],
'user' => $GLOBALS['user']);
//'posts' => $GLOBALS['posts'],
//'post' => $GLOBALS['post']);
?> ?>

View File

@ -9,8 +9,136 @@
GNU Affero General Public License for more details. */ GNU Affero General Public License for more details. */
function input_enforce($values, $names, $types) { // NUMBER STRING ARRAY [STRING] --> NIL
$stack = ""; // Make sure a user is both authenticated *and* permitted to do a given task,
// aka in the right login-class.
function auth_enforce($id, $password, $permitted, $message="do that") {
if (!user_valid_password($id, $password)) {
input_error("Sorry, your user-name or password is wrong.");
}
while ($i < length($valuesw)) { $class = user_class($id);
if (function if (!in_array($class, $permitted)) {
perm_error("Mate, only a " . comma_sep($permitted, " or ")
. " can " . $message . "-- you hecking "
. $class . "!");
}
}
// ARRAY ARRAY ARRAY --> ARRAY
// Validate a list of values against a corresponding list of types;
// return a list of names (corresponding to the values) that don't
// match their types. If an empty array is returned, then, all inputs are
// valid.
// Two non-existant "pseudo-types" are accepted-- "url" and "e-mail".
// A "type" can also be an array of acceptable values.
// Example:
// input_enforce(["apple", 4, "ap@ap.co.uk", "never"],
// ["Fruit", "Age", "E-mail", "Preference"],
// ["string", "int", "email",
// ["never", "always", "now"]]);
//
// ... it's an ugly, long function, I know...
function input_enforce($values, $names, $types) {
$stack = array();
$i = 0;
while ($i < count($values)) {
$value = $values[$i];
$type = $types[$i];
$name = $names[$i];
$res = true;
switch ($type) {
case (is_array($type)):
if (!in_array($value, $type)) { $res = false; }
break;
default:
$type_check = "is_" . $type;
if (!call_user_func($type_check, $value)) {
$res = false;
}
break;
}
if (!$res) {
$stack[] = $name;
}
$i++;
}
return $stack;
}
// -------------------------------------
// pseudo-types
// STRING --> BOOLEAN
// Return whether or not a given string is a valid e-mail.
function is_email($string) {
return filter_var($string, FILTER_VALIDATE_EMAIL);
}
// STRING --> BOOLEAN
// Return whether or not a given string is a valid url.
function is_url($string) {
return filter_var($string, FILTER_VALIDATE_URL);
}
// VARYING --> BOOLEAN
// Return whether or not a given value is a non-empty string
function is_ne_string($value) {
if (is_string($value) && !empty($value)) {
return true;
} else {
return false;
}
}
// -------------------------------------
// STRING --> BOOLEAN
// Return whether or not a string is already a username
function is_user_name($username) {
if (user_name_to_id($username)) {
return true;
} else {
return false;
}
}
// NUMBER --> BOOLEAN
// Return whether or not a number is already a user ID
function is_user_id($id) {
if (in_array($id, $GLOBALS['users'])) {
return true;
} else {
return false;
}
}
// -------------------------------------
// STRING --> BOOLEAN
// Return whether or not a given string is a valid (unused) username
function is_free_user_name($username) {
if (!is_user_name($username) && is_ne_string($username)) {
return true; } else { return false; }
}
// STRING --> BOOLEAN
// Return whether or not a given number is a valid (unused) user ID
function is_free_user_id($id) {
if (!is_user_id($id) && is_int($id)) {
return true; } else { return false; }
}
// -------------------------------------
?>

40
res/lib/url.php Normal file
View File

@ -0,0 +1,40 @@
<?php
/* This file is free software: you can redistribute it and/or modify
it under the terms of version 3 of the GNU Affero General Public
License as published by the Free Software Foundation.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details. */
// STRING -- > STRING
// Turn a path (relative to root) into absolute URL
function root_url($string) {
return protocol() . "://" . $_SERVER['HTTP_HOST'] . "/"
. $GLOBALS['root']
. $string;
}
// NIL --> STRING
// Return the current protocol (HTTP, HTTPS, etc)
function protocol() {
return explode('/', $_SERVER['SERVER_PROTOCOL'])[0];
}
// STRING --> NIL
// Redirect to a regular URL (I.E., "https://duckduckgo.com")
function redirect($url) {
header('Location: ' . $url);
return;
}
// STRING --> NIL
// Redirect to a URL relative to root (I.E., "res/img/")
function root_redirect($path) {
header('Location: ' . root_url($path));
return;
}

View File

@ -28,16 +28,22 @@ function user_set($id, $variable, $new_value) {
// NUMBER STRING STRING [STRING STRING STRING STRING STRING] --> BOOLEAN // NUMBER STRING STRING [STRING STRING STRING STRING STRING] --> BOOLEAN
// Create a user of the given specification. // Create a user of the given specification.
function user_create($id, $name, $password, $login="Spectator", function user_create($id, $name, $password, $class="Spectator",
$full_name=NULL, $email=NULL, $url=NULL, $bio=NULL) { $full_name=NULL, $email=NULL, $url=NULL, $bio=NULL) {
return db_insert_row("lusers", return db_insert_row("lusers",
array("id", "username", "password_hash", "login", array("id", "username", "hash", "class",
"full_name", "email", "website", "biography"), "full_name", "email", "website", "biography"),
array($id, $name, $password, $login, array($id, $name, $password, $class,
$full_name, $email, $url, $bio)); $full_name, $email, $url, $bio));
} }
// NUMBER --> BOOLEAN
// Delete a user by their ID.
function user_delete($id) {
return db_cmd("delete from lusers where id = " . $id);
}
// ------------------------------------- // -------------------------------------
@ -51,7 +57,7 @@ function user_id_to_name($id) {
// STRING --> NUMBER // STRING --> NUMBER
// Get a user's ID from username. // Get a user's ID from username.
function user_name_to_id($username) { function user_name_to_id($username) {
return db_get_cell("lusers", "username", $username, "id"); return db_get_cell("lusers", "username", string_wrap($username), "id");
} }
@ -61,13 +67,13 @@ function user_name_to_id($username) {
// NUMBER --> STRING // NUMBER --> STRING
// Return a username from a user-ID // Return a username from a user-ID
function user_name($id) { function user_name($id) {
return user_id_to_name($id, "username"); return user_id_to_name($id);
} }
// NUMBER --> STRING // NUMBER --> STRING
// Return a user's login-class from ID // Return a user's login-class from ID
function user_login($id) { function user_class($id) {
return user_get($id, "login"); return user_get($id, "class");
} }
// NUMBER --> STRING // NUMBER --> STRING
@ -96,10 +102,46 @@ function user_biography($id) {
// ------------------------------------- // -------------------------------------
// NUMBER --> ARRAY
// Fetch an array of a user's IDs
function user_ids() {
return db_get_columns("lusers", "id");
}
// -------------------------------------
// NUMBER --> ARRAY // NUMBER --> ARRAY
// Fetch an array of a user's posts (by ID) // Fetch an array of a user's posts (by ID)
function user_posts($user_id) { function user_posts($id) {
return db_get_cell("posts", "user", $user_id, "id"); return db_get_cell("posts", "user", $id, "id");
}
// -------------------------------------
// NUMBER --> ARRAY
// Return an array filled with all of a user's relevant data.
function user_data($id) {
return array('full_name' => user_full_name($id),
'name' => user_name($id),
'bio' => user_biography($id),
'email' => user_email($id),
'website' => user_website($id),
'posts' => user_posts($id));
}
// -------------------------------------
// NUMBER STRING --> BOOLEAN
// Return whether or not a given password is valid.
function user_valid_password($id, $password) {
return password_verify($password, user_get($id, "hash"));
} }
?> ?>

View File

@ -1,5 +1,17 @@
<section id="creation"> <section id="creation">
<form id="user_creation" action="private/user_create.php" method="post"> <form id="user_creation" action="private/user_create.php" method="post">
<section id="authentication">
<p><label>Your Username</label>
<input name="auth_user" type="text" />
</p>
<p><label>Your Password</label>
<input name="auth_pass" type="text">
</p>
<hr />
<section id="user_details">
<p><label>User ID</label><input name="id" type="number" /></p> <p><label>User ID</label><input name="id" type="number" /></p>
<p><label>Full Name</label><input name="full_name" type="text"/> <p><label>Full Name</label><input name="full_name" type="text"/>
</p> </p>
@ -17,21 +29,46 @@
<hr /> <hr />
<p><label>Login Group</label> <p><label>Login Group</label>
<select name="login"> <select name="login">
<option value="contributor">Contributor</option> <option value="contributor">Contributor</option>
<option value="spectator">Spectator</option> <option value="spectator">Spectator</option>
<option value="admin">Admin</option>
<option value="wizard">Wizard</option> <option value="wizard">Wizard</option>
<option value="archmage">Archmage</option>
</select>
</p>
</section>
<p><input type="submit" /></p>
</form>
</section>
<hr />
<section id="destruction">
<form id="user_destruction" action="private/user_destroy.php"
method="post">
<section id="authentication">
<p><label>Your Username</label>
<input name="auth_user" type="text" />
</p>
<p><label>Your Password</label>
<input name="auth_pass" type="text">
</p>
</section>
<hr />
<p><label>Target</label>
<select name="id">
{% for id in users %}
<option value="{{ id }}">
{{ user[id]['full_name'] }}
</option>
{% endfor %}
</select> </select>
</p> </p>
<p><input type="submit" /></p> <p><input type="submit" /></p>
</form> </form>
</section> </section>
<section id="destruction">
<form action="private/user_delete.php" method="post">
</form>
<form action="private/post_delete.php" method="post">
</form>
</section>

View File

@ -1,3 +1,4 @@
<h1>Eek!</h1> <h1>Eek!</h1>
<h2>Something was hecked.</h2> <h2>Something was hecked.</h2>
<h3>{{ error_message }} Go back and try again.</h3> <h3>{{ error_message }}</h3>
<h3>Go back and try again.</h3>

View File

@ -1,10 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" type="text/css" href="../css/global.css">
<link rel="stylesheet" type="text/css" href="../css/navbar.css">
<title>Index</title>
</head>
<body>
</body>
</html

View File

@ -4,7 +4,4 @@
<h3>{{ url }}</h3> <h3>{{ url }}</h3>
<p>{{ bio }}</p> <p>{{ bio }}</p>
<ul> <ul>
{% for post in posts %}
<li>{{ post }}</li>
{% endfor %}
</ul> </ul>

View File

@ -8,21 +8,32 @@
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details. */ GNU Affero General Public License for more details. */
$depth = ""; $depth = "";
$title = "About";
include "res/lib/load.php"; include "res/lib/load.php";
// -------------------------------------
echo $GLOBALS['twig']->render('head.twig.html', $id = $_GET['id'] ?? user_name_to_id($_GET['name']);
['theme' => $GLOBALS['theme'], $name = user_name($id);
'depth' => $depth,
'title' =>$title]);
echo $GLOBALS['twig']->render('index.twig.html', // -------------------------------------
['animal'=> "cat"]);
echo $GLOBALS['twig']->render('foot.twig.html', if (!is_user_id($id)) {
['theme' => $GLOBALS['theme'], general_error("It looks like that isn't a real user.");
'depth' => $depth]); }
if (empty($name)) {
general_error("It looks like that isn't a real user...");
}
// ------------------------------------
$local_exports = array('full_name' => user_full_name($id), 'name' => $name,
'bio' => user_biography($id), 'email' =>
user_email($id), 'website' => user_website($id));
// -------------------------------------
display_page("user.twig.html", $depth, $title, $local_exports);
?> ?>