diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d8e16cd --- /dev/null +++ b/.gitignore @@ -0,0 +1,25 @@ + +# Created by https://www.toptal.com/developers/gitignore/api/visualstudiocode +# Edit at https://www.toptal.com/developers/gitignore?templates=visualstudiocode + +### VisualStudioCode ### +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +*.code-workspace + +# Local History for Visual Studio Code +.history/ + +### VisualStudioCode Patch ### +# Ignore all local history of files +.history +.ionide + +# Support for Project snippet scope +!.vscode/*.code-snippets + +# End of https://www.toptal.com/developers/gitignore/api/visualstudiocode +.DS_Store \ No newline at end of file diff --git a/.idea/passman.iml b/.idea/passman.iml index 48c9161..f0ae207 100644 --- a/.idea/passman.iml +++ b/.idea/passman.iml @@ -1,7 +1,9 @@ - + + + diff --git a/.idea/php.xml b/.idea/php.xml index 3571588..0e09af4 100644 --- a/.idea/php.xml +++ b/.idea/php.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..dfcc0e9 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,4 @@ +{ + "tabWidth": 4, + "useTabs": true +} diff --git a/README.md b/README.md index ababe51..d1bd3b5 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,2 @@ # passman -Password Manager +The best Password Manager diff --git a/public_html/LICENSE.txt b/public_html/LICENSE.txt new file mode 100644 index 0000000..75eab8c --- /dev/null +++ b/public_html/LICENSE.txt @@ -0,0 +1,25 @@ +BSD 2-Clause License + +Copyright (c) 2021, Ben Forino, Harry Syred, Khal Rahman, Oskar Papaj +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/public_html/account.php b/public_html/account.php new file mode 100644 index 0000000..83167d6 --- /dev/null +++ b/public_html/account.php @@ -0,0 +1,25 @@ + + +

Account Details

+
+
+ + + + + + + +
+
+

+
+
+ +
+
\ No newline at end of file diff --git a/public_html/addPassword.php b/public_html/addPassword.php new file mode 100644 index 0000000..599941f --- /dev/null +++ b/public_html/addPassword.php @@ -0,0 +1,30 @@ + + +
+
+
+

Add new website

+
+ + + + + + + + + +
+
+
+
+
+

Upload CSV

+ +
+
+
+ + \ No newline at end of file diff --git a/public_html/contact.php b/public_html/contact.php new file mode 100644 index 0000000..7ad7d59 --- /dev/null +++ b/public_html/contact.php @@ -0,0 +1,54 @@ + + +
+
+

We're here

+

Feel free to ask a question

+
+
+
+
+ + + + + + + + + + + +
+
+
+
+
+

Customer Service Team:

+
+
+ profilePic +
Meet Harry
+

About Harry: some text

+

+
+ profilePic +
Meet Ben
+

Meet Ben: some text

+

+
+ profilePic +
Meet Oskar
+

Meet Ben: some text

+
+
+
+
+
+ + + + + diff --git a/public_html/footer.php b/public_html/footer.php new file mode 100644 index 0000000..84973d5 --- /dev/null +++ b/public_html/footer.php @@ -0,0 +1,13 @@ + + + + + \ No newline at end of file diff --git a/public_html/header.php b/public_html/header.php new file mode 100644 index 0000000..9769277 --- /dev/null +++ b/public_html/header.php @@ -0,0 +1,35 @@ + "passman.harrysy.red"]); +?> + + + + + + + + + + + + PassMan + + + +
+ +
\ No newline at end of file diff --git a/public_html/icon.svg b/public_html/icon.svg new file mode 100644 index 0000000..665bba0 --- /dev/null +++ b/public_html/icon.svg @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/public_html/iconPassman.png b/public_html/iconPassman.png new file mode 100644 index 0000000..613d574 Binary files /dev/null and b/public_html/iconPassman.png differ diff --git a/public_html/img/profilePicture.jpeg b/public_html/img/profilePicture.jpeg new file mode 100644 index 0000000..dcbd491 Binary files /dev/null and b/public_html/img/profilePicture.jpeg differ diff --git a/public_html/index.html b/public_html/index.html deleted file mode 100644 index e479892..0000000 --- a/public_html/index.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - - PASS MAN - - - - -

Pass Man

-

- The De Facto password manager -

- - diff --git a/public_html/index.php b/public_html/index.php new file mode 100644 index 0000000..11f93cb --- /dev/null +++ b/public_html/index.php @@ -0,0 +1,18 @@ + + \ No newline at end of file diff --git a/public_html/login.php b/public_html/login.php new file mode 100644 index 0000000..e4ac80d --- /dev/null +++ b/public_html/login.php @@ -0,0 +1,39 @@ + "passman.harrysy.red"]); +?> + + + + + + + + + + + PassMan + + + +
+
+ +
+ +
+ +
+ +
+ + + +
+

Create Account

+
+

+
+
+
\ No newline at end of file diff --git a/public_html/logout.php b/public_html/logout.php new file mode 100644 index 0000000..5d969b7 --- /dev/null +++ b/public_html/logout.php @@ -0,0 +1,6 @@ + "packages.benforino.co.uk"]); +session_unset(); +session_destroy(); +header("location: index.php?logout=successful"); +exit(); diff --git a/public_html/main.php b/public_html/main.php new file mode 100644 index 0000000..900c312 --- /dev/null +++ b/public_html/main.php @@ -0,0 +1,56 @@ + + +
+
+
+

Website Name

+ + + Refresh +
+ +
+ +
+
+
+
+
+
+ +
+
+ + +
+
+
+ +

Example.com

+
+
+

Username

+ +

Password

+ + +
+ + +
+
+ +
+
+
+
+
+ + \ No newline at end of file diff --git a/public_html/menu.php b/public_html/menu.php new file mode 100644 index 0000000..ec5838d --- /dev/null +++ b/public_html/menu.php @@ -0,0 +1,16 @@ + + + + + + + \ No newline at end of file diff --git a/public_html/otp.php b/public_html/otp.php new file mode 100644 index 0000000..0dba848 --- /dev/null +++ b/public_html/otp.php @@ -0,0 +1,47 @@ + "passman.harrysy.red"]); ?> + + + + + + + + + + + PassMan + + + + +
+
+ +
+ +
+ +
+ + +

Email verification code sent to

+ + +
+ + +
+ +
+

+
+
+
+ \ No newline at end of file diff --git a/public_html/pwd/mysql.php b/public_html/pwd/mysql.php index fef9370..8a4665e 100644 --- a/public_html/pwd/mysql.php +++ b/public_html/pwd/mysql.php @@ -11,11 +11,3 @@ $sqlDatabase = "passman"; // to connect to the locally // hosted MySQL server -// -// This below is to hide this -// page from any prying eyes if -// nginx has error and doesn't -// hide this directory: -//http_response_code(404);// stop silly bots from indexing this page -//include "/usr/share/nginx/html/index.html";// adds HTML to page, shoudl be change this to 404 error later to hide this page -?> diff --git a/public_html/reportabug.php b/public_html/reportabug.php new file mode 100644 index 0000000..e7edf34 --- /dev/null +++ b/public_html/reportabug.php @@ -0,0 +1,25 @@ + + + + +
+

Report New Bug

