commit 457d8a0d4c30669f74fa707709a6c3f7e1422ec5
Author: goom <30990201+MarkMrGamer@users.noreply.github.com>
Date: Sat Nov 22 23:57:26 2025 -0800
Pushing all files from my usb
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..c172dc6
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+/vendor/
+config.inc.php
\ No newline at end of file
diff --git a/.htaccess b/.htaccess
new file mode 100644
index 0000000..b03b653
--- /dev/null
+++ b/.htaccess
@@ -0,0 +1,8 @@
+RewriteEngine On
+RewriteBase /
+RewriteRule ^images/(.*) /views/images/$1 [L]
+RewriteRule ^styles/(.*) /views/styles/$1 [L]
+RewriteRule ^scripts/(.*) /views/scripts/$1 [L]
+RewriteCond %{REQUEST_FILENAME} !-f
+RewriteCond %{REQUEST_FILENAME} !-d
+RewriteRule . index.php [L]
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..261eeb9
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..31172f7
--- /dev/null
+++ b/README.md
@@ -0,0 +1,12 @@
+# MallardNet
+MallardNet is a marcoblogging site created in 2025.
+
+
i made these instructions because it has composer, so it needs the steps in either not to have errors without the /vendor/ folder
1. have composer installed on your computer 2. put all of this stuff in your www folder 3. run composer update to establish /vendor/ folder (requires because it uses a router) 4. install. sql file in a new database 5. change config.sample.inc.php to config.inc.php and then change the database details to your. database and db account details. 6. done, . its running, can code yipee
diff --git a/composer.json b/composer.json
new file mode 100644
index 0000000..a2c1ad0
--- /dev/null
+++ b/composer.json
@@ -0,0 +1,5 @@
+{
+ "require": {
+ "bramus/router": "~1.6"
+ }
+}
diff --git a/composer.lock b/composer.lock
new file mode 100644
index 0000000..9bedf2f
--- /dev/null
+++ b/composer.lock
@@ -0,0 +1,70 @@
+{
+ "_readme": [
+ "This file locks the dependencies of your project to a known state",
+ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
+ "This file is @generated automatically"
+ ],
+ "content-hash": "1c8a1ef3d6be7e51a0a9b9c991ff9fc9",
+ "packages": [
+ {
+ "name": "bramus/router",
+ "version": "1.6.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/bramus/router.git",
+ "reference": "55657b76da8a0a509250fb55b9dd24e1aa237eba"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/bramus/router/zipball/55657b76da8a0a509250fb55b9dd24e1aa237eba",
+ "reference": "55657b76da8a0a509250fb55b9dd24e1aa237eba",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "require-dev": {
+ "friendsofphp/php-cs-fixer": "~2.14",
+ "phpunit/php-code-coverage": "~2.0",
+ "phpunit/phpunit": "~4.8"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-0": {
+ "Bramus": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Bram(us) Van Damme",
+ "email": "bramus@bram.us",
+ "homepage": "http://www.bram.us"
+ }
+ ],
+ "description": "A lightweight and simple object oriented PHP Router",
+ "homepage": "https://github.com/bramus/router",
+ "keywords": [
+ "router",
+ "routing"
+ ],
+ "support": {
+ "issues": "https://github.com/bramus/router/issues",
+ "source": "https://github.com/bramus/router/tree/1.6.1"
+ },
+ "time": "2021-11-18T19:24:07+00:00"
+ }
+ ],
+ "packages-dev": [],
+ "aliases": [],
+ "minimum-stability": "stable",
+ "stability-flags": [],
+ "prefer-stable": false,
+ "prefer-lowest": false,
+ "platform": [],
+ "platform-dev": [],
+ "plugin-api-version": "2.3.0"
+}
diff --git a/index.php b/index.php
new file mode 100644
index 0000000..45844e7
--- /dev/null
+++ b/index.php
@@ -0,0 +1,122 @@
+all('/', function() use ($views_dir, $website, $conn) {
+ if (!isset($_SESSION["user"])) {
+ require($views_dir . 'main.php');
+ } else {
+ require($views_dir . "/dupes/home/feed_micros.php");
+ }
+
+ return;
+ });
+
+ $router->get('/feed/(\w+)', function($feed_type) use ($views_dir, $website, $conn) {
+ if (!isset($_SESSION["user"]) || htmlspecialchars($feed_type) == NULL) {
+ header("Location: /");
+ } else {
+ switch(htmlspecialchars($feed_type)) {
+ case "micros":
+ require($views_dir . "/dupes/home/feed_micros.php");
+ break;
+ case "marcos":
+ require($views_dir . "/dupes/home/feed_marcos.php");
+ break;
+ case "gallery":
+ require($views_dir . "/dupes/home/feed_gallery.php");
+ break;
+ default:
+ header("Location: /");
+ }
+ }
+
+ return;
+ });
+
+
+ $router->get('/quack/(\w+)', function($post_id) use ($views_dir, $website, $conn) {
+ if (!$post_id) {
+ header("Location: /");
+ } else {
+ require($views_dir . "/post.php");
+ }
+ });
+
+ $router->get('/delete_quack/(\w+)', function($post_id) use ($conn) {
+ $hasTitle = false;
+
+ if (!isset($_SESSION["user"])) {
+ header("Location: /");
+ } else {
+ $post = new Post($_SESSION["user"], $conn);
+ if ($post->getSpecifcPost(htmlspecialchars($post_id)) != NULL) {
+ $post_details = $post->getSpecifcPost(htmlspecialchars($post_id)) ;
+
+ if ($post_details["author"] == $_SESSION["user"])
+ if ($post_details["title"] != NULL)
+ $hasTitle = true;
+
+ $post->deletePost($post_id);
+ }
+
+ if ($hasTitle) {
+ header("Location: /feed/marcos");
+ } else {
+ header("Location: /");
+ }
+ }
+ return;
+ });
+
+ $router->all('/settings', function() use ($views_dir, $website, $conn) {
+ require($views_dir . 'settings.php');
+ return;
+ });
+
+ $router->all('/apply', function() use ($views_dir, $website) {
+ require($views_dir . 'apply.php');
+ return;
+ });
+
+ $router->all('/temp_register', function() use ($views_dir, $website, $conn) {
+ require($views_dir . 'temp_reg.php');
+ return;
+ });
+
+ $router->all('/login', function() use ($views_dir, $website, $conn) {
+ require($views_dir . 'login.php');
+ return;
+ });
+
+ $router->all('/logout', function() use ($views_dir, $website, $conn) {
+ session_destroy();
+ header("Location: /");
+ return;
+ });
+
+ $router->set404(function() {
+ header('HTTP/1.1 404 Not Found');
+ echo "Waddled to nowhere";
+ return;
+ });
+
+ $router->run();
+?>
\ No newline at end of file
diff --git a/lib/classes/Account.php b/lib/classes/Account.php
new file mode 100644
index 0000000..3187c74
--- /dev/null
+++ b/lib/classes/Account.php
@@ -0,0 +1,35 @@
+current_user = $current_user;
+ $this->conn = $conn;
+ }
+
+ public function isLoggedIn() {
+ return isset($_SESSION["user"]) && $_SESSION["user"] == $this->current_user;
+ }
+
+ public function accountExists() {
+ $stmt = $this->conn->prepare("SELECT username FROM accounts WHERE username = :username");
+ $stmt->bindParam(":username", $this->current_user);
+ $stmt->execute();
+
+ return $stmt->rowCount() > 0;
+ }
+
+ public function getDetails($info) {
+ if (!$this->accountExists() || !$this->isLoggedIn())
+ return NULL;
+
+ $stmt = $this->conn->prepare("SELECT * FROM accounts WHERE username = :username");
+ $stmt->bindParam(":username", $this->current_user);
+ $stmt->execute();
+
+ $current_user = $stmt->fetch(PDO::FETCH_ASSOC);
+ return $current_user[$info] ?? NULL;
+ }
+ }
+?>
\ No newline at end of file
diff --git a/lib/classes/Login.php b/lib/classes/Login.php
new file mode 100644
index 0000000..dfae798
--- /dev/null
+++ b/lib/classes/Login.php
@@ -0,0 +1,52 @@
+username = trim($username);
+ $this->password = trim($password);
+ $this->conn = $conn;
+ }
+
+ public function checkUsername() {
+ if (empty($this->username)) {
+ $this->error = "Please fill out all of the fields.";
+ } else {
+ $stmt = $this->conn->prepare("SELECT username FROM accounts WHERE username = :username");
+ $stmt->bindParam(":username", $this->username);
+ $stmt->execute();
+
+ if ($stmt->rowCount() == 0)
+ $this->error = "Incorrect username or password.";
+ }
+
+ return $this->error;
+ }
+
+ public function checkPassword() {
+ if (empty($this->password)) {
+ $this->error = "Please fill out all of the fields.";
+ } else {
+ $stmt = $this->conn->prepare("SELECT password FROM accounts WHERE username = :username");
+ $stmt->bindParam(":username", $this->username);
+ $stmt->execute();
+
+ $user = $stmt->fetch(PDO::FETCH_ASSOC);
+
+ if ($user == NULL || !password_verify($this->password, $user["password"]))
+ $this->error = "Incorrect username or password.";
+ }
+
+ return $this->error;
+ }
+
+ public function authUser() {
+ session_regenerate_id(true);
+ $_SESSION['user'] = $this->username;
+ return true;
+ }
+ }
+?>
\ No newline at end of file
diff --git a/lib/classes/Post.php b/lib/classes/Post.php
new file mode 100644
index 0000000..33b3f73
--- /dev/null
+++ b/lib/classes/Post.php
@@ -0,0 +1,87 @@
+current_user = $current_user;
+ $this->conn = $conn;
+ }
+
+ public function getForm($title, $content) {
+ $this->title = $title;
+ $this->content = $content;
+ }
+
+ public function postUpdate() {
+ if (!$this->isLoggedIn())
+ return;
+
+ switch(true) {
+ case empty($this->content):
+ $this->error = "Your post cannot be left empty.";
+ break;
+ case strlen($this->content) > 2500:
+ $this->error = "Post exceeds the character limit. Are you trying to bypass it?";
+ break;
+ }
+
+ return $this->error;
+ }
+
+ public function insertPost() {
+ if (!$this->isLoggedIn())
+ return;
+
+ $new_content = $this->content;
+
+ if (empty($this->title)) {
+ // micro post
+ $type = 1;
+ $new_content = substr($this->content, 0, 300);
+ } else {
+ // marco post
+ $type = 2;
+ }
+
+ $stmt = $this->conn->prepare("INSERT INTO posts (title, content, author, type) VALUES (:title, :content, :author, :type)");
+ $stmt->bindParam(":title", $this->title);
+ $stmt->bindParam(":content", $new_content);
+ $stmt->bindParam(":author", $this->getDetails("username"));
+ $stmt->bindParam(":type", $type);
+
+ $stmt->execute();
+ return true;
+ }
+
+ public function getPosts($type) {
+ $stmt = $this->conn->prepare("SELECT * FROM posts WHERE type = :type ORDER BY date DESC");
+ $stmt->bindParam(":type", $type);
+ $stmt->execute();
+
+ return $stmt;
+ }
+
+ public function getSpecifcPost($id) {
+ $stmt = $this->conn->prepare("SELECT * FROM posts WHERE id = :id");
+ $stmt->bindParam(":id", $id);
+ $stmt->execute();
+
+ $post_details = $stmt->fetch(PDO::FETCH_ASSOC);
+ return $post_details;
+ }
+
+ public function deletePost($id) {
+ $stmt = $this->conn->prepare("DELETE FROM posts WHERE id = :id");
+ $stmt->bindParam(":id", $id);
+ $stmt->execute();
+
+ return true;
+ }
+ }
+?>
\ No newline at end of file
diff --git a/lib/classes/Register.php b/lib/classes/Register.php
new file mode 100644
index 0000000..65c81fb
--- /dev/null
+++ b/lib/classes/Register.php
@@ -0,0 +1,64 @@
+username = trim($username);
+ $this->password = trim($password);
+ $this->conn = $conn;
+ }
+
+ public function checkUsername() {
+ switch(true) {
+ case empty($this->username):
+ $this->error = "Please fill out all of the fields";
+ break;
+ case preg_match("/[^a-z0-9 ]/i", $this->username):
+ $this->error = "Username cannot have any special characters.";
+ break;
+ case strlen($this->username) > 16:
+ $this->error = "Username cannot be longer than 16 characters.";
+ break;
+ case strlen($this->username) < 3:
+ $this->error = "Your username cannot be shorter than 3 characters.";
+ break;
+ default:
+ $stmt = $this->conn->prepare("SELECT username FROM accounts WHERE username = :username");
+ $stmt->bindParam(":username", $this->username);
+ $stmt->execute();
+
+ if ($stmt->rowCount() > 0)
+ $this->error = "Username has been already taken.";
+ }
+
+ return $this->error;
+ }
+
+ public function checkPassword($passwordConfirm) {
+ if (empty($this->password)) {
+ $this->error = "Please fill out all of the fields.";
+ } else {
+ if ($this->password != $passwordConfirm)
+ $this->error = "Passwords don't match.";
+ }
+
+ return $this->error;
+ }
+
+ public function insertUser() {
+ $hashed_password = password_hash($this->password, PASSWORD_BCRYPT);
+
+ $stmt = $this->conn->prepare("INSERT INTO accounts (username, password) VALUES (:username, :password)");
+ $stmt->bindParam(":username", $this->username);
+ $stmt->bindParam(":password", $hashed_password);
+ $stmt->execute();
+
+ session_regenerate_id(true);
+ $_SESSION["user"] = $this->username;
+ return true;
+ }
+ }
+?>
\ No newline at end of file
diff --git a/lib/classes/Settings.php b/lib/classes/Settings.php
new file mode 100644
index 0000000..fbb9e84
--- /dev/null
+++ b/lib/classes/Settings.php
@@ -0,0 +1,107 @@
+current_user = $current_user;
+ $this->conn = $conn;
+ }
+
+ public function getForm($username, $bio, $password) {
+ $this->new_username = $username;
+ $this->new_bio = $bio;
+ $this->new_password = $password;
+ }
+
+ public function updateUsername() {
+ if ($this->new_username == $this->getDetails("username"))
+ return NULL;
+
+ switch(true) {
+ case empty($this->new_username):
+ $this->error = "Your username cannot be left blank.";
+ break;
+ case preg_match("/[^a-z0-9 ]/i", $this->new_username):
+ $this->error = "Username cannot have any special characters.";
+ break;
+ case strlen($this->new_username) > 16:
+ $this->error = "Username cannot be longer than 16 characters.";
+ break;
+ case strlen($this->new_username) < 3:
+ $this->error = "Username cannot be shorter than 3 characters.";
+ break;
+ default:
+ $stmt = $this->conn->prepare("SELECT username FROM accounts WHERE username = :username");
+ $stmt->bindParam(":username", $this->new_username);
+ $stmt->execute();
+
+ if ($stmt->rowCount() > 0)
+ $this->error = "Username has been already taken.";
+ }
+
+
+ if ($this->error == NULL) {
+ $stmt = $this->conn->prepare("UPDATE accounts SET username = :username WHERE id = :id");
+ $stmt->bindParam(":username", $this->new_username);
+ $stmt->bindParam(":id", $this->getDetails("id"));
+ $stmt->execute();
+
+ session_regenerate_id(true);
+ $_SESSION["user"] = $this->new_username;
+ return true;
+ }
+
+ return $this->error;
+ }
+
+ public function updateBio() {
+ if ($this->new_bio == $this->getDetails("bio"))
+ return NULL;
+
+
+ if (strlen($this->new_bio) > 150)
+ $this->error = "Bio cannot be longer than 150 characters.";
+
+ if ($this->error == NULL) {
+ $stmt = $this->conn->prepare("UPDATE accounts SET bio = :bio WHERE id = :id");
+ $stmt->bindParam(":bio", $this->new_bio);
+ $stmt->bindParam(":id", $this->getDetails("id"));
+ $stmt->execute();
+
+ return true;
+ }
+
+ return $this->error;
+ }
+
+ public function updatePassword($passwordConfirm) {
+ if (empty($this->new_password)) {
+ return NULL;
+ } else {
+ if ($this->new_password != $passwordConfirm)
+ $this->error = "Passwords don't match.";
+ }
+
+ if ($this->error == NULL) {
+ $hashed_password = password_hash($this->new_password, PASSWORD_BCRYPT);
+
+ $stmt = $this->conn->prepare("UPDATE accounts SET password = :password WHERE id = :id");
+ $stmt->bindParam(":password", $hashed_password);
+ $stmt->bindParam(":id", $this->getDetails("id"));
+ $stmt->execute();
+
+ return true;
+ }
+
+ return $this->error;
+ }
+ }
+?>
\ No newline at end of file
diff --git a/mallar.sql b/mallar.sql
new file mode 100644
index 0000000..f8da43e
--- /dev/null
+++ b/mallar.sql
@@ -0,0 +1,136 @@
+-- phpMyAdmin SQL Dump
+-- version 5.2.1
+-- https://www.phpmyadmin.net/
+--
+-- Host: localhost
+-- Generation Time: Nov 19, 2025 at 08:57 AM
+-- Server version: 10.4.32-MariaDB
+-- PHP Version: 8.2.12
+
+SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
+START TRANSACTION;
+SET time_zone = "+00:00";
+
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
+/*!40101 SET NAMES utf8mb4 */;
+
+--
+-- Database: `mallar`
+--
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `accounts`
+--
+
+CREATE TABLE `accounts` (
+ `id` int(11) NOT NULL,
+ `username` varchar(16) DEFAULT NULL,
+ `password` text DEFAULT NULL,
+ `bio` varchar(150) NOT NULL DEFAULT 'Hi! I''m new to quacking!',
+ `rank` int(11) DEFAULT 1,
+ `level_exp` int(11) DEFAULT 0,
+ `level` int(11) DEFAULT 1,
+ `date_created` timestamp NULL DEFAULT current_timestamp()
+) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
+
+--
+-- Dumping data for table `accounts`
+--
+
+INSERT INTO `accounts` (`id`, `username`, `password`, `bio`, `rank`, `level_exp`, `level`, `date_created`) VALUES
+(1, 'goom', '$2y$10$Zn6Zb4msPzvvOoP.iM0WkuvmFnfAeczFWDLS7OEHjlJpo1qfL0c3W', '', 1, 0, 1, '2025-11-07 03:25:51'),
+(2, 'poo', '$2y$10$DHs.Kc5YP.FUQQahXOV4LOAlsREMrSLBT73dyz4SfSQiSbt4mIaMa', 'Hi! I\'m new to quacking!', 1, 0, 1, '2025-11-12 23:20:34');
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `applications`
+--
+
+CREATE TABLE `applications` (
+ `id` int(11) NOT NULL,
+ `username` tinytext NOT NULL,
+ `email` varchar(320) NOT NULL DEFAULT '',
+ `context` text NOT NULL,
+ `where_heard` text NOT NULL,
+ `status` varchar(50) NOT NULL DEFAULT 'pending',
+ `reason` text DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `posts`
+--
+
+CREATE TABLE `posts` (
+ `id` int(11) NOT NULL,
+ `title` varchar(60) DEFAULT NULL,
+ `content` varchar(2500) DEFAULT NULL,
+ `date` timestamp NULL DEFAULT current_timestamp(),
+ `author` varchar(16) NOT NULL,
+ `type` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
+
+--
+-- Dumping data for table `posts`
+--
+
+INSERT INTO `posts` (`id`, `title`, `content`, `date`, `author`, `type`) VALUES
+(12, '', 'I'm eating eggs', '2025-11-12 23:23:21', 'goom', 1),
+(15, '', 'Whats up', '2025-11-17 07:43:20', 'goom', 1),
+(17, '', 'Poop', '2025-11-17 08:41:48', 'goom', 1);
+
+--
+-- Indexes for dumped tables
+--
+
+--
+-- Indexes for table `accounts`
+--
+ALTER TABLE `accounts`
+ ADD PRIMARY KEY (`id`);
+
+--
+-- Indexes for table `applications`
+--
+ALTER TABLE `applications`
+ ADD PRIMARY KEY (`id`);
+
+--
+-- Indexes for table `posts`
+--
+ALTER TABLE `posts`
+ ADD PRIMARY KEY (`id`) USING BTREE;
+
+--
+-- AUTO_INCREMENT for dumped tables
+--
+
+--
+-- AUTO_INCREMENT for table `accounts`
+--
+ALTER TABLE `accounts`
+ MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=3;
+
+--
+-- AUTO_INCREMENT for table `applications`
+--
+ALTER TABLE `applications`
+ MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
+
+--
+-- AUTO_INCREMENT for table `posts`
+--
+ALTER TABLE `posts`
+ MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=18;
+COMMIT;
+
+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
diff --git a/views/apply.php b/views/apply.php
new file mode 100644
index 0000000..bd64f52
--- /dev/null
+++ b/views/apply.php
@@ -0,0 +1,66 @@
+
+
+ = $website->title; ?>: = $website->slogan; ?>
+
+
+
+
+
welcome, = $account->getDetails("username"); ?> | log out
+
+
+
+
+
+
\ No newline at end of file
diff --git a/views/includes/left_sidebar.php b/views/includes/left_sidebar.php
new file mode 100644
index 0000000..b051e73
--- /dev/null
+++ b/views/includes/left_sidebar.php
@@ -0,0 +1,30 @@
+
\ No newline at end of file
diff --git a/views/login.php b/views/login.php
new file mode 100644
index 0000000..a431853
--- /dev/null
+++ b/views/login.php
@@ -0,0 +1,77 @@
+ htmlspecialchars($_POST["username"]),
+ "password" => htmlspecialchars($_POST["password"]),
+ ];
+
+ $login = new Login($form->username, $form->password, $conn);
+
+ $login->checkUsername();
+ $login->checkPassword();
+
+ if ($login->error == NULL) {
+ $login->authUser();
+ header("Location: /");
+ }
+ }
+?>
+
+
+ = $website->title; ?>: = $website->slogan; ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Duck login
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/views/main.php b/views/main.php
new file mode 100644
index 0000000..688bbf7
--- /dev/null
+++ b/views/main.php
@@ -0,0 +1,82 @@
+ htmlspecialchars($_POST["username"]),
+ "password" => htmlspecialchars($_POST["password"]),
+ ];
+
+ $login = new Login($form->username, $form->password, $conn);
+
+ $login->checkUsername();
+ $login->checkPassword();
+
+ if ($login->error == NULL) {
+ $login->authUser();
+ header("Location: /");
+ }
+ }
+?>
+
+
+ = $website->title; ?>: = $website->slogan; ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
WHAT IS MALLARDNET?
+
+ MallardNet is a marcoblogging platform where you can post blog-like posts on a live feed.
+ users can not only marco post, but they can have their post in any of it's three categories.
+
+
+
marco posts - blog-type posts
+
mirco posts - teeny tiny updates
+
image posts - for photography users or creative users who wants to share their world and creativity