package org.openautonomousconnection.webserver.api; import org.openautonomousconnection.protocol.side.server.CustomConnectedClient; import org.openautonomousconnection.protocol.side.web.ProtocolWebServer; import org.openautonomousconnection.protocol.side.web.managers.SessionManager; import java.io.IOException; import java.util.Locale; import java.util.Map; /** * Provides session-related information for Java WebPages. * Reads session id primarily from Cookie header ("session=..."). */ public final class SessionContext { private static final String COOKIE_NAME = "session"; private final String sessionId; private final String user; private final boolean valid; private SessionContext(String sessionId, String user, boolean valid) { this.sessionId = sessionId; this.user = user; this.valid = valid; } /** * Creates a SessionContext from request headers (case-insensitive). * * @param client connected client * @param server web server * @param headers request headers * @return session context * @throws IOException on errors */ public static SessionContext from(CustomConnectedClient client, ProtocolWebServer server, Map headers) throws IOException { if (headers == null || headers.isEmpty()) return new SessionContext(null, null, false); String sessionId = extractSessionId(headers); if (sessionId == null || sessionId.isBlank()) return new SessionContext(null, null, false); String ip = (client != null && client.getConnection() != null && client.getConnection().getTcpSocket() != null && client.getConnection().getTcpSocket().getInetAddress() != null) ? client.getConnection().getTcpSocket().getInetAddress().getHostAddress() : ""; String userAgent = getHeaderIgnoreCase(headers, "user-agent"); if (userAgent == null) userAgent = ""; boolean valid = SessionManager.isValid(sessionId, ip, userAgent, server); if (!valid) return new SessionContext(sessionId, null, false); String user = SessionManager.getUser(sessionId); return new SessionContext(sessionId, user, true); } private static String extractSessionId(Map headers) { String cookie = getHeaderIgnoreCase(headers, "cookie"); String fromCookie = parseCookie(cookie, COOKIE_NAME); if (fromCookie != null && !fromCookie.isBlank()) return fromCookie; // Fallback String session = getHeaderIgnoreCase(headers, "session"); return (session == null || session.isBlank()) ? null : session.trim(); } private static String parseCookie(String cookieHeader, String name) { if (cookieHeader == null || cookieHeader.isBlank() || name == null || name.isBlank()) return null; String[] parts = cookieHeader.split(";"); for (String p : parts) { String t = p.trim(); int eq = t.indexOf('='); if (eq <= 0) continue; String k = t.substring(0, eq).trim(); if (!k.equalsIgnoreCase(name)) continue; String v = t.substring(eq + 1).trim(); return v.isEmpty() ? null : v; } return null; } private static String getHeaderIgnoreCase(Map headers, String key) { if (key == null) return null; String needle = key.trim().toLowerCase(Locale.ROOT); for (Map.Entry e : headers.entrySet()) { if (e.getKey() == null) continue; if (e.getKey().trim().toLowerCase(Locale.ROOT).equals(needle)) { return e.getValue(); } } return null; } /** * @return whether session is valid */ public boolean isValid() { return valid; } /** * @return session id */ public String getSessionId() { return sessionId; } /** * @return user id stored in session (string) */ public String getUser() { return user; } }