using System; using System.IO; using System.Net; using System.Text; using System.Threading; using System.Windows.Forms; using System.Collections.Generic; using DPFP; using DPFP.Verification; using DPFP.Capture; public class DigitalPersonaServiceSimple : Form, DPFP.Capture.EventHandler { private static HttpListener httpListener; private static readonly int PORT = 8585; private static Dictionary UserTemplates = new Dictionary(); private static DPFP.Capture.Capture Capturer; private static Template capturedTemplate = null; private static bool isCapturing = false; private static string currentOperation = ""; public static void Main(string[] args) { Console.WriteLine("=== DigitalPersona Service Simple v1.0 ==="); Console.WriteLine("[INFO] Versión simplificada sin controles ActiveX"); // Configurar modo STA para compatibilidad con Windows Forms Application.SetCompatibleTextRenderingDefault(false); try { // Inicializar el capturador InitializeCapture(); // Cargar plantillas existentes LoadAllTemplates(); // Iniciar el servidor HTTP StartHttpServer(); Console.WriteLine("[INFO] Servidor HTTP activo en http://localhost:" + PORT); Console.WriteLine("[INFO] Servicio listo - http://localhost:" + PORT); // Ejecutar el loop de la aplicación Application.Run(); } catch (Exception ex) { Console.WriteLine("[ERROR] Error crítico: " + ex.Message); Console.WriteLine("[ERROR] Stack trace: " + ex.StackTrace); Console.ReadKey(); } } private static void InitializeCapture() { try { Capturer = new DPFP.Capture.Capture(); if (Capturer != null) { var handler = new DigitalPersonaServiceSimple(); Capturer.EventHandler = handler; Console.WriteLine("[INFO] Capturador inicializado correctamente"); } } catch (Exception ex) { Console.WriteLine("[ERROR] Error inicializando capturador: " + ex.Message); } } private static void StartHttpServer() { httpListener = new HttpListener(); httpListener.Prefixes.Add("http://localhost:" + PORT + "/"); httpListener.Start(); // Procesar requests en un thread separado Thread serverThread = new Thread(ProcessHttpRequests); serverThread.IsBackground = true; serverThread.Start(); } private static void ProcessHttpRequests() { while (httpListener.IsListening) { try { HttpListenerContext context = httpListener.GetContext(); ThreadPool.QueueUserWorkItem(o => HandleRequest((HttpListenerContext)o), context); } catch (Exception ex) { Console.WriteLine("[ERROR] Error procesando request: " + ex.Message); } } } private static void HandleRequest(HttpListenerContext context) { try { string path = context.Request.Url.AbsolutePath; string method = context.Request.HttpMethod; Console.WriteLine($"[REQUEST] {method} {path}"); string responseJson = ""; switch (path) { case "/enroll": responseJson = HandleEnroll(); break; case "/verify": responseJson = HandleVerify(); break; case "/status": responseJson = HandleStatus(); break; default: responseJson = "{\"success\":false,\"message\":\"Endpoint no encontrado\"}"; break; } // Enviar respuesta byte[] buffer = Encoding.UTF8.GetBytes(responseJson); context.Response.ContentLength64 = buffer.Length; context.Response.ContentType = "application/json"; context.Response.Headers.Add("Access-Control-Allow-Origin", "*"); context.Response.Headers.Add("Access-Control-Allow-Methods", "GET, POST, OPTIONS"); context.Response.Headers.Add("Access-Control-Allow-Headers", "Content-Type"); context.Response.OutputStream.Write(buffer, 0, buffer.Length); context.Response.Close(); } catch (Exception ex) { Console.WriteLine("[ERROR] Error manejando request: " + ex.Message); try { string errorResponse = "{\"success\":false,\"message\":\"Error interno del servidor\"}"; byte[] errorBuffer = Encoding.UTF8.GetBytes(errorResponse); context.Response.StatusCode = 500; context.Response.ContentLength64 = errorBuffer.Length; context.Response.ContentType = "application/json"; context.Response.OutputStream.Write(errorBuffer, 0, errorBuffer.Length); context.Response.Close(); } catch { } } } private static string HandleEnroll() { try { Console.WriteLine("[ENROLL] Iniciando proceso de registro"); currentOperation = "enroll"; isCapturing = true; capturedTemplate = null; // Mostrar mensaje simple en consola en lugar de ventana Console.WriteLine("[ENROLL] Coloque su dedo en el lector para registrar"); if (Capturer != null) { Capturer.StartCapture(); // Esperar por la captura (máximo 30 segundos) int timeout = 30000; // 30 segundos int elapsed = 0; int interval = 500; // 0.5 segundos while (isCapturing && elapsed < timeout) { Thread.Sleep(interval); elapsed += interval; Application.DoEvents(); // Procesar eventos de Windows } Capturer.StopCapture(); if (capturedTemplate != null) { // Generar ID único para el usuario string userId = DateTime.Now.Ticks.ToString(); // Guardar template SaveTemplate(userId, capturedTemplate); Console.WriteLine("[ENROLL] Huella registrada exitosamente para usuario: " + userId); return "{\"success\":true,\"message\":\"Huella registrada exitosamente\",\"userId\":\"" + userId + "\"}"; } else { Console.WriteLine("[ENROLL] Timeout o no se capturó huella"); return "{\"success\":false,\"message\":\"Timeout: No se capturó huella en 30 segundos\"}"; } } else { return "{\"success\":false,\"message\":\"Capturador no disponible\"}"; } } catch (Exception ex) { Console.WriteLine("[ENROLL] Error: " + ex.Message); return "{\"success\":false,\"message\":\"Error en registro: " + ex.Message.Replace("\"", "\\\"") + "\"}"; } finally { isCapturing = false; currentOperation = ""; } } private static string HandleVerify() { try { Console.WriteLine("[VERIFY] Iniciando proceso de verificación"); currentOperation = "verify"; isCapturing = true; capturedTemplate = null; // Mostrar mensaje en consola Console.WriteLine("[VERIFY] Coloque su dedo registrado en el lector"); if (Capturer != null) { Capturer.StartCapture(); // Esperar por la captura (máximo 30 segundos) int timeout = 30000; int elapsed = 0; int interval = 500; while (isCapturing && elapsed < timeout) { Thread.Sleep(interval); elapsed += interval; Application.DoEvents(); } Capturer.StopCapture(); if (capturedTemplate != null) { // Verificar contra todas las plantillas string matchedUserId = VerifyTemplate(capturedTemplate); if (!string.IsNullOrEmpty(matchedUserId)) { Console.WriteLine("[VERIFY] Huella verificada para usuario: " + matchedUserId); return "{\"success\":true,\"message\":\"Verificación exitosa\",\"userId\":\"" + matchedUserId + "\"}"; } else { Console.WriteLine("[VERIFY] Huella no reconocida"); return "{\"success\":false,\"message\":\"Huella no reconocida\"}"; } } else { Console.WriteLine("[VERIFY] Timeout o no se capturó huella"); return "{\"success\":false,\"message\":\"Timeout: No se capturó huella en 30 segundos\"}"; } } else { return "{\"success\":false,\"message\":\"Capturador no disponible\"}"; } } catch (Exception ex) { Console.WriteLine("[VERIFY] Error: " + ex.Message); return "{\"success\":false,\"message\":\"Error en verificación: " + ex.Message.Replace("\"", "\\\"") + "\"}"; } finally { isCapturing = false; currentOperation = ""; } } private static string HandleStatus() { int templateCount = UserTemplates.Count; bool captureReady = Capturer != null; return "{\"success\":true,\"message\":\"Servicio activo\"," + "\"templatesLoaded\":" + templateCount + "," + "\"captureReady\":" + (captureReady ? "true" : "false") + "," + "\"isCapturing\":" + (isCapturing ? "true" : "false") + "}"; } private static void SaveTemplate(string userId, Template template) { try { // Guardar en memoria UserTemplates[userId] = template; // Guardar archivo .fpt string fileName = "database/fingerprints/user_" + userId + ".fpt"; Directory.CreateDirectory(Path.GetDirectoryName(fileName)); using (FileStream fs = File.Create(fileName)) { template.Serialize(fs); } // Guardar como base64 using (MemoryStream ms = new MemoryStream()) { template.Serialize(ms); string base64 = Convert.ToBase64String(ms.ToArray()); File.WriteAllText("database/fingerprints/user_" + userId + "_base64.txt", base64); } Console.WriteLine("[SAVE] Template guardado: " + fileName); } catch (Exception ex) { Console.WriteLine("[SAVE] Error guardando template: " + ex.Message); } } private static void LoadAllTemplates() { try { string dir = "database/fingerprints"; if (Directory.Exists(dir)) { string[] files = Directory.GetFiles(dir, "*.fpt"); foreach (string file in files) { try { Template template = new Template(); using (FileStream fs = File.OpenRead(file)) { template.DeSerialize(fs); } string userId = Path.GetFileNameWithoutExtension(file).Replace("user_", ""); UserTemplates[userId] = template; Console.WriteLine("[LOAD] Template cargado: " + userId); } catch (Exception ex) { Console.WriteLine("[LOAD] Error cargando " + file + ": " + ex.Message); } } Console.WriteLine("[LOAD] Total templates cargados: " + UserTemplates.Count); } } catch (Exception ex) { Console.WriteLine("[LOAD] Error cargando templates: " + ex.Message); } } private static string VerifyTemplate(Template sample) { try { Verification.Verification Verificator = new Verification.Verification(); Verification.Verification.Result Result = new Verification.Verification.Result(); foreach (var kvp in UserTemplates) { Verificator.Verify(sample, kvp.Value, ref Result); if (Result.Verified) { Console.WriteLine("[VERIFY] Match encontrado para usuario " + kvp.Key + " (FAR: " + Result.FARAchieved + ")"); return kvp.Key; } } return null; } catch (Exception ex) { Console.WriteLine("[VERIFY] Error en verificación: " + ex.Message); return null; } } // Implementar EventHandler para captura public void OnComplete(object Capture, string ReaderSerialNumber, Sample Sample) { if (isCapturing) { try { // Procesar muestra DPFP.FeatureSet features = ExtractFeatures(Sample, DPFP.Processing.DataPurpose.Enrollment); if (features != null) { if (currentOperation == "enroll") { // Para enrollment, crear template directamente Template template = new Template(); template.DeSerialize(features.Bytes); capturedTemplate = template; isCapturing = false; Console.WriteLine("[CAPTURE] Huella capturada para enrollment"); } else if (currentOperation == "verify") { // Para verificación, crear template para comparar Template template = new Template(); template.DeSerialize(features.Bytes); capturedTemplate = template; isCapturing = false; Console.WriteLine("[CAPTURE] Huella capturada para verificación"); } } else { Console.WriteLine("[CAPTURE] Calidad de huella insuficiente, intente de nuevo"); } } catch (Exception ex) { Console.WriteLine("[CAPTURE] Error procesando muestra: " + ex.Message); } } } public void OnFingerGone(object Capture, string ReaderSerialNumber) { Console.WriteLine("[CAPTURE] Dedo retirado"); } public void OnFingerTouch(object Capture, string ReaderSerialNumber) { Console.WriteLine("[CAPTURE] Dedo detectado"); } public void OnReaderConnect(object Capture, string ReaderSerialNumber) { Console.WriteLine("[READER] Lector conectado: " + ReaderSerialNumber); } public void OnReaderDisconnect(object Capture, string ReaderSerialNumber) { Console.WriteLine("[READER] Lector desconectado: " + ReaderSerialNumber); } public void OnSampleQuality(object Capture, string ReaderSerialNumber, CaptureFeedback CaptureFeedback) { if (CaptureFeedback == DPFP.Capture.CaptureFeedback.Good) { Console.WriteLine("[QUALITY] Calidad de muestra: Buena"); } else { Console.WriteLine("[QUALITY] Calidad de muestra: " + CaptureFeedback.ToString()); } } private static DPFP.FeatureSet ExtractFeatures(Sample Sample, DPFP.Processing.DataPurpose Purpose) { try { DPFP.Processing.FeatureExtraction Extractor = new DPFP.Processing.FeatureExtraction(); DPFP.Capture.CaptureFeedback feedback = DPFP.Capture.CaptureFeedback.None; DPFP.FeatureSet features = new DPFP.FeatureSet(); Extractor.CreateFeatureSet(Sample, Purpose, ref feedback, ref features); if (feedback == DPFP.Capture.CaptureFeedback.Good) { return features; } else { return null; } } catch (Exception ex) { Console.WriteLine("[EXTRACT] Error extrayendo características: " + ex.Message); return null; } } }