From da3d35fbf3942337936e791bcbf24892986d3cf2 Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Sat, 22 Nov 2025 12:04:14 +0000 Subject: [PATCH] v1 --- admin.php | 102 +++++++ api.php | 168 +++++++++++ assets/css/custom.css | 67 +++++ assets/js/main.js | 119 ++++++++ change_password.php | 87 ++++++ db/add_friend_system.php | 64 +++++ db/create_messages_table.php | 19 ++ db/setup.php | 47 +++ index.php | 544 ++++++++++++++++++++++++++--------- login.php | 57 ++++ logout.php | 7 + 11 files changed, 1139 insertions(+), 142 deletions(-) create mode 100644 admin.php create mode 100644 api.php create mode 100644 assets/css/custom.css create mode 100644 assets/js/main.js create mode 100644 change_password.php create mode 100644 db/add_friend_system.php create mode 100644 db/create_messages_table.php create mode 100644 db/setup.php create mode 100644 login.php create mode 100644 logout.php diff --git a/admin.php b/admin.php new file mode 100644 index 0000000..7b8b009 --- /dev/null +++ b/admin.php @@ -0,0 +1,102 @@ +prepare('SELECT id FROM users WHERE username = ?'); + $stmt->execute([$username]); + if ($stmt->fetch()) { + $message = '

Username already exists.

'; + } else { + $hashed_password = password_hash($password, PASSWORD_DEFAULT); + $stmt = $pdo->prepare('INSERT INTO users (username, password, force_password_change) VALUES (?, ?, 1)'); + if ($stmt->execute([$username, $hashed_password])) { + $message = '

User added successfully!

'; + } else { + $message = '

Failed to add user.

'; + } + } + } else { + $message = '

Username and password are required.

'; + } +} + +// Fetch all users to display +$stmt = $pdo->query('SELECT id, username, is_admin, created_at FROM users ORDER BY created_at DESC'); +$users = $stmt->fetchAll(); + +?> + + + + + + Admin Panel + + + +
+ +

Admin Panel

+ +
+ +

Add New User

+
+ + + +
+ +

Manage Users

+ + + + + + + + + + + + + + + + + + + +
IDUsernameRoleCreated At
+
+ + diff --git a/api.php b/api.php new file mode 100644 index 0000000..e708d2d --- /dev/null +++ b/api.php @@ -0,0 +1,168 @@ + 'Unauthorized']); + exit; +} + +$action = $_GET['action'] ?? ''; +$current_user_id = $_SESSION['user_id']; + +try { + $pdo = db(); + switch ($action) { + case 'get_my_unique_id': + $stmt = $pdo->prepare("SELECT unique_id FROM users WHERE id = ?"); + $stmt->execute([$current_user_id]); + $user = $stmt->fetch(PDO::FETCH_ASSOC); + echo json_encode($user); + break; + + case 'search_users': + $query = $_GET['query'] ?? ''; + $stmt = $pdo->prepare("SELECT id, username, unique_id FROM users WHERE unique_id LIKE ? AND id != ?"); + $stmt->execute(["%$query%", $current_user_id]); + $users = $stmt->fetchAll(PDO::FETCH_ASSOC); + echo json_encode($users); + break; + + case 'send_friend_request': + $data = json_decode(file_get_contents('php://input'), true); + $user_to_add_id = (int)($data['user_id'] ?? 0); + + if ($user_to_add_id === 0) { + echo json_encode(['error' => 'Invalid user ID']); + exit; + } + + // Check if a request already exists + $stmt = $pdo->prepare("SELECT id FROM friends WHERE (user_one_id = ? AND user_two_id = ?) OR (user_one_id = ? AND user_two_id = ?)"); + $stmt->execute([$current_user_id, $user_to_add_id, $user_to_add_id, $current_user_id]); + if ($stmt->fetch()) { + echo json_encode(['error' => 'Friend request already sent or you are already friends.']); + exit; + } + + $stmt = $pdo->prepare("INSERT INTO friends (user_one_id, user_two_id, status, action_user_id) VALUES (?, ?, 'pending', ?)"); + $stmt->execute([$current_user_id, $user_to_add_id, $current_user_id]); + + echo json_encode(['success' => true, 'message' => 'Friend request sent.']); + break; + + case 'get_friend_requests': + $stmt = $pdo->prepare(" + SELECT f.id, u.username, u.unique_id + FROM friends f + JOIN users u ON f.action_user_id = u.id + WHERE f.user_two_id = ? AND f.status = 'pending' AND f.action_user_id != ? + "); + $stmt->execute([$current_user_id, $current_user_id]); + $requests = $stmt->fetchAll(PDO::FETCH_ASSOC); + echo json_encode($requests); + break; + + case 'update_friend_request': + $data = json_decode(file_get_contents('php://input'), true); + $request_id = (int)($data['request_id'] ?? 0); + $status = $data['status'] ?? ''; // 'accepted' or 'declined' + + if ($request_id === 0 || !in_array($status, ['accepted', 'declined'])) { + echo json_encode(['error' => 'Invalid input']); + exit; + } + + if ($status === 'accepted') { + $stmt = $pdo->prepare("UPDATE friends SET status = 'accepted' WHERE id = ? AND user_two_id = ?"); + $stmt->execute([$request_id, $current_user_id]); + } else { // declined + $stmt = $pdo->prepare("DELETE FROM friends WHERE id = ? AND user_two_id = ?"); + $stmt->execute([$request_id, $current_user_id]); + } + + echo json_encode(['success' => true, 'message' => 'Friend request ' . $status]); + break; + + case 'get_friends': + $stmt = $pdo->prepare(" + SELECT u.id, u.username + FROM friends f + JOIN users u ON (u.id = f.user_one_id OR u.id = f.user_two_id) + WHERE (f.user_one_id = ? OR f.user_two_id = ?) + AND f.status = 'accepted' + AND u.id != ? + "); + $stmt->execute([$current_user_id, $current_user_id, $current_user_id]); + $friends = $stmt->fetchAll(PDO::FETCH_ASSOC); + echo json_encode($friends); + break; + + case 'get_messages': + $recipient_id = (int)($_GET['user_id'] ?? 0); + if ($recipient_id === 0) { + echo json_encode(['error' => 'Invalid user ID']); + exit; + } + $stmt = $pdo->prepare("SELECT * FROM messages WHERE (sender_id = ? AND recipient_id = ?) OR (sender_id = ? AND recipient_id = ?) ORDER BY created_at ASC"); + $stmt->execute([$current_user_id, $recipient_id, $recipient_id, $current_user_id]); + $messages = $stmt->fetchAll(PDO::FETCH_ASSOC); + echo json_encode($messages); + break; + + case 'send_message': + $recipient_id = (int)($_POST['recipient_id'] ?? 0); + $message = trim($_POST['message'] ?? ''); + $image_url = null; + + if ($recipient_id === 0) { + echo json_encode(['error' => 'Invalid recipient ID']); + exit; + } + + if (isset($_FILES['image']) && $_FILES['image']['error'] == UPLOAD_ERR_OK) { + $upload_dir = __DIR__ . '/uploads/'; + if (!is_dir($upload_dir)) { + mkdir($upload_dir, 0775, true); + } + + $allowed_types = ['image/jpeg', 'image/png', 'image/gif']; + $file_type = mime_content_type($_FILES['image']['tmp_name']); + if (!in_array($file_type, $allowed_types)) { + echo json_encode(['error' => 'Invalid file type. Only JPG, PNG, and GIF are allowed.']); + exit; + } + + $file_ext = pathinfo($_FILES['image']['name'], PATHINFO_EXTENSION); + $file_name = uniqid() . '.' . $file_ext; + $upload_path = $upload_dir . $file_name; + + if (move_uploaded_file($_FILES['image']['tmp_name'], $upload_path)) { + $image_url = 'uploads/' . $file_name; + } else { + echo json_encode(['error' => 'Failed to upload image.']); + exit; + } + } + + if (empty($message) && !$image_url) { + echo json_encode(['error' => 'Message cannot be empty.']); + exit; + } + + $stmt = $pdo->prepare("INSERT INTO messages (sender_id, recipient_id, message, image_url) VALUES (?, ?, ?, ?)"); + $stmt->execute([$current_user_id, $recipient_id, $message, $image_url]); + + echo json_encode(['success' => true, 'message' => 'Message sent']); + break; + + default: + echo json_encode(['error' => 'Invalid action']); + break; + } +} catch (PDOException $e) { + http_response_code(500); + echo json_encode(['error' => 'Database error: ' . $e->getMessage()]); +} \ No newline at end of file diff --git a/assets/css/custom.css b/assets/css/custom.css new file mode 100644 index 0000000..ec1cd20 --- /dev/null +++ b/assets/css/custom.css @@ -0,0 +1,67 @@ + +body, html { + height: 100%; + margin: 0; + display: flex; + justify-content: center; + align-items: center; + background-color: #f8f9fa; +} + +.calculator { + width: 320px; + border: 1px solid #ccc; + border-radius: 10px; + box-shadow: 0 0 20px rgba(0,0,0,0.1); + background: #fff; +} + +.calculator-screen { + width: 100%; + height: 80px; + border: none; + background-color: #222; + color: #fff; + text-align: right; + padding-right: 20px; + padding-left: 10px; + font-size: 2.5rem; + border-top-left-radius: 10px; + border-top-right-radius: 10px; +} + +.calculator-keys { + display: grid; + grid-template-columns: repeat(4, 1fr); + gap: 1px; +} + +.btn { + height: 60px; + font-size: 1.5rem; + border: 1px solid #ccc; + background-color: #f2f2f2; +} + +.operator { + background-color: #f9a825; + color: white; +} + +.equal-sign { + grid-column: span 2; + background-color: #28a745; + color: white; +} + +.all-clear { + background-color: #dc3545; + color: white; +} + +#chat-container { + width: 100%; + height: 100%; + display: flex; + flex-direction: column; +} diff --git a/assets/js/main.js b/assets/js/main.js new file mode 100644 index 0000000..91f993c --- /dev/null +++ b/assets/js/main.js @@ -0,0 +1,119 @@ + +document.addEventListener('DOMContentLoaded', () => { + const calculator = document.querySelector('.calculator'); + const screen = document.querySelector('.calculator-screen'); + const keys = document.querySelector('.calculator-keys'); + const chatContainer = document.getElementById('chat-container'); + + let displayValue = '0'; + let firstOperand = null; + let operator = null; + let waitingForSecondOperand = false; + + function updateDisplay() { + screen.value = displayValue; + } + + updateDisplay(); + + keys.addEventListener('click', (e) => { + const { target } = e; + const { value } = target; + + if (!target.matches('button')) { + return; + } + + switch (value) { + case '+': + case '-': + case '*': + case '/': + handleOperator(value); + break; + case '=': + handleEqualSign(); + break; + case '.': + inputDecimal(value); + break; + case 'all-clear': + resetCalculator(); + break; + default: + if (Number.isInteger(parseInt(value))) { + inputDigit(value); + } + } + + updateDisplay(); + }); + + function handleOperator(nextOperator) { + const inputValue = parseFloat(displayValue); + + if (operator && waitingForSecondOperand) { + operator = nextOperator; + return; + } + + if (firstOperand === null && !isNaN(inputValue)) { + firstOperand = inputValue; + } else if (operator) { + const result = calculate(firstOperand, inputValue, operator); + displayValue = `${parseFloat(result.toFixed(7))}`; + firstOperand = result; + } + + waitingForSecondOperand = true; + operator = nextOperator; + } + + function handleEqualSign() { + if (screen.value === '1+1') { + calculator.style.display = 'none'; + chatContainer.style.display = 'block'; + return; + } + + const inputValue = parseFloat(displayValue); + if (operator && !waitingForSecondOperand) { + const result = calculate(firstOperand, inputValue, operator); + displayValue = `${parseFloat(result.toFixed(7))}`; + firstOperand = null; + operator = null; + waitingForSecondOperand = false; + } + } + + function calculate(first, second, op) { + if (op === '+') return first + second; + if (op === '-') return first - second; + if (op === '*') return first * second; + if (op === '/') return first / second; + return second; + } + + function inputDigit(digit) { + if (waitingForSecondOperand) { + displayValue = digit; + waitingForSecondOperand = false; + } else { + displayValue = displayValue === '0' ? digit : displayValue + digit; + } + } + + function inputDecimal(dot) { + if (waitingForSecondOperand) return; + if (!displayValue.includes(dot)) { + displayValue += dot; + } + } + + function resetCalculator() { + displayValue = '0'; + firstOperand = null; + operator = null; + waitingForSecondOperand = false; + } +}); diff --git a/change_password.php b/change_password.php new file mode 100644 index 0000000..44e199f --- /dev/null +++ b/change_password.php @@ -0,0 +1,87 @@ +prepare("UPDATE users SET password = :password, force_password_change = 0 WHERE id = :id"); + $stmt->execute([ + ':password' => $hashed_password, + ':id' => $_SESSION['user_id'] + ]); + $_SESSION['force_password_change'] = 0; + $success = "Password changed successfully. You will be redirected to the main page in 3 seconds."; + header("refresh:3;url=index.php"); + } catch (PDOException $e) { + $error = "Database error: " . $e->getMessage(); + } + } +} +?> + + + + + + Change Password + + + +
+
+

Change Your Password

+

As a new user, you must change your password.

+ +

+ + +

+ +
+
+ + +
+
+ + +
+ +
+ +
+
+ + \ No newline at end of file diff --git a/db/add_friend_system.php b/db/add_friend_system.php new file mode 100644 index 0000000..97f295f --- /dev/null +++ b/db/add_friend_system.php @@ -0,0 +1,64 @@ +query("SHOW COLUMNS FROM users LIKE 'unique_id'"); + $exists = $stmt->fetch(PDO::FETCH_ASSOC); + + if ($exists) { + // Drop the unique key if it exists + try { + $pdo->exec("ALTER TABLE users DROP KEY unique_id"); + } catch (PDOException $e) { + // Ignore error if the key doesn't exist + } + // Drop the column + $pdo->exec("ALTER TABLE users DROP COLUMN unique_id"); + echo "Dropped existing unique_id column.\n"; + } + + // Add unique_id column to users table + $pdo->exec("ALTER TABLE users ADD COLUMN unique_id VARCHAR(16) NOT NULL AFTER id"); + echo "Added unique_id column to users table.\n"; + + // Populate unique_id for existing users + $stmt = $pdo->query("SELECT id FROM users"); + $users = $stmt->fetchAll(PDO::FETCH_ASSOC); + + $updateStmt = $pdo->prepare("UPDATE users SET unique_id = ? WHERE id = ?"); + + foreach ($users as $user) { + $unique_id = substr(md5(uniqid(rand(), true)), 0, 8); + $updateStmt->execute([$unique_id, $user['id']]); + } + echo "Populated unique_id for existing users.\n"; + + // Add unique constraint + $pdo->exec("ALTER TABLE users ADD UNIQUE (unique_id)"); + echo "Added unique constraint to unique_id column.\n"; + + + // Create friends table + $pdo->exec(" + CREATE TABLE IF NOT EXISTS friends ( + id INT AUTO_INCREMENT PRIMARY KEY, + user_one_id INT NOT NULL, + user_two_id INT NOT NULL, + status ENUM('pending', 'accepted', 'declined', 'blocked') NOT NULL, + action_user_id INT NOT NULL, + FOREIGN KEY (user_one_id) REFERENCES users(id), + FOREIGN KEY (user_two_id) REFERENCES users(id), + FOREIGN KEY (action_user_id) REFERENCES users(id), + UNIQUE KEY unique_friendship (user_one_id, user_two_id) + ) + "); + echo "Created friends table.\n"; + + echo "Friend system database setup complete!\n"; + +} catch (PDOException $e) { + die("Database error: " . $e->getMessage()); +} \ No newline at end of file diff --git a/db/create_messages_table.php b/db/create_messages_table.php new file mode 100644 index 0000000..9df9333 --- /dev/null +++ b/db/create_messages_table.php @@ -0,0 +1,19 @@ +exec($sql); + echo "INFO: `messages` table created or already exists."; +} catch (PDOException $e) { + die("ERROR: Could not connect to the database: " . $e->getMessage()); +} diff --git a/db/setup.php b/db/setup.php new file mode 100644 index 0000000..abfaaaa --- /dev/null +++ b/db/setup.php @@ -0,0 +1,47 @@ +setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + + $sql = " + CREATE TABLE IF NOT EXISTS users ( + id INT AUTO_INCREMENT PRIMARY KEY, + username VARCHAR(50) NOT NULL UNIQUE, + password VARCHAR(255) NOT NULL, + is_admin BOOLEAN NOT NULL DEFAULT 0, + force_password_change BOOLEAN NOT NULL DEFAULT 1, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP + ); + "; + + $pdo->exec($sql); + echo "Table 'users' created successfully." . PHP_EOL; + + // Add admin user + $username = 'admin'; + $password = 'admin'; + $hashed_password = password_hash($password, PASSWORD_DEFAULT); + + // Check if admin user already exists + $stmt = $pdo->prepare("SELECT * FROM users WHERE username = :username"); + $stmt->execute([':username' => $username]); + $user = $stmt->fetch(); + + if (!$user) { + $stmt = $pdo->prepare("INSERT INTO users (username, password, is_admin, force_password_change) VALUES (:username, :password, 1, 1)"); + $stmt->execute([ + ':username' => $username, + ':password' => $hashed_password + ]); + echo "Admin user created successfully." . PHP_EOL; + } else { + echo "Admin user already exists." . PHP_EOL; + } + + +} catch(PDOException $e) { + die("ERROR: Could not connect. " . $e->getMessage()); +} diff --git a/index.php b/index.php index 7205f3d..52b0662 100644 --- a/index.php +++ b/index.php @@ -1,150 +1,410 @@ - + - - - New Style - - - - - - - - - - - - - - - - - - - + + + Secure Messenger - Alpha Version + -
-
-

Analyzing your requirements and generating your website…

-
- Loading… -
-

AI is collecting your requirements and applying the first changes.

-

This page will update automatically as the plan is implemented.

-

Runtime: PHP — UTC

+
+
+

Secure Messenger

+

Alpha Version -

+
+
+
+ +
+ +
+
+

Select a friend to chat

+
+ + Admin | + + Logout +
+
+
+
+

Welcome, !

+

Select a friend from the list to start a conversation.

+
+
+ +
+
+ + + +
+
-
- + + - + \ No newline at end of file diff --git a/login.php b/login.php new file mode 100644 index 0000000..e2dbaed --- /dev/null +++ b/login.php @@ -0,0 +1,57 @@ +prepare("SELECT * FROM users WHERE username = :username"); + $stmt->execute([':username' => $username]); + $user = $stmt->fetch(); + + if ($user && password_verify($password, $user['password'])) { + // For admin user, ensure force_password_change is always off + if ($user['username'] === 'admin' && $user['force_password_change']) { + $updateStmt = $pdo->prepare("UPDATE users SET force_password_change = 0 WHERE id = :id"); + $updateStmt->execute([':id' => $user['id']]); + $user['force_password_change'] = 0; // Update the local variable as well + } + + $_SESSION['user_id'] = $user['id']; + $_SESSION['username'] = $user['username']; + $_SESSION['is_admin'] = $user['is_admin']; + + // This session variable is no longer strictly needed but left for compatibility + $_SESSION['force_password_change'] = $user['force_password_change']; + + if ($user['force_password_change']) { + header("Location: change_password.php"); + } else { + header("Location: index.php"); + } + exit; + } else { + $_SESSION['login_error'] = "Invalid username or password."; + header('Location: index.php'); + exit; + } +} catch (PDOException $e) { + error_log("Database error in login.php: " . $e->getMessage()); + $_SESSION['login_error'] = "A database error occurred. Please try again later."; + header('Location: index.php'); + exit; +} +?> \ No newline at end of file diff --git a/logout.php b/logout.php new file mode 100644 index 0000000..3a0a043 --- /dev/null +++ b/logout.php @@ -0,0 +1,7 @@ + \ No newline at end of file