TrashNotes

2025-04-13 22:35:48
#ok #simple-chat 



% cat index.php 
<?php
// Начинаем сессию с усиленными настройками безопасности
session_start([
    'cookie_httponly' => true, // Защита от JavaScript-доступа к куки
    'cookie_secure' => isset($_SERVER['HTTPS']), // Куки передаются только по HTTPS
    'use_strict_mode' => true // Защита от подмены ID сессии
]);

// Генерация нового CSRF-токена, если его еще нет
if (!isset($_SESSION['csrf_token'])) {
    $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}

// Файл для хранения сообщений
$messageFile = 'messages.txt';

// Если имя пользователя не установлено в сессии, используем "Guest"
if (!isset($_SESSION['username'])) {
    $_SESSION['username'] = 'Guest';
}

// Получаем IP-адрес пользователя
$userIp = $_SERVER['REMOTE_ADDR'];

// Ограничение частоты отправки сообщений (минимальный интервал - 5 секунд)
if (isset($_SESSION['last_message_time'])) {
    $time_diff = time() - $_SESSION['last_message_time'];
    if ($time_diff < 1) { // Минимальный интервал между сообщениями (5 секунд)
        die('Please wait before sending another message.');
    }
}

// Проверяем, отправлена ли форма с новым сообщением
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    // Проверка CSRF-токена
    if (!isset($_POST['csrf_token']) || $_POST['csrf_token'] !== $_SESSION['csrf_token']) {
        die('Invalid CSRF token');
    }

    // Обновляем имя пользователя, если оно передано
    if (!empty($_POST['username'])) {
        $_SESSION['username'] = htmlspecialchars($_POST['username']);
    }

    // Если сообщение не пустое, добавляем его в файл
    if (!empty($_POST['message'])) {
        $newMessage = htmlspecialchars($_POST['message']); // Защита от XSS
        $username = $_SESSION['username']; // Имя пользователя из сессии
        $timestamp = date('Y-m-d H:i:s'); // Полная дата и время

        // Формируем строку сообщения в формате "Username@IP: message"
        $displayName = $username . '@' . $userIp;
        $messageLine = "[$timestamp]\n    $displayName: $newMessage" . PHP_EOL;

        // Добавляем сообщение в файл
        file_put_contents($messageFile, $messageLine, FILE_APPEND | LOCK_EX);

        // Сохраняем время последнего сообщения
        $_SESSION['last_message_time'] = time();
    }
}

// Читаем все сообщения из файла
$messages = file_exists($messageFile) ? file($messageFile, FILE_IGNORE_NEW_LINES) : [];

// Ограничиваем количество сообщений до 10 последних
$messages = array_slice($messages, -15);
?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Simple Chat</title>
    <!-- Link to styles -->
    <link rel="stylesheet" href="styles.css">
</head>
<body>
    <h1>Simple Chat</h1>

    <!-- Form for sending a new message -->
    <form method="POST" action="" style="margin-bottom: 20px;">
        <!-- CSRF-токен -->
        <input type="hidden" name="csrf_token" value="<?php echo htmlspecialchars($_SESSION['csrf_token']); ?>">

        <!-- label for="username">Name:</label -->
        <input type="text" id="username" name="username" value="<?php echo htmlspecialchars($_SESSION['username']); ?>" placeholder="Enter your name" required>
        
        <!-- label for="message">Message:</label -->
        <input type="text" id="message" name="message" placeholder="Enter your message" autofocus >

        <button type="submit">Send / Refresh</button>
    </form>

    <!-- Display messages -->
        <?php if (!empty($messages)): ?>
            <pre><?php echo htmlspecialchars(implode(PHP_EOL, $messages)); ?></pre>
        <?php else: ?>
            <p>No messages yet. Be the first to write one!</p>
        <?php endif; ?>
    <a href="http://ur4uqu.com/chat/messages.txt"; target="_blank">message-log</a>
</body>
</html>


####################

% cat styles.css 
/* Общие стили */
body {
  font-family: monospace;
  line-height: 1.6;
  margin: 0 auto;
  max-width: 90%;
  padding: 15px;
  background-color: #2c2c2c;
  color: #f0f0f0;
}

h1 {
  color: #ffffff;
  text-align: center;
  font-weight: 700;
}

/* Стиль для блока с сообщениями */
.chat-messages {
  font-family: monospace;
  white-space: pre-wrap; /* Перенос строк с сохранением пробелов */
  word-wrap: break-word; /* Разрыв длинных слов */
  background-color: #3a3a3a;
  color: #f0f0f0;
  padding: 10px;
  border-radius: 5px;
  overflow-y: hidden; /* Убираем скроллинг */
  line-height: 1.4; /* Убираем через-строчность */
}

code, pre {
  font-family: monospace;
  font-size: 15px;
  line-height: 1.5;
  letter-spacing: 0.01em;
  color: #c9c9c9; /* Более светлый цвет текста */
  background-color: #333333; /* Темный фон */
  padding: 8px;
  border-radius: 8px;
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); /* Небольшая тень */
  text-align: left;
  white-space: pre-wrap; 
  word-break: keep-all;
}


/* Стиль для полей ввода */
input[type="text"] {
  font-family: monospace;
  font-size: 18px;
  line-height: 1.6;
  color: #f0f0f0; /* Цвет текста, как и у body */
  background-color: #333333; /* Темный фон */
  border: 1px solid #555; /* Более темная граница */
  border-radius: 8px;
  padding: 10px;
  margin-bottom: 15px;
  width: 100%; /* Занимает всю ширину контейнера */
  box-sizing: border-box; /* Учитывает padding и border в ширине */
  transition: border-color 0.3s; /* Плавное изменение цвета границы */
}

input[type="text"]:focus {
  outline: none; /* Убираем стандартное выделение при фокусе */
  border-color: #1e90ff; /* Подсвечиваем границу при фокусе */
  box-shadow: 0 0 5px rgba(30, 144, 255, 0.5); /* Добавляем небольшую тень */
}

input[type="text"]::placeholder {
  color: #b0b0b0; /* Более светлый цвет для placeholder */
}

/* Стиль для кнопки */
button {
  background: linear-gradient(90deg, #4e73df 0%, #1c7ed6 100%);
  color: white;
  border: none;
  border-radius: 5px;
  padding: 10px 20px;
  font-size: 16px;
  cursor: pointer;
  transition: background 0.3s ease;
}

button:hover {
  background: linear-gradient(90deg, #1c7ed6 0%, #4e73df 100%);
}

/* Стиль для ссылок */
a {
  color: #ffa07a; /* Оранжевый цвет */
  text-decoration: none; /* Удаление подчеркивания */
}

a:hover {
  color: #ff9900; /* Темно-оранжевый цвет при наведении */
}
← Previous Next →
Back to list