busyTimeout(5000); } return $db; } // Obtener IPs de usuarios conectados function get_connected_ips() { $ch = curl_init(); curl_setopt_array($ch, [ CURLOPT_URL => EJABBERD_API_URL . '/connected_users_info', CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPAUTH => CURLAUTH_BASIC, CURLOPT_USERPWD => EJABBERD_USER . ':' . EJABBERD_PASSWORD, CURLOPT_HTTPHEADER => ['Content-Type: application/json'], CURLOPT_POST => true, CURLOPT_SSL_VERIFYPEER => false, CURLOPT_SSL_VERIFYHOST => 0, CURLOPT_POSTFIELDS => json_encode([]), CURLOPT_TIMEOUT => 5, CURLOPT_CONNECTTIMEOUT => 3 ]); $response = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); if (curl_errno($ch)) { error_log("CURL Error: " . curl_error($ch)); curl_close($ch); return []; } curl_close($ch); if ($httpCode !== 200) { error_log("Error en API ejabberd: HTTP $httpCode - $response"); return []; } $data = json_decode($response, true); if (!is_array($data)) { error_log("Respuesta inválida de API: " . $response); return []; } return $data; } // Convertir IP a número entero sin signo function ip_to_int($ip) { $ipLong = ip2long($ip); if ($ipLong === false) { return null; } return sprintf('%u', $ipLong); } // Buscar ubicación en la base de datos SQLite function ip_to_location($ip) { // Verificar caché $cache_file = IP_CACHE_DIR . '/' . md5($ip) . '.json'; if (file_exists($cache_file)) { $cache = json_decode(file_get_contents($cache_file), true); if ($cache && time() - $cache['timestamp'] < 86400) { return $cache; } } // Convertir IP $ip_num = ip_to_int($ip); if ($ip_num === null) { return null; } // Buscar en SQLite $db = get_ip_database(); $stmt = $db->prepare('SELECT country, city, region, lat, lon FROM ip_ranges WHERE :ip >= start AND :ip <= end LIMIT 1'); if (!$stmt) { error_log("Error preparando consulta: " . $db->lastErrorMsg()); return null; } $stmt->bindValue(':ip', $ip_num, SQLITE3_INTEGER); $result = $stmt->execute(); if (!$result) { error_log("Error ejecutando consulta: " . $db->lastErrorMsg()); return null; } $data = $result->fetchArray(SQLITE3_ASSOC); if ($data) { // Validar y convertir coordenadas $lat = is_numeric($data['lat']) ? (float)$data['lat'] : null; $lon = is_numeric($data['lon']) ? (float)$data['lon'] : null; // Si las coordenadas no son válidas, no retornar ubicación if ($lat === null || $lon === null) { error_log("Coordenadas inválidas para IP: $ip - Lat: {$data['lat']}, Lon: {$data['lon']}"); return null; } // Determinar el mejor nombre para la ubicación $locationName = $data['country']; if ($locationName === 'NA' || $locationName === 'EU' || empty($locationName)) { if (!empty($data['city']) && !empty($data['region'])) { $locationName = $data['city'] . ', ' . $data['region']; } elseif (!empty($data['city'])) { $locationName = $data['city']; } elseif (!empty($data['region'])) { $locationName = $data['region']; } else { $locationName = 'Desconocido'; } } $location = [ 'ip' => $ip, 'country' => $locationName, 'lat' => $lat, 'lon' => $lon, 'timestamp' => time() ]; // Guardar en caché file_put_contents($cache_file, json_encode($location)); return $location; } else { error_log("No se encontró ubicación para IP: $ip ($ip_num)"); } return null; } ?>