+ +
+ + + + + + + + + +
+
+ + + + + + \ No newline at end of file diff --git a/public_html/scripts/accountScript.js b/public_html/scripts/accountScript.js new file mode 100644 index 0000000..8ad8b15 --- /dev/null +++ b/public_html/scripts/accountScript.js @@ -0,0 +1,74 @@ +$(document).ready(function () { + getDetails(); + $("#submit").click(function (e) { + e.preventDefault(); + $.ajax({ + type: "POST", + url: "scripts/manageAccount.php", + data: $("#user_details").serialize() + "&request=update", + dataType: "json", + success: function (response) { + console.log(response); + if (response["result"] == "success") { + $("#output").html("Account Details Updated Successfully"); + } else { + $("#output").html("There was an error"); + } + refresh(); + }, + }); + }); + $("#delete").click(function (e) { + e.preventDefault(); + if ( + confirm( + "This will delete your entire account permanently, are you sure?" + ) + ) { + $.ajax({ + type: "POST", + url: "scripts/manageAccount.php", + data: { request: "delete" }, + dataType: "json", + success: function (response) { + if (response["result"] == "success") { + window.location.replace("logout.php"); + } else { + $("#output").html( + "There was an error, try again later" + ); + } + }, + }); + } + }); +}); +function getDetails() { + $.ajax({ + // Sends an async POST request to the userData script and returns an array of user details and address + type: "POST", + url: "scripts/manageAccount.php", + data: { request: "all" }, + dataType: "json", + cache: false, + statusCode: { + 404: function () { + console.log("error 404, no data returned from sql query"); + window.location.replace("/logout.php"); + }, + 403: function () { + console.log("error 403, access denied"); + window.location.replace("/login.php"); + }, + }, + success: function (response) { + for (const [key, value] of Object.entries(response)) { + $("[name='" + key + "']").val(value); + } + }, + }); +} + +function refresh() { + getDetails(); +} diff --git a/public_html/scripts/ajax.php b/public_html/scripts/ajax.php new file mode 100644 index 0000000..d0741c6 --- /dev/null +++ b/public_html/scripts/ajax.php @@ -0,0 +1,77 @@ + "passman.harrysy.red"]); +if (isset($_SESSION["user_id"]) && !isset($_GET["auth_token"])) { + $uid = $_SESSION["user_id"]; + $key = $_COOKIE["key"]; + $result = []; + if (isset($_GET["get"])) { + $get = $_GET["get"]; + if ($get == "websites") { + $result[0] = getWebsiteList($conn, [0,$uid]); + $result[1] = 200; + } + else if ($get == "passwords") { + if (isset($_GET["website_id"])) { + $result[0] = getPasswordList($conn, [0,$uid], $_GET["website_id"], $key); + $result[1] = 200; + } + } + else { + $result[0] = $_GET["get"] . " command not found"; + $result[1] = 403; + } + } + else if(isset($_POST["update"])) + { + if($_POST["update"] == "password"){ + $result[0] = json_encode(setPassword($conn,[0,$uid],$_POST["password_id"],$key,$_POST["username"],$_POST["password"])); + } + else { + $result[0] = $_GET["get"] . " command not found"; + $result[1] = 403; + } + } + else if (isset($_POST["add"])) + { + if ($_POST["add"] == "website") + { + $result[0] = addWebsite($conn,[0,$uid],$_POST["website_name"],$_POST["website_address"]); + $result[1] = 200; + } + else if ($_POST["add"] == "password") + { + $result[0] = addPassword($conn,[0,$uid],$_POST["website_id"],$_POST["username"],$_POST["password"],$key); + $result[1] = 200; + } + } + else if (isset($_POST["delete"])) + { + if ($_POST["delete"] == "website") + { + $result[0] = json_encode(deleteWebsite($conn,[0,$uid],$_POST["website_id"])); + $result[1] = 200; + } + else if ($_POST["delete"] == "password") + { + $result[0] = json_encode(deletePassword($conn,[0,$uid],$_POST["password_id"])); + $result[1] = 200; + } + } + + if (($result[0] == "") || ($result[0] == null) || ($result[0] == "null")||($result[0] == "[]")) { + echo "No data found"; + $result[1] = 204; + } + echo $result[0]; + http_response_code($result[1]); +} elseif (isset($_GET["username"])) { + $ar = array("1" => "hello"); + echo json_encode($ar); +} else { + echo "To use Ajax login with is required"; + http_response_code(401); +} diff --git a/public_html/scripts/csvUpload.php b/public_html/scripts/csvUpload.php index 630d592..fe95fd7 100644 --- a/public_html/scripts/csvUpload.php +++ b/public_html/scripts/csvUpload.php @@ -1,12 +1,11 @@ Select file to upload: '); +} else { + echo ('
Select file to upload:
'); } -?> diff --git a/public_html/scripts/db.php b/public_html/scripts/db.php index e968adb..a0948b6 100644 --- a/public_html/scripts/db.php +++ b/public_html/scripts/db.php @@ -1,13 +1,6 @@ "passman.harrysy.red"]); ?> + + + + + + + + + + + PassMan + + + + +
+
+ +
+ +
+ +
+ +

Email verification code sent to example@gmail.com

+ +
+ + +
+ +
+

+
+
+
+ diff --git a/public_html/scripts/errorHandle.js b/public_html/scripts/errorHandle.js new file mode 100644 index 0000000..a22f074 --- /dev/null +++ b/public_html/scripts/errorHandle.js @@ -0,0 +1,92 @@ +$(document).ready(function () { + var parts = window.location.search.substr(1).split("&"); + var $_GET = {}; + for (var i = 0; i < parts.length; i++) { + var temp = parts[i].split("="); + $_GET[decodeURIComponent(temp[0])] = decodeURIComponent(temp[1]); + } + errorMsg($_GET); + $("[class='section2']").hover( + function () { + $("[class='accountDrop']").show(); + $("[class='accountDrop']").css("display", "flex"); + }, + function () { + $("[class='accountDrop']").hide(); + } + ); + $("[class='section2']").click(function (e) { + $("[class='accountDrop']").toggle(); + }); + $("[class='section2']").blur(function (e) { + $("[class='accountDrop']").hide(); + }); + $.ajax({ + type: "POST", + url: "scripts/manageAccount.php", + data: { request: "getSettings" }, + dataType: "json", + success: function (response) { + if (response["dark_mode"] == "on") { + $("body").css("color", "white"); + $("body").css("background-color", "#121212"); + } + }, + }); +}); + +function errorMsg($_GET) { + switch ($_GET["error"]) { + case "ef": + displayErrorMsg( + "There are empty fields, please check your details and try again" + ); + break; + case "notfound": + $("input").css("border-color", "red"); + displayErrorMsg( + "Username/Password inccorect, please check your details and try again" + ); + break; + case "stmtfailed": + displayErrorMsg( + "Database error, please try again in a few minutes, if issue persists, contact support" + ); + break; + case "otpExpired": + displayErrorMsg( + "Your one time passcode has expired, please login again, otp's expire after 20 minutes" + ); + break; + case "maxlength": + displayErrorMsg("Max input length exceeded"); + break; + case "complexity": + displayErrorMsg( + 'Password does not meet complexity requirements
  • 8 Characters
  • 1 Special Character
  • 1 Uppercase Character
  • 1 Number
  • Not be in top 100,000 most common passwords
' + ); + $("[name='password']").css("border-color", "red"); + break; + case "otpIncorrect": + displayErrorMsg("One time passcode is incorrect, please try again"); + break; + case "ue": + displayErrorMsg( + "A user with with your username or email already exists, please try logging in" + ); + break; + case "commonPassword": + displayErrorMsg( + "Your password has been found in a common list of passwords, please try a more complex password" + ); + break; + default: + break; + } +} + +function displayErrorMsg(message) { + $("#error").css("background", "lightcoral"); + $("#error").css("padding", "10px"); + $("#error").html(message); +} diff --git a/public_html/scripts/extension.php b/public_html/scripts/extension.php new file mode 100644 index 0000000..03604ae --- /dev/null +++ b/public_html/scripts/extension.php @@ -0,0 +1,18 @@ +$code'; + } + if (($temp == "") or ($temp == null)) { + $temp = '$name here is your code:
$code'; + } + try { + include "getBrowserInfo.php"; + $browser = getOS() . " - " . getBrowser(); + } catch (Exception $ex) { + $browser = grabIp(); + } + $body = str_replace('$device', $browser, str_replace('$code', $txt, str_replace('$name', $userInfo["first_name"], $temp))); + $headers = "MIME-Version: 1.0" . "\r\n"; // tells email provider to accept next line + $headers .= "Content-type:text/html;charset=UTF-8" . "\r\n"; // tells email provider that this email is formatted in HTML + $headers .= "From: otp@passman.harrysy.red"; //tells email that it was sent by + //mail($to, $subject, "Your OTP passcode is:\r\n" . $txt, $headers); //sets up email parameters and mails it to the user + mail($to, $subject, $body, $headers); //sets up email parameters and mails it to the user + mysqli_query($conn, 'DELETE FROM otp WHERE user_id = "' . $userInfo["user_id"] . '"'); + $sql = "INSERT INTO otp (user_id, otp, otp_created) VALUES (?,?,?)"; //inserts the otp into the otp database linked to the user + $stmt = mysqli_stmt_init($conn); + mysqli_stmt_prepare($stmt, $sql); + mysqli_stmt_bind_param($stmt, "sss", $userInfo["user_id"], $txt, time()); + mysqli_stmt_execute($stmt); + $_SESSION["tempID"] = $userInfo["user_id"]; + if (!isset($pD["location"])) { + $censoredEmail = explode('@', $userInfo["email"]); + if (sizeof($censoredEmail) > 1) + header("location:../otp.php?email=@" . $censoredEmail[1]); + else + header("location:../otp.php"); + exit(); + } else { + response("otp"); + } +} function loginUser($conn, $pD) { - $userInfo = isUnique($conn, $pD); //uses the isUnique function to check if user exists and to get user details - // from database - if ($userInfo == false) { - header("location:../login.php?error=notfound"); - exit(); - } - if (password_verify($pD["password"], $userInfo["password"])) { - //checks if the password hash inputted and the password - //hash on the database match, the session is then setup - session_start(); - $_SESSION["userID"] = $userInfo["userID"]; - $_SESSION["first_name"] = $userInfo["first_name"]; - $_SESSION["last_name"] = $userInfo["last_name"]; - $_SESSION["username"] = $userInfo["username"]; - $_SESSION["email"] = $userInfo["email"]; - $_SESSION["password"] = $userInfo["password"]; - header("location:../index.php?error=success"); - exit(); - } else { - header("location:../login.php?error=notFound"); - exit(); - } + $userInfo = isUnique($conn, $pD); //uses the isUnique function to check if user exists and to get user details + // from database + if ($userInfo == false) { + if (!isset($pD["location"])) { + header("location:../login.php?error=notfound"); + exit(); + } else { + response("error", "notfound"); + } + } + if (password_verify($pD["password"], $userInfo["master_password"])) { + if ($userInfo["masterkey"] == "") { + //setcookie("key", hash("sha3-512", $pD["password"]), 0, "/", "passman.harrysy.red", true); + setcookie("key", keyGen($conn, $pD["password"], $userInfo["user_id"]), 0, "/", "passman.harrysy.red", true); + } else { + setcookie("key", keyGet($conn, $pD["password"], $userInfo["user_id"]), 0, "/", "passman.harrysy.red", true); + } + + generateOneTimePassword($conn, $userInfo, $pD); + //checks if the password hash inputted and the password + //hash on the database match, the one time passcode function is then called + } else { + if (!isset($pD["location"])) { + header("location:../login.php?error=notfound"); + exit(); + } else { + response("error", "notfound"); + } + } +} +function keyGet($conn, $password, $user_id) +{ + $sql = "select masterkey, masteriv from user where user_id = ?;"; //sql statement to get masterkey and masteriv + $stmt = mysqli_stmt_init($conn); // to make statement variable + mysqli_stmt_prepare($stmt, $sql); // to prepare statment with sql line + mysqli_stmt_bind_param($stmt, "i", $user_id); // binds the parameter + mysqli_stmt_execute($stmt); // executes sql + $stmtresult = mysqli_stmt_get_result($stmt); //gets the result of the sql query + $row = mysqli_fetch_assoc($stmtresult); // creates an associative array of the sql result + $iv = base64_decode($row["masteriv"]); // decoded iv to binary version + $masterkey = decryptData($row["masterkey"], $password, $iv); // decrypt masterpassword + return $masterkey; // returns master password +} +function keyGen($conn, $password, $user_id) +{ + $iv = generateIV(); // genorates iv + $key = hash("sha3-512", $password); //genorates key + $based_iv = base64_encode($iv); //base64 + $masterkey = encryptData($key, $password, $iv); + $sql = "update user set masterkey = ?, masteriv = ? where user_id = ?;"; + $stmt = mysqli_stmt_init($conn); + mysqli_stmt_prepare($stmt, $sql); + mysqli_stmt_bind_param($stmt, "ssi", $masterkey, $based_iv, $user_id); + mysqli_stmt_execute($stmt); + return keyGet($conn, $password, $user_id); } +/** + * This updates the users password with the key\ + * This will roll back if it fails + * + * @param mysqli $conn + * Database connection, should be the same one mysqli_autocommit function was used on + * @param int $user_id + * the user id of the user that the password is changing for + * @param string $oldPassword + * the old password of the user + * @param string $newPassword + * the new password you want the new user to use + * @return Array + * The outcomes of the funciton:\ + * `[0, "Success"]`\ + * `[1, "Failure, Password did not meet complexity needs"]`\ + * `[2, "Failure to change password, DBMS rolled back"]`\ + * `[3, "Failure to change key, DBMS rolled back"]`\ + * `[4, "Error caught by try:\n , DBMS rolled back"]`\ + * `[98, "Error caught by try:\n , Unknown DBMS state"]`\ + * `[98, "Unknown error, Unknown DBMS state"]`\ + * `[99, "Catastrophic Failure, Unknown DBMS stat"]` + */ +function changeUserPassword($conn, $oldPassword, $newPassword) +{ + try { + mysqli_autocommit($conn, FALSE); // stops rollbacks + + mysqli_commit($conn); + } catch (Exception $e) { + return [98, "Error caught by try:\n " . $e . ", Unknown DBMS state"]; + die("Can't change passwrod safely"); + } + try { + $resultFromKeyChange = keyPasswordChange($conn, $_SESSION["user_id"], $oldPassword, $newPassword); + $pswdHash = password_hash($newPassword, PASSWORD_DEFAULT); //hashes the users password before it is stored + if ($resultFromKeyChange) { + $sql = "update user set master_password = ? where user_id = ?;"; + $stmt = mysqli_stmt_init($conn); + mysqli_stmt_prepare($stmt, $sql); + mysqli_stmt_bind_param($stmt, "si", $pswdHash, $_SESSION["user_id"]); + mysqli_stmt_execute($stmt); + $sql = "SELECT `master_password` FROM user WHERE user_id = ?;"; + $stmt = mysqli_stmt_init($conn); + mysqli_stmt_prepare($stmt, $sql); + mysqli_stmt_bind_param($stmt, "i", $_SESSION["user_id"]); + mysqli_stmt_execute($stmt); //executes sql query + $stmtresult = mysqli_stmt_get_result($stmt); //gets the result of the sql query + if ($row = mysqli_fetch_assoc($stmtresult)) { // creates an associative array of the sql result + if (password_verify($newPassword, $row["master_password"])) { + mysqli_commit($conn); + mysqli_autocommit($conn, TRUE); + return [0, "Success"]; + } else { + mysqli_rollback($conn); + mysqli_autocommit($conn, TRUE); + return [2, "Failure to change Passwrod, DBMS rolled back"]; + } + } else { + mysqli_rollback($conn); + mysqli_autocommit($conn, TRUE); + return [2, "Failure to change Passwrod, DBMS rolled back"]; + } + } else { + mysqli_rollback($conn); + mysqli_autocommit($conn, TRUE); + return [3, "Failure to change key, DBMS rolled BACK"]; + } + } catch (Exception $e) { + try { + mysqli_rollback($conn); + mysqli_autocommit($conn, TRUE); + return [4, "Error Caught By Try: " . $e . ", DBMS rolled back"]; + } catch (Exception $ee) { + return [98, "Error caught by try:\n " . $ee . "\n\nAND\n\n" . $e . ", Unknown DBMS state"]; + } + } + return [99, "Catastrophic Failure, Unknown DBMS stat"]; +} +/** + * This updates the key to new password\ + * **THIS DOES NOT CHANGE PASSWORD**\ + * Please use `changeUserPassword` to change Password + * + * @param mysqli $conn + * Database connection, should be the same one mysqli_autocommit function was used on + * @param int $user_id + * the user id of the user that the password is changing for + * @param string $oldPassword + * the old password of the user + * @param string $newPassword + * the new password you want the new user to use + * @return boolean + * if it was successfully able to make changes\ + * False - attempt failed, please rollback\ + * True - attempt passed, commit + */ +function keyPasswordChange($conn, $user_id, $oldPassword, $newPassword) +{ + try { + $iv = generateIV(); // genorates iv + $key = keyGet($conn, $oldPassword, $user_id); + $based_iv = base64_encode($iv); //base64 + $masterkey = encryptData($key, $newPassword, $iv); + $sql = "update user set masterkey = ?, masteriv = ? where user_id = ?;"; + $stmt = mysqli_stmt_init($conn); + mysqli_stmt_prepare($stmt, $sql); + mysqli_stmt_bind_param($stmt, "ssi", $masterkey, $based_iv, $user_id); + mysqli_stmt_execute($stmt); + if ($key == keyGet($conn, $user_id, $newPassword)) { + return TRUE; + } else { + return FALSE; + } + } catch (ErrorException $e) { + return FALSE; + } +} function signUp($conn, $pD) { - $sql = "INSERT INTO user (first_name, last_name, username, email, password) VALUES (?,?,?,?,?);"; //starts to - // prepare the sql statement - $stmt = mysqli_stmt_init($conn); - if (!mysqli_stmt_prepare($stmt, $sql)) { - header("location: ../signup.php?error=stmtfailed"); - exit(); - } - $pswdHash = password_hash($pD["password"], PASSWORD_DEFAULT); //hashes the users password before it is stored + $sql = "INSERT INTO user (first_name, last_name, username, email, master_password, dob, mobile) VALUES (?,?,?,?,?,?,?);"; //starts to + // prepare the sql statement + $stmt = mysqli_stmt_init($conn); + if (!mysqli_stmt_prepare($stmt, $sql)) { + header("location: ../signup.php?error=stmtfailed"); + exit(); + } + $pswdHash = password_hash($pD["password"], PASSWORD_DEFAULT); //hashes the users password before it is stored - mysqli_stmt_bind_param($stmt, "sssss", $pD["first_name"], $pD["last_name"], $pD["username"], $pD["email"], $pswdHash); + mysqli_stmt_bind_param($stmt, "sssssss", $pD["first_name"], $pD["last_name"], $pD["username"], $pD["email"], $pswdHash, $pD["dob"], $pD["mobile"]); + //bind parameters to statement + if (!mysqli_stmt_execute($stmt)) { //executes the INSERT statement + header("location:../signup.php?error=stmtfailed"); + exit(); + } + header("location:../login.php?signup=success"); + exit(); +} +function generateIV() +{ + $cipher = "aes-256-cbc"; //define cipher to use + $ivlen = openssl_cipher_iv_length($cipher); //defines iv's length + $iv = openssl_random_pseudo_bytes($ivlen); //creates iv using random bytes - if (!mysqli_stmt_execute($stmt)) { //executes the INSERT statement - header("location:../signup.php?error=stmtfailed"); - exit(); - } - header("location:../signup.php?error=success"); - exit(); + return $iv; +} + +function encryptData($data, $key, $iv) +{ + $cipher = "aes-256-cbc"; //define cipher to use + if (in_array($cipher, openssl_get_cipher_methods())) { //checks if cipher is valid + $ciphertext = openssl_encrypt($data, $cipher, $key, 0, $iv); //encrypts + return $ciphertext; + } else { + echo "can't securely encrypt and decrypt password"; + return -1; + } +} + +function decryptData($ciphertext, $key, $iv) +{ + $cipher = "aes-256-cbc"; //define cipher to use + if (in_array($cipher, openssl_get_cipher_methods())) { //checks if cipher is valid + $plaintext = openssl_decrypt($ciphertext, $cipher, $key, 0, $iv); //decrypts + return $plaintext; + } else { + echo "can't securely encrypt and decrypt password"; + return -1; + } +} + +function createWebEntry($conn, $pD) +{ + $sql = "INSERT INTO saved_website (user_id, website_name, web_address) VALUES (?,?,?);"; + $stmt = mysqli_stmt_init($conn); + if (!mysqli_stmt_prepare($stmt, $sql)) { + header("location: ../index.php?error=stmtfailed"); + exit(); + } + mysqli_stmt_bind_param($stmt, "sss", $_SESSION["user_id"], $pD["website_name"], $pD["web_address"]); + if (!mysqli_stmt_execute($stmt)) { //executes the INSERT statement + header("location:../index.php?error=stmtfailed"); + exit(); + } + header("location:../index.php?error=success"); +} + +function passwordComplex($pswd) +{ + if (strlen($pswd) < 20) { + $uppercase = preg_match('@[A-Z]@', $pswd); + $lowercase = preg_match('@[a-z]@', $pswd); + $number = preg_match('@[0-9]@', $pswd); + $specialChars = preg_match('@[^\w]@', $pswd); + if (!$uppercase || !$lowercase || !$number || !$specialChars || strlen($pswd) < 8) { + return false; + } else { + return true; + } + } else { + return true; + } +} +function getWebsiteList($conn, $user_identifier) +{ + $user_id = ""; + if ($user_identifier[0] == 0) + $user_id = $user_identifier[1]; + else + $user_id = getUidWhereAuthCode($conn, $user_identifier[1]); + $sql = "SELECT website_id, website_name, web_address from user JOIN saved_website ON user.user_id = saved_website.user_id WHERE user.user_id = ? order by saved_website.website_name"; + $stmt = mysqli_stmt_init($conn); + mysqli_stmt_prepare($stmt, $sql); + mysqli_stmt_bind_param($stmt, "s", $user_id); + mysqli_stmt_execute($stmt); + $stmtresult = mysqli_stmt_get_result($stmt); + $result = mysqli_fetch_all($stmtresult, MYSQLI_ASSOC); + mysqli_free_result($stmtresult); + return json_encode($result); +} +function addWebsite($conn, $user_identifier, $wb_name, $wb_address) +{ + $website_name = ($wb_name); + $website_address = ($wb_address); + $user_id = ""; + if ($user_identifier[0] == 0) + $user_id = $user_identifier[1]; + else + $user_id = getUidWhereAuthCode($conn, $user_identifier[1]); + $rand = 0; + $available = false; + do { + $rand = rand(0, 999999999); + $sql = "SELECT 1 as 'exists' from saved_website WHERE website_id = ?"; + $stmt = mysqli_stmt_init($conn); + mysqli_stmt_prepare($stmt, $sql); + mysqli_stmt_bind_param($stmt, "s", $rand); + mysqli_stmt_execute($stmt); + $stmtresult = mysqli_stmt_get_result($stmt); + $result = mysqli_fetch_all($stmtresult, MYSQLI_ASSOC); + mysqli_free_result($stmtresult); + if (sizeof($result) > 0) { + $available = false; + } else if (sizeof($result) == 0) { + $available = true; + } + $stmt->close(); + } while (!$available); + $sql = "INSERT INTO saved_website VALUES (?,?,?,?,CURRENT_TIMESTAMP(),CURRENT_TIMESTAMP())"; + $stmt = mysqli_stmt_init($conn); + mysqli_stmt_prepare($stmt, $sql); + mysqli_stmt_bind_param($stmt, "iiss", $rand, $user_id, $website_name, $website_address); + mysqli_stmt_execute($stmt); + $result = mysqli_stmt_affected_rows($stmt); + return json_encode(["result" => $result, "name" => $website_name, "address" => $website_address]); +} +function addPassword($conn, $user_identifier, $website_id, $pw_username, $pw_password, $key) +{ + $iv = generateIV(); // genorates a new IV per new version of a password + $cryptUsername = encryptData($pw_username, $key, $iv); + $cryptPassword = encryptData($pw_password, $key, $iv); + $user_id = ""; + if ($user_identifier[0] == 0) + $user_id = $user_identifier[1]; + else + + $user_id = getUidWhereAuthCode($conn, $user_identifier[1]); + $rand = 0; + $available = false; + do { + $rand = rand(0, 999999999); + $sql = "SELECT 1 as 'exists' from website_password WHERE password_id = ?"; + $stmt = mysqli_stmt_init($conn); + mysqli_stmt_prepare($stmt, $sql); + mysqli_stmt_bind_param($stmt, "s", $rand); + mysqli_stmt_execute($stmt); + $stmtresult = mysqli_stmt_get_result($stmt); + $result = mysqli_fetch_all($stmtresult, MYSQLI_ASSOC); + mysqli_free_result($stmtresult); + if (sizeof($result) > 0) { + $available = false; + } else if (sizeof($result) == 0) { + $available = true; + } + $stmt->close(); + } while (!$available); + $sql = "INSERT INTO website_password values (?,(SELECT sw.website_id FROM `saved_website` as sw WHERE sw.website_id = ? AND sw.user_id = ?),?,?,?)"; + //$sql = "INSERT INTO website_password values (?,(SELECT website_id FROM `saved_website` WHERE website_id = ? AND user_id = ?),?,?,?)"; + //$sql = "INSERT INTO password_id VALUES (?,?,?,?,CURRENT_TIMESTAMP(),CURRENT_TIMESTAMP())"; + $stmt = mysqli_stmt_init($conn); + mysqli_stmt_prepare($stmt, $sql); + mysqli_stmt_bind_param($stmt, "iiisss", $rand, $website_id, $user_id, $cryptUsername, $cryptPassword, base64_encode($iv)); + mysqli_stmt_execute($stmt); + $result = mysqli_stmt_affected_rows($stmt); + return json_encode(["result" => $result, "rand" => $rand, "website_id" => $website_id, "user_id" => $user_id, "cryptUn" => $cryptUsername, "cryptPw" => $cryptPassword]); +} +function getPasswordList($conn, $user_identifier, $website_id, $key) +{ + $user_id = ""; + if ($user_identifier[0] == 0) + $user_id = $user_identifier[1]; + else + $user_id = getUidWhereAuthCode($conn, $user_identifier[1]); + //$sql = "SELECT website_password.website_id, password_id, username, password, vi from website_password JOIN [SELECT website_id, from user JOIN saved_website ON user.user_id = saved_website.user_id WHERE user.user_id = ?] where website"; + $sql = "SELECT website_password.* from website_password JOIN (SELECT website_id FROM user JOIN saved_website ON user.user_id = saved_website.user_id where user.user_id = ?) as websites on website_password.website_id = websites.website_id where website_password.website_id = ?"; + $stmt = mysqli_stmt_init($conn); + mysqli_stmt_prepare($stmt, $sql); + mysqli_stmt_bind_param($stmt, "ss", $user_id, $website_id); + mysqli_stmt_execute($stmt); + $stmtresult = mysqli_stmt_get_result($stmt); + $cipher = mysqli_fetch_all($stmtresult, MYSQLI_ASSOC); + mysqli_free_result($stmtresult); + $result = []; + for ($i = 0; $i < sizeof($cipher); $i++) { + $result[$i] = []; + $result[$i]["website_id"] = $cipher[$i]["website_id"]; + $result[$i]["password_id"] = $cipher[$i]["password_id"]; + $result[$i]["username"] = decryptData($cipher[$i]["username"], $key, base64_decode($cipher[$i]["iv"])); + $result[$i]["password"] = decryptData($cipher[$i]["password"], $key, base64_decode($cipher[$i]["iv"])); + } + return json_encode($result); +} + + +function response($response, $error = "none") +{ + $return = array("response" => $response, "error" => $error); + echo json_encode($return); + exit(); +} +function getUidWhereAuthCode($conn, $authToken) +{ + /**TODO: + * - make invalid in 2 weeks after date_created + * - add function to make invalid and check if invalid here + */ + $sql = "SELECT user_id from auth_token where auth_token = ?"; + $stmt = mysqli_stmt_init($conn); + mysqli_stmt_prepare($stmt, $sql); + mysqli_stmt_bind_param($stmt, 's', $authToken); + mysqli_stmt_execute($stmt); + $stmtresult = mysqli_stmt_get_result($stmt); + $result = mysqli_fetch_all($stmtresult); + return $result['user_id']; +} +function deletePassword($conn, $user_identifier, $password_id) +{ + $user_id = ""; + if ($user_identifier[0] == 0) + $user_id = $user_identifier[1]; + else + $user_id = getUidWhereAuthCode($conn, $user_identifier[1]); + //$sql = "SELECT website_password.website_id, password_id, username, password, vi from website_password JOIN [SELECT website_id, from user JOIN saved_website ON user.user_id = saved_website.user_id WHERE user.user_id = ?] where website"; + //$sql = "SELECT website_password.* from website_password JOIN (SELECT website_id FROM user JOIN saved_website ON user.user_id = saved_website.user_id where user.user_id = ?) as websites on website_password.website_id = websites.website_id where website_password.website_id = ?"; + //$sql = "UPDATE website_password as tb set tb.username = ?, tb.password = ?, tb.iv = ? where tb.password_id = ? AND password_id in (select website_password.password_id from user inner join saved_website on user.user_id = saved_website.user_id inner join website_password on saved_website.website_id = website_password.website_id WHERE user.user_id = ?) "; + $sql = "DELETE FROM website_password where password_id = ? AND password_id in (select website_password.password_id from user inner join saved_website on user.user_id = saved_website.user_id inner join website_password on saved_website.website_id = website_password.website_id WHERE user.user_id = ?) "; + $stmt = mysqli_stmt_init($conn); + mysqli_stmt_prepare($stmt, $sql); + mysqli_stmt_bind_param($stmt, "ii", $password_id, $user_id); + mysqli_stmt_execute($stmt); + return ["success" => mysqli_stmt_affected_rows($stmt)]; +} +function deleteWebsite($conn, $user_identifier, $website_id) +{ + $user_id = ""; + if ($user_identifier[0] == 0) + $user_id = $user_identifier[1]; + else + $user_id = getUidWhereAuthCode($conn, $user_identifier[1]); + //$sql = "SELECT website_password.website_id, password_id, username, password, vi from website_password JOIN [SELECT website_id, from user JOIN saved_website ON user.user_id = saved_website.user_id WHERE user.user_id = ?] where website"; + //$sql = "SELECT website_password.* from website_password JOIN (SELECT website_id FROM user JOIN saved_website ON user.user_id = saved_website.user_id where user.user_id = ?) as websites on website_password.website_id = websites.website_id where website_password.website_id = ?"; + //$sql = "UPDATE website_password as tb set tb.username = ?, tb.password = ?, tb.iv = ? where tb.password_id = ? AND password_id in (select website_password.password_id from user inner join saved_website on user.user_id = saved_website.user_id inner join website_password on saved_website.website_id = website_password.website_id WHERE user.user_id = ?) "; + //$sql = "DELETE FROM website_password where password_id = ? AND password_id in (select website_password.password_id from user inner join saved_website on user.user_id = saved_website.user_id inner join website_password on saved_website.website_id = website_password.website_id WHERE user.user_id = ?) "; + $sql = "DELETE FROM saved_website where website_id = ? AND user_id = ?"; + $stmt = mysqli_stmt_init($conn); + mysqli_stmt_prepare($stmt, $sql); + mysqli_stmt_bind_param($stmt, "ii", $website_id, $user_id); + mysqli_stmt_execute($stmt); + return ["success" => mysqli_stmt_affected_rows($stmt)]; +} +function setPassword($conn, $user_identifier, $password_id, $key, $username, $password) +{ + $user_id = ""; + if ($user_identifier[0] == 0) + $user_id = $user_identifier[1]; + else + $user_id = getUidWhereAuthCode($conn, $user_identifier[1]); + $iv = generateIV(); // genorates a new IV per new version of a password + //$sql = "SELECT website_password.website_id, password_id, username, password, vi from website_password JOIN [SELECT website_id, from user JOIN saved_website ON user.user_id = saved_website.user_id WHERE user.user_id = ?] where website"; + //$sql = "SELECT website_password.* from website_password JOIN (SELECT website_id FROM user JOIN saved_website ON user.user_id = saved_website.user_id where user.user_id = ?) as websites on website_password.website_id = websites.website_id where website_password.website_id = ?"; + $cryptUsername = encryptData($username, $key, $iv); + $cryptPassword = encryptData($password, $key, $iv); + $sql = "UPDATE website_password as tb set tb.username = ?, tb.password = ?, tb.iv = ? where tb.password_id = ? AND password_id in (select website_password.password_id from user inner join saved_website on user.user_id = saved_website.user_id inner join website_password on saved_website.website_id = website_password.website_id WHERE user.user_id = ?) "; + $stmt = mysqli_stmt_init($conn); + mysqli_stmt_prepare($stmt, $sql); + mysqli_stmt_bind_param($stmt, "sssii", $cryptUsername, $cryptPassword, base64_encode($iv), $password_id, $user_id); + mysqli_stmt_execute($stmt); + return ["success" => mysqli_stmt_affected_rows($stmt)]; +} +function commonPassword($conn, $pD) +{ + $pD["password"] = strtolower($pD["password"]); + $sql = "SELECT * FROM `common_passwords` WHERE `password` = ?"; + $stmt = mysqli_stmt_init($conn); + mysqli_stmt_prepare($stmt, $sql); + mysqli_stmt_bind_param($stmt, "s", $pD["password"]); + mysqli_stmt_execute($stmt); + $stmtresult = mysqli_stmt_get_result($stmt); //gets the result of the sql query + $result = mysqli_fetch_assoc($stmtresult); + if (count($result) >= 1) { + return true; + } else { + return false; + } } diff --git a/public_html/scripts/getBrowserInfo.php b/public_html/scripts/getBrowserInfo.php new file mode 100644 index 0000000..21ae442 --- /dev/null +++ b/public_html/scripts/getBrowserInfo.php @@ -0,0 +1,78 @@ + 'Windows 10', + '/windows nt 6.3/i' => 'Windows 8.1', + '/windows nt 6.2/i' => 'Windows 8', + '/windows nt 6.1/i' => 'Windows 7', + '/windows nt 6.0/i' => 'Windows Vista', + '/windows nt 5.2/i' => 'Windows Server 2003/XP x64', + '/windows nt 5.1/i' => 'Windows XP', + '/windows xp/i' => 'Windows XP', + '/windows nt 5.0/i' => 'Windows 2000', + '/windows me/i' => 'Windows ME', + '/win98/i' => 'Windows 98', + '/win95/i' => 'Windows 95', + '/win16/i' => 'Windows 3.11', + '/macintosh|mac os x/i' => 'Mac OS X', + '/mac_powerpc/i' => 'Mac OS 9', + '/linux/i' => 'Linux', + '/ubuntu/i' => 'Ubuntu', + '/iphone/i' => 'iPhone', + '/ipod/i' => 'iPod', + '/ipad/i' => 'iPad', + '/android/i' => 'Android', + '/blackberry/i' => 'BlackBerry', + '/webos/i' => 'Mobile' + ); + + foreach ($os_array as $regex => $value) { + if (preg_match($regex, $user_agent)) { + $os_platform = $value; + } + } + return $os_platform; +} +function getBrowser() +{ + $user_agent = $_SERVER['HTTP_USER_AGENT']; + if ($_SERVER['HTTP_SENT_FROM'] == "passext") { + $browser = "PassManExtension"; + return $browser; + } else { + + $browser = "Browser Unknown"; + $browser_array = array( + '/passext/i' => 'PassManExtension', + '/msie/i' => 'Internet Explorer', + '/firefox/i' => 'Firefox', + '/safari/i' => 'Safari', + '/chrome/i' => 'Chrome', + '/edge/i' => 'Edge', + '/opera/i' => 'Opera', + '/netscape/i' => 'Netscape', + '/maxthon/i' => 'Maxthon', + '/konqueror/i' => 'Konqueror', + '/mobile/i' => 'Handheld Browser' + ); + + foreach ($browser_array as $regex => $value) { + if (preg_match($regex, $user_agent)) { + $browser = $value; + } + } + return $browser; + } +} + +//echo getOS() . " - " . getBrowser(); diff --git a/public_html/scripts/loginAPI.php b/public_html/scripts/loginAPI.php index acedc85..3c33438 100644 --- a/public_html/scripts/loginAPI.php +++ b/public_html/scripts/loginAPI.php @@ -13,24 +13,18 @@ $statement->execute(); $rows = $statement->fetchAll(PDO::FETCH_ASSOC); $passwordhash = password_hash($password, PASSWORD_DEFAULT); -if (count($rows) == 1) -{ +if (count($rows) == 1) { if ( ($rows[0]["username"] == $username) and ($rows[0]["password"] == $passwordhash) - ) - { + ) { echo "Result: Logged in as " . $rows[0]["username"]; // this will be turned into function and used elsewhere - } - else - { + } else { echo "Result: Could not authenticate"; } -} -else -{ +} else { echo "Result: Could not authenticate"; } //elseif (($action == "search") and $debug) { diff --git a/public_html/scripts/loginScript.php b/public_html/scripts/loginScript.php index 7b6a0f5..4d94d00 100644 --- a/public_html/scripts/loginScript.php +++ b/public_html/scripts/loginScript.php @@ -1,20 +1,21 @@ "passman.harrysy.red"]); +if (isset($_POST["submit"]) && !isset($_SESSION["user_id"])) { // checks if any post data has been received + require_once("db.php"); + require_once("functions.php"); // calls both required php scripts + $pD = $_POST; + $pD["email"] = $pD["username"]; + unset($pD["submit"]); + $pD = array_map('htmlentities', $pD); + if (!emptyFields($pD)) { // checks if any of passed fields are empty + header("location:../login.php?error=ef"); + exit(); + } + //More checks to be done + loginUser($conn, $pD); //logs in the user } else { - header("location:../index.php"); - exit(); + header("location:../index.php"); + exit(); } diff --git a/public_html/scripts/main.js b/public_html/scripts/main.js new file mode 100644 index 0000000..1682e3f --- /dev/null +++ b/public_html/scripts/main.js @@ -0,0 +1,363 @@ +var count = 0; +document.getElementById("mainAddImport").addEventListener("click",addWebsite); +function listWebsites(div) { + $.ajax({ + type: "GET", + url: "/scripts/ajax.php", + data: "get=websites", + dataType: "JSON", + statusCode: { + 444: function () { + console.log("cant find data"); + }, + 500: function () { + console.log("PHP code error"); + }, + 401: function () { + console.log("please authenticate"); + document.location = "/logout.php"; + }, + }, + success: function (response) { + while (div.children().length > 0) div.children()[0].remove(); + //$("#passwords").empty(); + for (let i = 0; i < response.length; i++) { + let websiteButton = document.createElement("button"); + websiteButton.innerText = response[i]["website_name"]; + websiteButton.name = response[i]["web_address"]; + websiteButton.value = response[i]["website_id"]; + websiteButton.classList.add("websiteName"); + websiteButton.addEventListener("click",grabPasswords); + div.append(websiteButton); + } + }, + }); +} +function addWebsite(evt) { + if (document.getElementById("mkWbOverlay") == null) { + let overlay = document.createElement("div"); + overlay.classList.add("overlay"); + overlay.id = "mkWbOverlay"; + let span = document.createElement("span"); + span.innerText = "Add a new website to your account:"; + let wbName = document.createElement("input"); + wbName.type = "text"; + wbName.placeholder = "Website Name: Google"; + wbName.name = "wbName"; + let wbAddr = document.createElement("input"); + wbAddr.type = "text"; + wbAddr.placeholder = "Website Address: http://example.com"; + wbAddr.name = "wbAddr"; + let wbAddBtn = document.createElement("input"); + wbAddBtn.name = "wbAddBtn"; + wbAddBtn.type = "button"; + wbAddBtn.value = "Add Website"; + wbAddBtn.addEventListener("click", createWebsite); + let wbCancBtn = document.createElement("input"); + wbCancBtn.type = "button"; + wbCancBtn.value = "Cancel"; + wbCancBtn.name = "wbCancBtn"; + wbCancBtn.addEventListener("click", function () { + document.getElementById("mkWbOverlay").remove(); + }); + let btnHolder = document.createElement("div"); + btnHolder.classList.add("btn"); + btnHolder.appendChild(wbCancBtn); + btnHolder.appendChild(wbAddBtn); + overlay.appendChild(span); + + overlay.appendChild(wbName); + overlay.appendChild(wbAddr); + + overlay.appendChild(btnHolder); + document.body.appendChild(overlay); + } +} +function refreshPassword(evt) { + let btn = evt.currentTarget; + let wbId = btn.name; + let allWebsiteButtons = $(".websiteName"); + for (let i = 0;i < allWebsiteButtons.length;i++){ + if(allWebsiteButtons[i].value == wbId){ + allWebsiteButtons[i].click(); + } + } +} +function addPassword(evt) { + let btn = evt.currentTarget; + let wbId = btn.name; + console.log(wbId); + if (document.getElementById("mkPwOverlay") == null) { + let overlay = document.createElement("div"); + overlay.classList.add("overlay"); + overlay.id = "mkPwOverlay"; + let span = document.createElement("span"); + span.innerText = "Add a new password:"; + let wbName = document.createElement("input"); + wbName.type = "text"; + wbName.placeholder = "Username"; + wbName.name = "pwUsername"; + let wbAddr = document.createElement("input"); + wbAddr.type = "password"; + wbAddr.placeholder = "Password"; + wbAddr.name = "pwPassword"; + let wbAddBtn = document.createElement("input"); + wbAddBtn.name = wbId; + wbAddBtn.type = "button"; + wbAddBtn.value = "Add Password"; + wbAddBtn.addEventListener("click", createPassword); + let wbCancBtn = document.createElement("input"); + wbCancBtn.type = "button"; + wbCancBtn.value = "Cancel"; + wbCancBtn.name = "pwCancBtn"; + wbCancBtn.addEventListener("click", function () { + document.getElementById("mkPwOverlay").remove(); + }); + let btnHolder = document.createElement("div"); + btnHolder.classList.add("btn"); + btnHolder.appendChild(wbCancBtn); + btnHolder.appendChild(wbAddBtn); + overlay.appendChild(span); + + overlay.appendChild(wbName); + overlay.appendChild(wbAddr); + + overlay.appendChild(btnHolder); + document.body.appendChild(overlay); + } +} +function createWebsite(evt) { + let wbName = ""; + let wbAddr = ""; + + let overlayChildren = evt.currentTarget.parentNode.parentNode.children; + for (let i = 0; i < overlayChildren.length; i++) { + let child = overlayChildren[i]; + if (child.name == "wbAddr") { + wbAddr = child.value; + } else if (child.name == "wbName") { + wbName = child.value; + } + } + $.post( + "/scripts/ajax.php", + (data = { + add: "website", + website_name: wbName, + website_address: wbAddr, + }), + function (data, textStatus, jqXHR) { + if (data == 1) document.getElementById("mkWbOverlay").remove(); + }, + "json" + ); +} +function createPassword(evt) { + let btn = evt.currentTarget; + let wbId = btn.name; + let pwUsername = ""; + let pwPassword = ""; + + let overlayChildren = evt.currentTarget.parentNode.parentNode.children; + for (let i = 0; i < overlayChildren.length; i++) { + let child = overlayChildren[i]; + if (child.name == "pwUsername") { + pwUsername = child.value; + } else if (child.name == "pwPassword") { + pwPassword = child.value; + } + } + $.post( + "/scripts/ajax.php", + (data = { + add: "password", + website_id: wbId, + username: pwUsername, + password: pwPassword, + }), + function (data, textStatus, jqXHR) { + if (data["result"] == 1) + document.getElementById("mkPwOverlay").remove(); + }, + "json" + ); +} +function editPasswords(evt) { + let btn = evt.currentTarget; + let tmp = $('[name="' + btn.name + '"]'); + for (let i = 0; i < tmp.length; i++) { + if (tmp[i].id == "passwordUsername" || tmp[i].id == "passwordPassword") + tmp[i].disabled = false; + } + btn.value = "Save"; + btn.removeEventListener("click", editPasswords); + btn.addEventListener("click", updatePasswords); +} +function deletePasswords(evt) { + let btn = evt.currentTarget; + let tPart = btn.id.split(":"); + let part = ""; + if (tPart.length > 2) + part = tPart[1]; + let passwordId = btn.name.split(":")[1]; + $.ajax({ + type: "POST", + url: "/scripts/ajax.php", + data: { + delete: "password", + password_id: passwordId + }, + dataType: "JSON", + statusCode: { + 444: function () { + console.log("cant find data"); + }, + 500: function () { + console.log("PHP code error"); + }, + 401: function () { + document.location = "/logout.php"; + }, + }, + success: function (response) { + if(response["success"] == 1) + { + console.log("deleted"); + $("#refreshBtn").click(); + } + + } + }); + btn.removeEventListener("click", updatePasswords); +} +function updatePasswords(evt) { + let newUsername = document.getElementById("passwordUsername").value; + let newPassword = document.getElementById("passwordPassword").value; + + let btn = evt.currentTarget; + let tmp = $('[name="' + btn.name + '"]'); + // for (let i = 0; i < tmp.length; i++) { + // if (tmp[i].id = "passwordUsername") + // newUsername = tmp[i].value; + // if (tmp[i].id = "passwordPassword") + // newPassword = tmp[i].value; + // } + let tPart = btn.id.split(":"); + let part = ""; + if (tPart.length > 2) part = tPart[1]; + let passwordId = btn.name.split(":")[1]; + $.ajax({ + type: "POST", + url: "/scripts/ajax.php", + data: { + update: "password", + password_id: passwordId, + username: newUsername, + password: newPassword, + }, + dataType: "JSON", + statusCode: { + 444: function () { + console.log("cant find data"); + }, + 500: function () { + console.log("PHP code error"); + }, + 401: function () { + document.location = "/logout.php"; + }, + }, + success: function (response) { + console.log("Password updated"); + btn.removeEventListener("click", updatePasswords); + btn.addEventListener("click", editPasswords); + let tmp = $('[name="' + btn.name + '"]'); + for (let i = 0; i < tmp.length; i++) { + let tPart = tmp[i].id.split(":"); + let part = ""; + if (tPart.length == 3) part = tPart[2]; + if (part == "un" || part == "pw") tmp[i].disabled = false; + } + }, + }); + btn.removeEventListener("click", updatePasswords); +} +function grabPasswords(evt) { + let btn = evt.currentTarget; + $.ajax({ + type: "GET", + url: "/scripts/ajax.php", + data: "get=passwords&website_id=" + btn.value, + dataType: "JSON", + statusCode: { + 444: function () { + console.log("cant find data"); + }, + 500: function () { + console.log("PHP code error"); + }, + 401: function () { + document.location = "/logout.php"; + }, + }, + success: function (response) { + document.getElementById("mainWebsiteTitle").innerText = btn.innerText; + document.getElementById("mainWebsiteTitle").name = btn.name; + document.getElementById("mainWebsiteLink").href = btn.name; + let mainUserButtons = $("#mainUserButtons"); + mainUserButtons.empty(); + + let refBtn = document.createElement("button"); + refBtn.id = "refreshBtn"; + refBtn.name = btn.value; + refBtn.classList.add("name"); + refBtn.innerText = "Refresh"; + refBtn.addEventListener("click", refreshPassword); + mainUserButtons.append(refBtn); + if(typeof response !== 'undefined'){ + document.getElementById("passwordUsername").value = ""; + document.getElementById("passwordUsername").name = "password_id:"; + document.getElementById("passwordPassword").value = ""; + document.getElementById("passwordPassword").name = "password_id:"; + for (let i = 0; i < response.length; i++) { + let tmpButton = document.createElement("button"); + tmpName = "password_id:" + response[i]["password_id"]; + tmpButton.id = tmpName; + tmpButton.innerText = response[i]["username"]; + tmpButton.addEventListener("click",function (){ + + document.getElementById("passwordUsername").value = response[i]["username"]; + document.getElementById("passwordUsername").name = tmpName; + document.getElementById("passwordPassword").value = response[i]["password"]; + document.getElementById("passwordPassword").name = tmpName; + let editBtn = document.getElementById("passwordEdit"); + let deleteBtn = document.getElementById("passwordDelete"); + editBtn.value = response[i]["password_id"]; + deleteBtn.value = response[i]["password_id"]; + editBtn.name = tmpName; + deleteBtn.name = tmpName; + editBtn.addEventListener("click", editPasswords); + deleteBtn.addEventListener("click", deletePasswords); + }); + mainUserButtons.append(tmpButton); + } + } else { + console.log("No data"); + } + let addBtn = document.createElement("button"); + addBtn.id = btn.value + ":btn"; + addBtn.name = btn.value; + addBtn.classList.add("name"); + addBtn.innerText = "Add"; + addBtn.addEventListener("click", addPassword); + mainUserButtons.append(addBtn); + }, + }); +} +$(document).ready(function () { + listWebsites($("#list")); + $("#refresh").click(function (e) { + e.preventDefault(); + listWebsites($("#list")); + }); +}); diff --git a/public_html/scripts/main2.js b/public_html/scripts/main2.js new file mode 100644 index 0000000..4996e02 --- /dev/null +++ b/public_html/scripts/main2.js @@ -0,0 +1,407 @@ +"use strict";//forces strict js + +// @type {array} +var websites = []; +var passwords = []; +var currentWebsite = {"website_id":0}; +var currentPasswordId = 0; + +const getRandomID = (length) => { + let text = ''; + const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + do + { + for (let i = 0; i < length; i++){ + text += possible.charAt(Math.floor(Math.random() * possible.length)); + } + } + while (document.getElementById(text) != null); + return text; +} + +/** + * This is the on ready function + */ +$(function () { + displayWebsites(); + $("#mainAddImport").on("click", function () { + makeOverlayWebsite(); + + }); + $("#passwordEdit").on("click", function () { + editPasswords(); + }); + $("#passwordDelete").on("click", function () { + deletePasswords(); + }); +}); +function refresh(){ + displayWebsites(true); +} +function statusUpdate(title,status){ + let titleTextNode = document.createTextNode("Function: "+title); + let statusTextNode = document.createTextNode("Stauts: "+status); + $("#status").append(titleTextNode,statusTextNode); +} +/** + * This function will grab the website list + * @param {function} callFunc - This is a function called once function has been updated + */ +function grabWebsites(callFunc) { + //$("#status").text("Requesting Websites");// tells user it is requesting website + statusUpdate("grabWebsite","Requesting Websites") + $.ajax({ + type: "GET", + url: "/scripts/ajax.php", + data: { + get:"websites" + }, + dataType: "JSON", + success: function (data,textstatus,jqxhr) { + if(textstatus == "success"){ // checks if success + $("#status").text("Success: Websites");// tells user it is requesting website + websites = data;//sets global variable to list websites + if((data.length > 0) && (typeof callFunc == "function")){ + callFunc(); + } + } + } + }); +} +/** + * This function genorates html and displays buttons of websits in #list + * @param {boolean} forceUpdate - Forces an update of website list + */ +function displayWebsites(forceUpdate) { + if((websites.length == 0)||((typeof forceUpdate == "boolean")&&(forceUpdate))){ + grabWebsites(displayWebsites); + }else{ + let w = websites; + let list = $("#list"); + list.empty(); + for (let i = 0; i < w.length;i++){ + let websiteBtn = document.createElement("button"); + websiteBtn.addEventListener("click",function (){ + currentWebsite = w[i]; + displayAccounts(w[i]["website_id"],true); + }); + websiteBtn.innerText = w[i]["website_name"];// grabs website name + websiteBtn.name = w[i]["web_address"];// grabs website address, css displays this under name + let deleteBtn = document.createElement("a"); + deleteBtn.style="float:right;display:block;"; + deleteBtn.addEventListener("click",function () { + if(confirm("Delete website:\nName:\t\t\""+w[i]["website_name"]+"\"\nAddress:\t\""+w[i]["website_address"]+"\"")) + deleteWebsite(w[i]["website_id"]); + }); + deleteBtn.innerText = "🗑️"; + websiteBtn.appendChild(deleteBtn); + list.append(websiteBtn); + if(((i == 0)&&(currentWebsite["website_id"] == 0))||(currentWebsite["website_id"] == w[i]["website_id"])){ + websiteBtn.click(); + } + } + } +} +/** + * This function grabs the passwords from database + * @param {*} websiteId + * @param {*} callFunc + */ +function grabPasswords(websiteId,callFunc){ + statusUpdate("grabPasswords","Requesting Password") + $.ajax({ + type: "GET", + url: "/scripts/ajax.php", + data: { + get:"passwords", + website_id:websiteId + }, + dataType: "JSON", + success: function (data,textstatus,jqxhr) { + if(textstatus == "success"){ // checks if success + data = data.sort((a,b)=> { + var a1 = a["username"].toLowerCase(); + var b1 = b["username"].toLowerCase(); + return a1 b1? 1 :0; + }); + $("#status").text("Success: Passwords");// tells user it is requesting website + passwords = data;//sets global variable to list websites + if(typeof callFunc == "function"){ + callFunc(); + } + } + } + }); +} +/** + * This function genortes buttons for account of websites + * @param {*} websiteId + * @param {*} forceUpdate + */ +function displayAccounts(websiteId,forceUpdate) { + editPasswords(true);//resets edit button + $("#passwordUsername").val(""); + $("#passwordPassword").val(""); + let list = $("#accounts"); + $("#mainWebsiteTitle").text(currentWebsite["website_name"]); + list.empty(); + if(((typeof forceUpdate == "boolean")&&(forceUpdate))){ + grabPasswords(websiteId,displayAccounts); + }else{ + let p = passwords; + for (let i = 0; i < p.length;i++){ + let accountbtn = document.createElement("button"); + accountbtn.addEventListener("click",function (){ + currentPasswordId = p[i]["password_id"]; + displayPassword(p[i]["password_id"]); + }); + accountbtn.innerText = p[i]["username"];// grabs website name + list.append(accountbtn); + if(((i == 0)&&((typeof currentPasswordId == "number")&&(currentPasswordId == 0)))||(currentPasswordId == p[i]["password_id"])){ + accountbtn.click(); + } + } + } +} +/** + * This function genorates and displays buttons of websits in #list + * @param {boolean} forceUpdate - Forces an update of website list + */ +function displayPassword(passwordId) { + let p = passwords; + editPasswords(true);//resets edit button + for (let i = 0; i < p.length;i++){ + if(p[i]["password_id"] == passwordId){ + $("#passwordUsername").val( p[i]["username"]); + $("#passwordPassword").val( p[i]["password"]); + } + } +} +//done, tested +function editPasswords(reset = false) +{ + if(reset){ + $("#passwordUsername").attr("disabled","true"); + $("#passwordPassword").attr("disabled","true"); + $("#passwordEdit").text("Edit"); + }else if(currentPasswordId != 0) { + if($("#passwordEdit").text().toLowerCase() == "edit"){ + $("#passwordUsername").removeAttr("disabled"); + $("#passwordPassword").removeAttr("disabled"); + $("#passwordEdit").text("Save"); + } + else if($("#passwordEdit").text().toLowerCase() == "save"){ + $.ajax({ + type: "POST", + url: "/scripts/ajax.php", + data: { + update: "password", + password_id: currentPasswordId, + username: $("#passwordUsername").val(), + password: $("#passwordPassword").val() + }, + dataType: "JSON", + statusCode: { + 444: function () { + console.log("cant find data"); + }, + 500: function () { + console.log("PHP code error"); + }, + 401: function () { + document.location = "/logout.php"; + }, + }, + success: function (response) { + if(response["success"] == 1){ + $("#passwordUsername").attr("disabled","true"); + $("#passwordPassword").attr("disabled","true"); + $("#passwordEdit").text("Edit"); + } + }, + }); + }else{ + $("#passwordUsername").attr("disabled","true"); + $("#passwordPassword").attr("disabled","true"); + $("#passwordEdit").text("Edit"); + } + } +} +function makeOverlayPassword(){ + let website_id = currentWebsite["website_id"]; + let overlay = document.createElement("div"); + overlay.classList.add("overlay"); + overlay.id = "mkPwOverlay"; + let span = document.createElement("span"); + span.innerText = "Add a new password to"+currentWebsite["website_name"]+":"; + let pwUsername = document.createElement("input"); + pwUsername.type = "text"; + pwUsername.placeholder = "Username"; + pwUsername.name = "pwUsername"; + pwUsername.id = overlay.id+">username"; + let pwPassword = document.createElement("input"); + pwPassword.type = "password"; + pwPassword.placeholder = "Password"; + pwPassword.name = "pwPassword"; + pwUsername.id = overlay.id+">password"; + let wbAddBtn = document.createElement("input"); + wbAddBtn.type = "button"; + wbAddBtn.value = "Add Password"; + wbAddBtn.addEventListener("click", function (){ + addPasswords(website_id,pwUsername.value,pwPassword.value); + document.getElementById("mkPwOverlay").remove(); + + }); + let wbCancBtn = document.createElement("input"); + wbCancBtn.type = "button"; + wbCancBtn.value = "Cancel"; + wbCancBtn.name = "pwCancBtn"; + wbCancBtn.addEventListener("click", function () { + document.getElementById("mkPwOverlay").remove(); + }); + let btnHolder = document.createElement("div"); + btnHolder.classList.add("btn"); + btnHolder.appendChild(wbCancBtn); + btnHolder.appendChild(wbAddBtn); + overlay.appendChild(span); + overlay.appendChild(pwUsername); + overlay.appendChild(pwPassword); + overlay.appendChild(btnHolder); + document.body.appendChild(overlay); +} + +function makeOverlayWebsite(){ + let overlay = document.createElement("div"); + overlay.classList.add("overlay"); + overlay.id = "mkWbOverlay"; + let span = document.createElement("span"); + span.innerText = "Add a new website:"; + let wbName = document.createElement("input"); + wbName.type = "text"; + wbName.placeholder = "Name"; + wbName.name = "wbName"; + wbName.id = overlay.id+">username"; + let wbAddress = document.createElement("input"); + wbAddress.type = "text"; + wbAddress.placeholder = "Address"; + wbAddress.name = "wbAddress"; + wbName.id = overlay.id+">password"; + let wbAddBtn = document.createElement("input"); + wbAddBtn.type = "button"; + wbAddBtn.value = "Add Password"; + wbAddBtn.addEventListener("click", function (){ + addWebsite(wbName.value,wbAddress.value); + document.getElementById("mkWbOverlay").remove(); + }); + let wbCancBtn = document.createElement("input"); + wbCancBtn.type = "button"; + wbCancBtn.value = "Cancel"; + wbCancBtn.name = "pwCancBtn"; + wbCancBtn.addEventListener("click", function () { + document.getElementById("mkWbOverlay").remove(); + }); + let btnHolder = document.createElement("div"); + btnHolder.classList.add("btn"); + btnHolder.appendChild(wbCancBtn); + btnHolder.appendChild(wbAddBtn); + overlay.appendChild(span); + overlay.appendChild(wbName); + overlay.appendChild(wbAddress); + overlay.appendChild(btnHolder); + document.body.appendChild(overlay); +} +function addWebsite(name,address){ + $.post( + "/scripts/ajax.php", + { + add: "website", + website_name: name, + website_address: address + }, + function (data, textStatus, jqXHR) { + if (data["result"] == 1) + displayWebsites(true); + }, + "json" + ); +} +function addPasswords(website_id,username,password){ + $.post( + "/scripts/ajax.php", + { + add: "password", + website_id: website_id, + username: username, + password: password + }, + function (data, textStatus, jqXHR) { + if (data["result"] == 1) + displayWebsites(true); + }, + "json" + ); +} +//done, notTested +function deletePasswords(){ + $.ajax({ + type: "POST", + url: "/scripts/ajax.php", + data: { + delete: "password", + password_id: currentPasswordId + }, + dataType: "JSON", + statusCode: { + 444: function () { + console.log("cant find data"); + }, + 500: function () { + console.log("PHP code error"); + }, + 401: function () { + document.location = "/logout.php"; + }, + }, + success: function (response) { + if(response["success"] == 1) + { + $("#passwordUsername").removeAttr("disabled"); + $("#passwordPassword").removeAttr("disabled"); + displayAccounts(currentWebsite["website_id"],true); + } + + } + }); +} +function deleteWebsite(website_id){ + $.ajax({ + type: "POST", + url: "/scripts/ajax.php", + data: { + delete: "website", + website_id: website_id + }, + dataType: "JSON", + statusCode: { + 444: function () { + console.log("cant find data"); + }, + 500: function () { + console.log("PHP code error"); + }, + 401: function () { + document.location = "/logout.php"; + }, + }, + success: function (response) { + if(response["success"] == 1) + { + $("#passwordUsername").removeAttr("disabled"); + $("#passwordPassword").removeAttr("disabled"); + displayAccounts(currentWebsite["website_id"],true); + displayWebsites(true); + } + + } + }); +} \ No newline at end of file diff --git a/public_html/scripts/manageAccount.php b/public_html/scripts/manageAccount.php new file mode 100644 index 0000000..5e94075 --- /dev/null +++ b/public_html/scripts/manageAccount.php @@ -0,0 +1,119 @@ + "passman.harrysy.red"]); +if (isset($_SESSION["user_id"])) { + if ($_POST["request"] == "all") { + $sql = "SELECT `first_name`, `last_name`, `username`, `email`, `dob`, `mobile` FROM `user` WHERE `user_id` = ? "; + $stmt = mysqli_stmt_init($conn); + mysqli_stmt_prepare($stmt, $sql); + mysqli_stmt_bind_param($stmt, "i", $_SESSION["user_id"]); + mysqli_stmt_execute($stmt); + $result = mysqli_stmt_get_result($stmt); + $result = mysqli_fetch_assoc($result); + if ($result == null) { + http_response_code(404); + die("No Data"); + } else { + echo json_encode($result); + exit(); + } + } elseif ($_POST["request"] == "update") { + $pD = array_map('htmlentities', $_POST); + if (!emptyFields($pD)) { + echo json_encode(array("result" => "error", "error" => "ef")); + exit(); + } + $sql = "UPDATE `user` SET `first_name` = ?, `last_name` = ?, `username` =?,`email` = ?, `dob` = ?, `mobile` = ? WHERE `user_id` = ?"; + $stmt = mysqli_stmt_init($conn); + mysqli_stmt_prepare($stmt, $sql); + mysqli_stmt_bind_param($stmt, "ssssssi", $pD["first_name"], $pD["last_name"], $pD["username"], $pD["email"], $pD["dob"], $pD["mobile"], $_SESSION["user_id"]); + if (mysqli_stmt_execute($stmt)) { + echo json_encode(array("result" => "success")); + exit(); + } else { + echo json_encode(array("result" => "error")); + exit(); + } + } elseif ($_POST["request"] == "delete") { + $sql = "DELETE FROM `user` WHERE `user_id` = ?"; + $stmt = mysqli_stmt_init($conn); + mysqli_stmt_prepare($stmt, $sql); + mysqli_stmt_bind_param($stmt, "s", $_SESSION["user_id"]); + if (mysqli_stmt_execute($stmt)) { + echo json_encode(array("result" => "success")); + exit(); + } else { + echo json_encode(array("result" => "error")); + exit(); + } + } elseif ($_POST["request"] == "getSettings") { + $result = getSettings($conn); + if ($result != false) { + if ($result["dark_mode"] == 1) { + $result["dark_mode"] = "on"; + } else { + $result["dark_mode"] = "off"; + } + echo json_encode($result); + exit(); + } else { + $sql = "INSERT INTO `user_preference` (`user_id`) VALUES(?)"; + $stmt = mysqli_stmt_init($conn); + mysqli_stmt_prepare($stmt, $sql); + mysqli_stmt_bind_param($stmt, "i", $_SESSION["user_id"]); + mysqli_stmt_execute($stmt); + $result = getSettings($conn); + if ($result["dark_mode"] == 1) { + $result["dark_mode"] = "on"; + } else { + $result["dark_mode"] = "off"; + } + json_encode($result); + exit(); + } + } elseif ($_POST["request"] == "updateSettings") { + $pD = array_map('htmlentities', $_POST); + if (!emptyFields($pD)) { + echo json_encode(array("result" => "error", "error" => "ef")); + exit(); + } + if ($pD["dark_mode"] == "on") { + $pD["dark_mode"] = 1; + } else { + $pD["dark_mode"] = 0; + } + $sql = "UPDATE `user_preference` SET `dark_mode` = ?, `preferred_language` = ?, `colour_scheme` = ? WHERE `user_id` = ?"; + $stmt = mysqli_stmt_init($conn); + mysqli_stmt_prepare($stmt, $sql); + mysqli_stmt_bind_param($stmt, "issi", $pD["dark_mode"], $pD["preferred_language"], $pD["colour_scheme"], $_SESSION["user_id"]); + if (mysqli_stmt_execute($stmt)) { + echo json_encode(array("result" => "success")); + exit(); + } else { + echo json_encode(array("result" => mysqli_stmt_error($stmt))); + exit(); + } + } else { + echo json_encode(array("result" => "error", "error" => "selection not understood")); + exit(); + } +} else { + echo json_encode("error1"); +} + + +function getSettings($conn) +{ + $sql = "SELECT `dark_mode`, `preferred_language`, `colour_scheme` FROM `user_preference` WHERE `user_id` = ?"; + $stmt = mysqli_stmt_init($conn); + mysqli_stmt_prepare($stmt, $sql); + mysqli_stmt_bind_param($stmt, "s", $_SESSION["user_id"]); + mysqli_stmt_execute($stmt); + $stmtresult = mysqli_stmt_get_result($stmt); + if ($row = mysqli_fetch_assoc($stmtresult)) { + return $row; + } else { + return false; + } +} diff --git a/public_html/scripts/otp.php b/public_html/scripts/otp.php new file mode 100644 index 0000000..0536777 --- /dev/null +++ b/public_html/scripts/otp.php @@ -0,0 +1,60 @@ + "passman.harrysy.red"]); +require "db.php"; +if (isset($_SESSION["tempID"]) and !isset($_SESSION["user_id"]) and isset($_POST["otp_submit"])) { //makes sure the user is not already logged in and post data has been recieved + $sql = "SELECT * FROM otp WHERE user_id = ? AND otp = ?"; //Queries the database if there is a otp entry for the submited otp and if it is linked to the user ID of the user logging in + $stmt = mysqli_stmt_init($conn); + mysqli_stmt_prepare($stmt, $sql); + mysqli_stmt_bind_param($stmt, "is", $_SESSION["tempID"], $_POST["otp"]); + mysqli_stmt_execute($stmt); + $result = mysqli_stmt_get_result($stmt); + $resulta = mysqli_fetch_assoc($result); + if (mysqli_num_rows($result) == 0) { //if no results returned is assumed to be inccorect + header("location:../otp.php?error=otpIncorrect"); + exit(); + } else { + if ((time() - $resulta["otp_created"]) <= 1200) { //only allows the otp if it is less than 20 mins long + $_SESSION["user_id"] = $_SESSION["tempID"]; + unset($_SESSION["tempID"]); + header("location:../index.php?login=success"); + exit(); + } else { + session_unset(); + session_destroy(); + header("location:../login.php?error=otpExpired"); + exit(); + } + } +} elseif (isset($_POST["location"]) && $_POST["location"] == "extension") { + $sql = "SELECT * FROM otp WHERE otp = ?"; //Queries the database if there is a otp entry for the submited otp and if it is linked to the user ID of the user logging in + $stmt = mysqli_stmt_init($conn); + mysqli_stmt_prepare($stmt, $sql); + mysqli_stmt_bind_param($stmt, "s", $_POST["otp"]); + mysqli_stmt_execute($stmt); + $result = mysqli_stmt_get_result($stmt); + $resulta = mysqli_fetch_assoc($result); + mysqli_stmt_close($stmt); + if (mysqli_num_rows($result) == 0) { //if no results returned is assumed to be inccorect + response("error", "otpIncorrect"); + } else { + if ((time() - $resulta["otp_created"]) <= 1200) { //only allows the otp if it is less than 20 mins long + $authToken = bin2hex(openssl_random_pseudo_bytes(20)); + $sql = "INSERT INTO auth_token (user_id, auth_token) VALUES (?,?)"; + $stmt = mysqli_stmt_init($conn); + mysqli_stmt_prepare($stmt, $sql); + mysqli_stmt_bind_param($stmt, "is", $resulta["user_id"], $authToken); + mysqli_stmt_execute($stmt); + response("success", $authToken); + } else { + response("error", "otpExpired"); + } + } +} else { + header("location:../index.php?error=loginError"); + exit(); +} +function response($response, $error = "none") +{ + $return = array("response" => $response, "error" => $error); + echo json_encode($return); + exit(); +} diff --git a/public_html/scripts/pwd/mysql.php b/public_html/scripts/pwd/mysql.php new file mode 100644 index 0000000..8a4665e --- /dev/null +++ b/public_html/scripts/pwd/mysql.php @@ -0,0 +1,13 @@ + + + + + Passman Verificaiton Code + + + +

Passman Verification Code

+ Hello $name, here is your verification code to login to your PassMan account: +
+ + $code + + + This code was requested from $device + +
+ This code will expire in 20 minutes.
+ + +

Keeping your account and passwords safe

+ We use verification codes to make sure that only you can log onto your account and access your passwords.
+ Never share this code with anyone even with the PassMan team. + +

What if I didn't request this code

+ If you didn't request this code then your password is comprimized, if it is please navigate to 'PassMan [dot] harrysy [dot] red', login and change your password. + +

+ Keeping your passwords secure,
+ PassMan team +

+ + \ No newline at end of file diff --git a/public_html/scripts/userInfo.js b/public_html/scripts/userInfo.js new file mode 100644 index 0000000..9ebcdbe --- /dev/null +++ b/public_html/scripts/userInfo.js @@ -0,0 +1,14 @@ +$(document).ready(function () { + $.ajax({ + type: "POST", + url: "scripts/userInfo.php", + dataType: "json", + success: function (response) { + setName(response); + }, + }); +}); + +function setName(info) { + $("#name").html("Hello " + info["first_name"]); +} diff --git a/public_html/scripts/userInfo.php b/public_html/scripts/userInfo.php new file mode 100644 index 0000000..cdf4f7e --- /dev/null +++ b/public_html/scripts/userInfo.php @@ -0,0 +1,15 @@ + "passman.harrysy.red"]); +require_once "db.php"; +if (isset($_SESSION["user_id"])) { + $sql = "SELECT first_name, last_name FROM user WHERE user_id = ?"; + $stmt = mysqli_stmt_init($conn); + mysqli_stmt_prepare($stmt, $sql); + mysqli_stmt_bind_param($stmt, "i", $_SESSION["user_id"]); + mysqli_stmt_execute($stmt); + $rows = mysqli_stmt_get_result($stmt); + $rows = mysqli_fetch_assoc($rows); + echo json_encode($rows); +} else { + http_response_code(403); + die('Forbidden'); +} diff --git a/public_html/settings.php b/public_html/settings.php new file mode 100644 index 0000000..45953b2 --- /dev/null +++ b/public_html/settings.php @@ -0,0 +1,29 @@ + + +

Settings

+
+ + + + + + + +
+
+

+
\ No newline at end of file diff --git a/public_html/signup.php b/public_html/signup.php new file mode 100644 index 0000000..3312e6b --- /dev/null +++ b/public_html/signup.php @@ -0,0 +1,37 @@ + + + + + + + PassMan + + +
+
+ +
+ +
+ +
+ + +
+ + + + + + + + +
+ +
+

+
+
+
\ No newline at end of file diff --git a/public_html/styles/cssOskar.css b/public_html/styles/cssOskar.css new file mode 100644 index 0000000..795088c --- /dev/null +++ b/public_html/styles/cssOskar.css @@ -0,0 +1,326 @@ +/* HEADER */ + +* { + margin: 0; + box-sizing: border-box; + font-family: sans-serif; +} + +.navbar { + width: 100%; + height: 100px; + text-align: center; + padding: 30px; + background-color: #092834; + color: white; + display: flex; + justify-content: space-between; +} + +.navar h1 { + position: absolute; + left: 50%; +} + +.navbar h3, +.navbar img { + float: right; + padding: 10px; + display: inline; +} + +.navbar img { + border-radius: 50%; + height: 50px; + width: 50px; + align-self: center; +} + +.section2 { + display: flex; +} + +.section2 h3 { + align-self: center; +} + +h1 > span { + color: #ffb570; +} + +/* FOOTER */ + +footer { + display: flex; + justify-content: space-evenly; + background-color: #092834; + position: absolute; + bottom: 0; + width: 100%; + height: 4rem; + margin-top: 100px; +} +footer a { + text-decoration: none; + color: white; +} + +/* CONTACT */ + +#message { + height: 100px; +} + +.contactTeamTitle, +.contactFName { + margin-top: 20px; +} + +.contactTeamMemeber1 img, +.contactTeamMemeber3 img { + float: left; + height: 130px; + width: 130px; +} + +#contactMainSection2 { + background-color: #092834; + color: white; + flex: 8; +} + +.contactTeamTitle { + font-size: 30px; + text-align: center; +} + +.contactTeamMembers { + display: flex; + flex-direction: column; + justify-content: space-evenly; + text-align: center; + width: 80%; + font-size: 20px; + margin: auto; + margin-top: 20px; +} + +.contactTeamMemeber1, +.contactTeamMemeber2, +.contactTeamMemeber3 { + margin: 20px; +} + +.contactTeamMemeber2 img { + float: right; + height: 130px; + width: 130px; +} + +.contactPage, +.mainPage, +.main { + background-color: #f7f4d4; +} + +#contactMainPage { + background-color: white; + font-size: 30px; + text-align: center; +} + +/* MAIN */ + +.mainPage { + height: 100%; + width: 80%; + margin: auto; + border-radius: 5px; +} + +.mainBody { + display: flex; + flex-direction: row; + margin-top: 5vh; + height: 65vh; +} + +.verticalLine { + width: 20px; + background-color: white; + float: 0.4; +} + +.mainSection1, +.mainSection2 { + flex: 10; + color: black; +} + +#mainSection2 { + display: flex; + flex-direction: row; + justify-content: space-evenly; +} + +.mainUserName { + flex: 0.7; + background-color: white; +} + +.mainUserDetails { + flex: 2; + padding: 10px; + border: solid; + text-align: center; + font-size: 25px; +} + +.mainUserDetails input { + padding: 20px; +} + +.mainUserDetailsButtons { + display: flex; + flex-direction: row; + margin: auto; + width: 40vh; +} + +.editButton { + background-color: green; +} + +.deleteButton { + background-color: red; +} + +.mainUserName button { + width: 100%; + margin: auto; +} + +.mainSection1Title, +.mainSection2Title { + text-align: center; + margin: 20px; + margin-bottom: 35px; + font-size: 40px; +} + +.mainUserName, +.mainUserDetails { + border: 3px solid black; +} + +.mainSection2 { + background-color: #ccffff; +} + +.name { + height: 60px; +} + +#mainWebsiteSection { + display: flex; + flex-direction: column; + justify-content: space-evenly; +} + +.mainSearch { + border-radius: 25px; + width: 35%; + height: 9%; + margin: auto; +} + +.mainAddImport { + border-radius: 25px; + width: 25%; + height: 7%; + margin-left: 37%; + margin-top: 10px; + margin-bottom: 35px; +} + +.mainSection2 hr { + width: 100%; +} + +.websiteName { + background-color: #b0e3e6; + margin-bottom: 35px; +} + +.loadMoreButton { + background-color: #0050ef; + width: 40%; + margin: auto; + color: white; +} + +#addMainSection1, +#addMainSection2 { + background-color: #092834; + color: white; +} + +.addUpload2, +.addUpload { + width: 150px; + height: 60px; + margin: auto; +} + +/* INPUT LABEL BUTTON */ + +input, +label, +button { + text-align: center; + display: block; + width: 70%; + margin-left: 15%; + margin-right: 15%; + font-size: 25px; +} + +input { + height: 30px; + margin-bottom: 15px; +} + +/* Overlay For Add Website and Add Password*/ +.addTitle { + margin-bottom: 30px; +} +div.overlay { + display: block; + position: fixed; + background-color: #092834; + border-radius: 1rem; + border-width: 1rem; + top: calc(2rem + 100px); + left: 2rem; + right: 2rem; + height: fit-content; + padding: 2rem 0 2rem 0; +} +div.overlay input[type="button"] { + margin: auto; +} +div.overlay > span { + color: white; + font-size: 2rem; + text-align: center; + width: 100%; + display: block; +} +div.overlay > div.btn { + width: 100%; + display: flex; + flex-flow: row wrap; +} +div.overlay > div.btn > input { + width: fit-content; +} diff --git a/public_html/styles/oldStyle.css b/public_html/styles/oldStyle.css new file mode 100644 index 0000000..a4a0f74 --- /dev/null +++ b/public_html/styles/oldStyle.css @@ -0,0 +1,188 @@ +* { + padding: 0px; + margin: 0px; + font-family: sans-serif; +} + +#error { + color: red; + text-align: center; +} + +.containerMain { + height: 100vh; + background-color: #092834; + color: #fff; + display: flex; + flex-wrap: wrap; +} + +.containerMainLeft { + flex: 50%; + margin: auto; +} + +.containerMainRight { + flex: 50%; + display: block; + margin: auto; +} + +.containerMainRight form { + display: flex; + flex-direction: column; + align-items: center; + width: 50%; + margin: auto; +} + +input { + width: 80%; + padding: 10px 15px; + margin: 8px 0px; +} + +button { + cursor: pointer; + transition: transform 1s; + padding: 10px 50px 10px 50px; + background-color: lightskyblue; + color: white; + margin: 10px; +} + +button:hover { + transform: scale(1.1); +} + +button#bugSend { + color: black; + background: white; + transition: transform 1s; +} + +button#bugSend:hover { + transform: scale(0.5); +} + +.logo { + width: fit-content; + margin: auto; + font-size: 4.5rem; + text-align: center; +} + +.logo > span > span { + color: #ffb570; +} + +.vl { + border-left: 3px solid white; + border-right: 3px solid white; + height: 80%; + position: absolute; + left: 50%; + margin-left: -3px; + top: 10%; + bottom: 10%; +} + +.navbar { + background-color: 092834; +} + +#loginIcon { + width: 10%; + height: 10%; + display: flex; + flex-direction: column; + align-items: center; + margin: 10px auto; +} + +#CreateAccount { + font-size: 0.8rem; + align-items: center; + display: flex; + flex-direction: column; + align-items: center; + color: white; + margin: -5px 0px 10px 0px; +} + +#emailVerifi { + font-size: 1rem; + align-items: center; + display: flex; + flex-direction: column; + align-items: center; + color: white; + margin: auto; +} + +#NewBugReport { + font-size: 2.5rem; + padding: 15px; + +} + +.containerReportBug { + display: flex; + flex-direction: column; + align-items: center; + margin: auto; + background-color: white; + height: 80vh; +} + +.containerReportBug form { + background-color: #092834; + color: white; + padding: 20px; + display: flex; + flex-direction: column; + flex-wrap: wrap; + width: 50%; +} + +.containerReportBug form input { + width: 80%; + display: flex; + flex-direction: column; + align-items: center; + margin: auto; +} + +.containerReportBug form textarea { + height: 150px; + box-sizing: border-box; + font-size: 16px; + resize: none; + width: 80%; + display: flex; + flex-direction: column; + align-items: center; + margin: auto; + } + +a { + text-decoration: none; +} + + + +@media screen and (max-width: 600px) { + .vl { + transform: rotate(90deg); + height: 100vw; + } +} + +div.overlay{ + display: block; + position: fixed; + top: 2rem; + left: 2rem; + right: 2rem; + bottom: 2rem; +} \ No newline at end of file diff --git a/public_html/styles/styles.css b/public_html/styles/styles.css new file mode 100644 index 0000000..4cad2eb --- /dev/null +++ b/public_html/styles/styles.css @@ -0,0 +1,580 @@ +* { + padding: 0; + margin: 0; + font-family: sans-serif; + text-decoration: none; +} + +#error { + color: red; + text-align: center; +} + +.containerMain { + height: 100vh; + background-color: #092834; + color: #fff; + display: flex; + flex-wrap: wrap; +} + +.containerMainLeft { + flex: 50%; + margin: auto; +} + +.containerMainRight { + flex: 50%; + display: block; + margin: auto; +} + +.containerMainRight form { + display: flex; + flex-direction: column; + align-items: center; + width: 50%; + margin: auto; +} +/*Inline-Form*/ +.inline-form { + display: flex; + flex-flow: row wrap; + align-items: center; + flex-direction: column; +} +.inline-form input { + vertical-align: middle; + margin: 5px 10px 5px 0; + padding: 10px; + background-color: #fff; + border: 1px solid #ddd; + width: 80%; +} +.inline-form button { + vertical-align: middle; + margin: 5px 10px 5px 0; + padding: 10px; + background-color: #fff; + border: 1px solid #ddd; + cursor: pointer; + color: black; +} +.inline-form div { + display: flex; + flex-flow: row wrap; + align-items: center; + flex-direction: column; +} +.inline-form select { + vertical-align: middle; + margin: 5px 10px 5px 0; + padding: 10px; + background-color: #fff; + border: 1px solid #ddd; + width: 80%; +} +/*Inline-Form*/ + +input { + width: 80%; + padding: 10px 15px; + margin: 8px 0; +} + +button { + cursor: pointer; + transition: transform 1s; + padding: 10px 50px; + background-color: lightskyblue; + color: white; + margin: 10px; +} + +button:hover { + transform: scale(1.1); +} + +button#bugSend { + color: black; + background: white; + transition: transform 1s; +} + +button#bugSend:hover { + transform: scale(0.5); +} + +.logo { + width: fit-content; + margin: auto; + font-size: 4.5rem; + text-align: center; +} + +.logo > span > span { + color: #ffb570; +} + +.vl { + border-left: 3px solid white; + border-right: 3px solid white; + height: 80%; + position: absolute; + left: 50%; + margin-left: -3px; + top: 10%; + bottom: 10%; +} + +.navbar { + background-color: #092834; +} + +.navbar a h1 { + color: white; +} + +#loginIcon { + width: 10%; + height: 10%; + display: flex; + flex-direction: column; + align-items: center; + margin: 10px auto; +} + +#CreateAccount { + font-size: 0.8rem; + align-items: center; + display: flex; + flex-direction: column; + align-items: center; + color: white; + margin: -5px 0 10px; +} + +#emailVerifi { + font-size: 1rem; + align-items: center; + display: flex; + flex-direction: column; + align-items: center; + color: white; + margin: auto; +} + +#NewBugReport { + font-size: 2.5rem; + padding: 15px; +} + +.containerReportBug { + display: flex; + flex-direction: column; + align-items: center; + margin: auto; + background-color: white; + height: 80vh; +} + +.containerReportBug form { + background-color: #092834; + color: white; + padding: 20px; + display: flex; + flex-direction: column; + flex-wrap: wrap; + width: 50%; +} + +.containerReportBug form input { + width: 80%; + display: flex; + flex-direction: column; + align-items: center; + margin: auto; +} + +.containerReportBug form textarea { + height: 150px; + box-sizing: border-box; + font-size: 16px; + resize: none; + width: 80%; + display: flex; + flex-direction: column; + align-items: center; + margin: auto; +} + +a { + text-decoration: none; +} + +@media screen and (max-width: 600px) { + .vl { + transform: rotate(90deg); + height: 100vw; + } +} + +div.overlay { + display: block; + position: fixed; + top: 2rem; + left: 2rem; + right: 2rem; + bottom: 2rem; + display: block; + position: fixed; + background-color: #092834; + border-radius: 1rem; + border-width: 1rem; + top: calc(2rem + 100px); + left: 2rem; + right: 2rem; + height: fit-content; + padding: 2rem 0; +} + +* { + margin: 0; + box-sizing: border-box; + font-family: sans-serif; +} + +.navbar { + width: 100%; + height: 100px; + text-align: center; + padding: 30px; + background-color: #092834; + color: white; + display: flex; + justify-content: space-between; +} + +.navar h1 { + position: absolute; + left: 50%; +} + +.navbar h3, +.navbar img { + float: right; + padding: 10px; + display: inline; +} + +.navbar img { + border-radius: 50%; + height: 50px; + width: 50px; + align-self: center; +} + +.section2 { + display: flex; + position: relative; +} +.section2 a { + border-color: grey; + padding: 0.5em; + border-style: solid; + border-width: 1px; +} +.section2 a:hover { + background-color: #092834; + color: white; +} +.accountDrop { + display: none; + position: absolute; + background-color: #f1f1f1; + min-width: 160px; + box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2); + z-index: 1; + left: 0; + top: 100%; + width: 100%; + flex-direction: column; + flex-wrap: nowrap; +} +.section2 h3 { + align-self: center; +} + +.menuContainer { + min-height: 65vh; +} + +#passwords { + text-align: center; +} + +h1 > span { + color: #ffb570; +} + +footer { + display: flex; + justify-content: space-evenly; + background-color: #092834; + bottom: 0; + width: 100%; + height: 4rem; + margin-top: 100px; +} + +footer a { + text-decoration: none; + color: white; +} + +#message { + height: 100px; +} + +.contactTeamTitle, +.contactFName { + margin-top: 20px; +} + +.contactTeamMemeber1 img, +.contactTeamMemeber3 img { + float: left; + height: 130px; + width: 130px; +} + +#contactMainSection2 { + background-color: #092834; + color: white; + flex: 8; +} + +.contactTeamTitle { + font-size: 30px; + text-align: center; +} + +.contactTeamMembers { + display: flex; + flex-direction: column; + justify-content: space-evenly; + text-align: center; + width: 80%; + font-size: 20px; + margin: auto; + margin-top: 20px; +} + +.contactTeamMemeber1, +.contactTeamMemeber2, +.contactTeamMemeber3 { + margin: 20px; +} + +.contactTeamMemeber2 img { + float: right; + height: 130px; + width: 130px; +} + +.contactPage, +.mainPage, +.main { + background-color: #f7f4d4; +} + +#contactMainPage { + background-color: white; + font-size: 30px; + text-align: center; +} + +.mainPage { + min-height: 100%; + margin: auto; + border-radius: 5px; +} + +.mainBody { + display: flex; + flex-direction: column; +} + +.verticalLine { + width: 20px; + background-color: white; + float: 0.4; +} + +.mainSection1, +.mainSection2 { + flex: 10; + color: black; +} + +#mainSection2 { + display: flex; + flex-direction: column; + justify-content: space-evenly; +} + +.mainUserName { + flex: 0.7; + background-color: white; +} + +.mainUserDetails { + flex: 2; + padding: 10px; + border: solid; + text-align: center; + font-size: 25px; +} + +.mainUserDetails input { + padding: 20px; +} + +.mainUserDetailsButtons { + display: flex; + flex-direction: column; + margin: auto; + width: 40vh; + justify-content: space-around; +} +.editButton { + background-color: green; +} + +.deleteButton { + background-color: red; +} + +.mainUserName button { + width: 100%; + margin: auto; +} + +.mainSection1Title, +.mainSection2Title { + text-align: center; + margin: 20px; + margin-bottom: 35px; + font-size: 40px; +} + +.mainUserName, +.mainUserDetails { + border: 3px solid black; +} + +.mainSection2 { + background-color: #ccffff; +} + +.name { + height: 60px; +} + +#mainWebsiteSection { + display: flex; + flex-direction: column; + justify-content: space-evenly; +} + +.mainSearch { + border-radius: 25px; + width: 35%; + height: 9%; + margin: auto; +} + +.mainSection2 hr { + width: 100%; +} + +.websiteName { + background-color: #b0e3e6; + margin-bottom: 35px; +} + +.loadMoreButton { + background-color: #0050ef; + width: 40%; + margin: auto; + color: white; +} + +#addMainSection1, +#addMainSection2 { + background-color: #092834; + color: white; +} + +.addUpload2, +.addUpload { + width: 150px; + height: 60px; + margin: auto; +} + +input, +label, +button { + text-align: center; + display: block; + width: 70%; + margin-left: 15%; + margin-right: 15%; + font-size: 25px; +} + +input { + margin-bottom: 15px; +} + +.addTitle { + margin-bottom: 30px; +} + +div.overlay input[type="button"] { + margin: auto; +} + +div.overlay > span { + color: white; + font-size: 2rem; + text-align: center; + width: 100%; + display: block; +} + +div.overlay > div.btn { + width: 100%; + display: flex; + flex-flow: row wrap; +} + +div.overlay > div.btn > input { + width: fit-content; +} +.status { + position: fixed; + bottom: 0; + left: 0; + display: block; + background: #092834; + color: white; + border-color: #092834; + border-style: solid; + border-width: 0.5rem; + border-top-right-radius: 0.5rem; +} +.ad button { + background-color: red; +} diff --git a/public_html/test.php b/public_html/test.php new file mode 100644 index 0000000..7f2657e --- /dev/null +++ b/public_html/test.php @@ -0,0 +1,2 @@ +