db_host = $config['dbhost']; $this->db_user = $config['dbuser']; $this->db_pass = $config['dbpass']; $this->db_dbase = $config['dbname']; $this->db_prefix = $config['dbpref']; $this->sess_lifetime = (defined('SESSION_LIFETIME') && is_numeric(SESSION_LIFETIME)) ? (int)SESSION_LIFETIME : (get_cfg_var("session.gc_maxlifetime") < 1440 ? 1440 : (int)get_cfg_var("session.gc_maxlifetime")); $this->connect(); } private function connect(): void { $this->mysql_connect = new mysqli($this->db_host, $this->db_user, $this->db_pass, $this->db_dbase); if ($this->mysql_connect->connect_error) { $this->error(); } $this->mysql_connect->set_charset('utf8'); } private function ensureConnection(): bool { if (!($this->mysql_connect instanceof mysqli) || !$this->mysql_connect->ping()) { $this->connect(); if (!$this->mysql_connect || $this->mysql_connect->connect_error) { return false; } } return true; } public function __destruct() { if ($this->mysql_connect instanceof mysqli) { $this->mysql_connect->close(); $this->mysql_connect = null; } } public function _open(string $path, string $name): bool { return true; } public function _close(): bool { if (!$this->ensureConnection()) { return false; } $sql = "DELETE FROM " . $this->db_prefix . "_sessions WHERE expiry < ?"; $stmt = $this->mysql_connect->prepare($sql); if (!$stmt) { error_log("Prepare failed in _close: " . $this->mysql_connect->error); return false; } $now = time(); $stmt->bind_param('i', $now); $stmt->execute(); $stmt->close(); // Соединение не закрываем! return true; } public function _read(string $ses_id): string { if (!$this->ensureConnection()) { return ''; } $sql = "SELECT value, Ip FROM " . $this->db_prefix . "_sessions WHERE sesskey = ? AND expiry > ?"; $stmt = $this->mysql_connect->prepare($sql); if (!$stmt) { error_log("Prepare failed in _read: " . $this->mysql_connect->error); return ''; } $now = time(); $stmt->bind_param('si', $ses_id, $now); $stmt->execute(); $stmt->bind_result($value, $ip); $result = ''; if ($stmt->fetch() && $ip === ($_SERVER['REMOTE_ADDR'] ?? '')) { $result = $value; } $stmt->close(); return $result; } public function _write(string $ses_id, string $data): bool { if (!$this->ensureConnection()) { return false; } $expiry = time() + $this->sess_lifetime; $remoteAddr = $_SERVER['REMOTE_ADDR'] ?? ''; $sql = "INSERT INTO " . $this->db_prefix . "_sessions (sesskey, expiry, value, Ip, expire_datum) VALUES (?, ?, ?, ?, FROM_UNIXTIME(?,'%d.%m.%Y, %H:%i:%s')) ON DUPLICATE KEY UPDATE expiry = VALUES(expiry), value = VALUES(value), Ip = VALUES(Ip), expire_datum = VALUES(expire_datum)"; $stmt = $this->mysql_connect->prepare($sql); if (!$stmt) { error_log("Prepare failed in _write: " . $this->mysql_connect->error); return false; } $stmt->bind_param('sisss', $ses_id, $expiry, $data, $remoteAddr, $expiry); $result = $stmt->execute(); if (!$result) { error_log("Execute failed in _write: " . $stmt->error); } $stmt->close(); return $result; } public function _destroy(string $ses_id): bool { if (!$this->ensureConnection()) { return false; } $sql = "DELETE FROM " . $this->db_prefix . "_sessions WHERE sesskey = ?"; $stmt = $this->mysql_connect->prepare($sql); if (!$stmt) { error_log("Prepare failed in _destroy: " . $this->mysql_connect->error); return false; } $stmt->bind_param('s', $ses_id); $result = $stmt->execute(); if (!$result) { error_log("Execute failed in _destroy: " . $stmt->error); } $stmt->close(); return $result; } public function _gc(int $maxlifetime): bool { if (!$this->ensureConnection()) { return false; } $threshold = time() - $maxlifetime; $sql = "DELETE FROM " . $this->db_prefix . "_sessions WHERE expiry < ?"; $stmt = $this->mysql_connect->prepare($sql); if (!$stmt) { error_log("Prepare failed in _gc: " . $this->mysql_connect->error); return false; } $stmt->bind_param('i', $threshold); $result = $stmt->execute(); if (!$result) { error_log("Execute failed in _gc: " . $stmt->error); } $stmt->close(); return $result; } private function error(): void { ob_start(); header('HTTP/1.1 503 Service Temporarily Unavailable'); header('Status: 503 Service Temporarily Unavailable'); header('Retry-After: 3600'); header('X-Powered-By:'); echo "Error connect to MySQL."; die; } }