using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Text.RegularExpressions; namespace HanvonF710XAttendanceService { internal sealed class HttpExchangeResult { public string Url { get; set; } public string Method { get; set; } = "POST"; public string RequestContentType { get; set; } public string RequestBodySanitized { get; set; } public int StatusCode { get; set; } public string ResponseHeaders { get; set; } public string ResponseBody { get; set; } public Dictionary ParsedResponse { get; set; } public string Error { get; set; } public bool IsHttpSuccess => StatusCode >= 200 && StatusCode < 300; } internal static class HanvonHttpDiagnostics { public static string SanitizeJsonBody(string json) { if (string.IsNullOrEmpty(json)) return json; string sanitized = Regex.Replace(json, "(\"password\"\\s*:\\s*\")([^\"]*)(\")", "$1***$3", RegexOptions.IgnoreCase); sanitized = Regex.Replace(sanitized, "(\"record\"\\s*:\\s*\")([^\"]{80})[^\"]*(\")", "$1$2...[truncated]$3", RegexOptions.IgnoreCase); sanitized = Regex.Replace(sanitized, "(\"face\"\\s*:\\s*\")([^\"]{80})[^\"]*(\")", "$1$2...[truncated]$3", RegexOptions.IgnoreCase); return sanitized; } public static string DescribeTemplatePayload(string payload, string pushMode) { if (string.IsNullOrWhiteSpace(payload)) return "empty"; string mode = pushMode ?? "unknown"; int len = payload.Length; string prefix = payload.Length > 24 ? payload.Substring(0, 24) : payload; try { byte[] decoded = Convert.FromBase64String(payload.Length > 256 ? payload.Substring(0, 256) : payload); if (decoded.Length >= 3) { return $"mode={mode} base64_len={len} decoded_prefix=0x{decoded[0]:X2}{decoded[1]:X2}{decoded[2]:X2} jpeg={(decoded[0] == 0xFF && decoded[1] == 0xD8)}"; } } catch { return $"mode={mode} base64_len={len} prefix={prefix} (not standard base64 JPEG header)"; } return $"mode={mode} base64_len={len} prefix={prefix}"; } public static void WriteExchange(TextWriter writer, string phase, string empId, HttpExchangeResult exchange) { writer.WriteLine($"[DB_TO_DEVICE] emp={empId} {phase}"); writer.WriteLine($"URL={exchange?.Url ?? "(null)"}"); writer.WriteLine($"HTTP={exchange?.StatusCode ?? 0}"); writer.WriteLine($"Method={exchange?.Method ?? "POST"}"); writer.WriteLine($"Content-Type={exchange?.RequestContentType ?? "(null)"}"); writer.WriteLine($"request={exchange?.RequestBodySanitized ?? "(null)"}"); if (!string.IsNullOrWhiteSpace(exchange?.ResponseHeaders)) { writer.WriteLine($"response_headers={exchange.ResponseHeaders}"); } writer.WriteLine($"response={exchange?.ResponseBody ?? exchange?.Error ?? "(null)"}"); } public static void WriteResultSummary( TextWriter writer, string empId, bool userExistsInList, string listId, string listName, string listFaceField, bool profileOk, string profileFaceFlag, string profilePhotoUrl, bool recordOk, int recordLen, string templateFormat) { writer.WriteLine($"[DB_TO_DEVICE] emp={empId} RESULT"); writer.WriteLine($"user_exists={(userExistsInList ? "true" : "false")} list_id={listId ?? ""} list_name={listName ?? ""} list_face={listFaceField ?? ""}"); writer.WriteLine($"profile_getuserinfo_ok={profileOk} faceflag={profileFaceFlag ?? ""} photourl={profilePhotoUrl ?? ""}"); writer.WriteLine($"face_exists={(recordOk ? "true" : "false")} backupnum_record_len={recordLen}"); writer.WriteLine($"template_format={templateFormat ?? ""}"); } } }