From 3a739eb9374f6fef0439c0288a859c1581498c1b Mon Sep 17 00:00:00 2001 From: Alain Date: Mon, 13 Oct 2025 04:47:26 -0500 Subject: [PATCH 1/4] disable sync is_archived --- core/Services/CalDAV/CalDAVClient.vala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/Services/CalDAV/CalDAVClient.vala b/core/Services/CalDAV/CalDAVClient.vala index 7ff90660a..a1128b0c5 100644 --- a/core/Services/CalDAV/CalDAVClient.vala +++ b/core/Services/CalDAV/CalDAVClient.vala @@ -344,7 +344,7 @@ public class Services.CalDAV.CalDAVClient : Services.CalDAV.WebDAVClient { } public async void sync_tasklist (Objects.Project project, GLib.Cancellable cancellable) throws GLib.Error { - if (project.is_deck) { + if (project.is_deck || project.is_archived) { return; } From 0a3338b79fa65e955dda4a7cd44608a0ba189f6f Mon Sep 17 00:00:00 2001 From: Alain Date: Mon, 13 Oct 2025 04:52:20 -0500 Subject: [PATCH 2/4] add logs --- core/Services/CalDAV/CalDAVClient.vala | 7 +++++ core/Services/CalDAV/Core.vala | 15 +++++++++-- core/Services/CalDAV/WebDAVClient.vala | 36 +++++++++++++++++++++++--- 3 files changed, 52 insertions(+), 6 deletions(-) diff --git a/core/Services/CalDAV/CalDAVClient.vala b/core/Services/CalDAV/CalDAVClient.vala index a1128b0c5..afa6b56db 100644 --- a/core/Services/CalDAV/CalDAVClient.vala +++ b/core/Services/CalDAV/CalDAVClient.vala @@ -344,7 +344,10 @@ public class Services.CalDAV.CalDAVClient : Services.CalDAV.WebDAVClient { } public async void sync_tasklist (Objects.Project project, GLib.Cancellable cancellable) throws GLib.Error { + debug ("[CalDAV] sync_tasklist called for: %s", project.name); + if (project.is_deck || project.is_archived) { + debug ("[CalDAV] Skipping project (is_deck: %s, is_archived: %s)", project.is_deck.to_string(), project.is_archived.to_string()); return; } @@ -362,14 +365,18 @@ public class Services.CalDAV.CalDAVClient : Services.CalDAV.WebDAVClient { project.loading = true; project.sync_started (); + debug ("[CalDAV] Fetching project details"); yield fetch_project_details (project, cancellable); if (project.sync_id == "") { + debug ("[CalDAV] Project has no sync_id, skipping sync"); project.loading = false; return; } + debug ("[CalDAV] Sending sync-collection report"); var multi_status = yield report (project.calendar_url, xml, "1", cancellable); + debug ("[CalDAV] Received %d responses", multi_status.responses().size); foreach (WebDAVResponse response in multi_status.responses ()) { string? href = response.href; diff --git a/core/Services/CalDAV/Core.vala b/core/Services/CalDAV/Core.vala index ff2d25887..2c52beff4 100644 --- a/core/Services/CalDAV/Core.vala +++ b/core/Services/CalDAV/Core.vala @@ -263,22 +263,33 @@ public class Services.CalDAV.Core : GLib.Object { public async void sync (Objects.Source source) { + debug ("[CalDAV] Starting sync for source: %s (type: %s)", source.display_name, source.source_type.to_string()); + debug ("[CalDAV] Server URL: %s", source.caldav_data.server_url); + debug ("[CalDAV] Username: %s", source.caldav_data.username); + debug ("[CalDAV] Password length: %d", source.caldav_data.password != null ? source.caldav_data.password.length : 0); + var caldav_client = get_client (source); source.sync_started (); try { var cancellable = new GLib.Cancellable (); + debug ("[CalDAV] Syncing source metadata"); yield caldav_client.sync (source, cancellable); - foreach (Objects.Project project in Services.Store.instance ().get_projects_by_source (source.id)) { + var projects = Services.Store.instance ().get_projects_by_source (source.id); + debug ("[CalDAV] Found %d projects to sync", projects.size); + + foreach (Objects.Project project in projects) { + debug ("[CalDAV] Syncing project: %s (url: %s, sync_id: %s)", project.name, project.calendar_url, project.sync_id); yield caldav_client.sync_tasklist (project, cancellable); } source.sync_finished (); source.last_sync = new GLib.DateTime.now_local ().to_string (); + debug ("[CalDAV] Sync completed successfully"); } catch (Error e) { - warning ("Failed to sync: %s", e.message); + warning ("[CalDAV] Sync failed: %s (code: %d)", e.message, e.code); source.sync_failed (); } } diff --git a/core/Services/CalDAV/WebDAVClient.vala b/core/Services/CalDAV/WebDAVClient.vala index 2005c8319..131cae706 100644 --- a/core/Services/CalDAV/WebDAVClient.vala +++ b/core/Services/CalDAV/WebDAVClient.vala @@ -66,20 +66,22 @@ public class Services.CalDAV.WebDAVClient : GLib.Object { if (abs_url == null) throw new GLib.IOError.FAILED ("Invalid URL: %s".printf (url)); + debug ("[CalDAV] %s request to: %s", method, abs_url); var msg = new Soup.Message (method, abs_url); msg.request_headers.append ("User-Agent", Constants.SOUP_USER_AGENT); msg.authenticate.connect ((auth, retrying) => { if (retrying) { - warning ("Authentication failed\n"); + warning ("[CalDAV] Authentication retry failed for user: %s", this.username); return false; } if (auth.scheme_name == "Digest" || auth.scheme_name == "Basic") { + debug ("[CalDAV] Authenticating with scheme: %s, username: %s, password length: %d", auth.scheme_name, this.username, this.password.length); auth.authenticate (this.username, this.password); return true; } - warning ("Unsupported auth schema: %s", auth.scheme_name); + warning ("[CalDAV] Unsupported auth schema: %s", auth.scheme_name); return false; }); @@ -113,10 +115,13 @@ public class Services.CalDAV.WebDAVClient : GLib.Object { GLib.Bytes response; try { response = yield session.send_and_read_async (msg, Priority.DEFAULT, cancellable); + debug ("[CalDAV] Response status: %u %s", msg.status_code, msg.reason_phrase ?? ""); } catch (Error e) { if (e is GLib.IOError.CANCELLED) { + debug ("[CalDAV] Request cancelled"); throw e; } + warning ("[CalDAV] Request failed: %s", e.message); throw new GLib.IOError.FAILED ("Request failed: %s".printf (e.message)); } @@ -130,13 +135,23 @@ public class Services.CalDAV.WebDAVClient : GLib.Object { if (!ok) { var response_text = (string) response.get_data (); + warning ("[CalDAV] Unexpected status %u, expected one of: %s", msg.status_code, string.joinv(", ", expected_statuses)); + warning ("[CalDAV] Response (first 500 chars): %s", response_text != null ? response_text.substring(0, int.min(500, response_text.length)) : "(null)"); + + if (msg.status_code == Soup.Status.UNAUTHORIZED) { + warning ("[CalDAV] Auth failed for user: %s", this.username); + throw new GLib.IOError.PERMISSION_DENIED ("Authentication failed. Token may be expired or revoked."); + } + throw new GLib.IOError.FAILED ( "%s %s failed: HTTP %u %s\n%s".printf ( method, abs_url, msg.status_code, msg.reason_phrase ?? "", response_text ?? "") ); } - return (string) response.get_data (); + var response_data = (string) response.get_data (); + debug ("[CalDAV] Response length: %d bytes", response_data != null ? response_data.length : 0); + return response_data; } } @@ -148,7 +163,20 @@ public class Services.CalDAV.WebDAVMultiStatus : Object { public WebDAVMultiStatus.from_string (string xml) throws GLib.Error { this.xml_content = xml; - this.root = new GXml.XDocument.from_string (xml).document_element; + debug ("[CalDAV] Parsing XML response, length: %d", xml != null ? xml.length : 0); + + if (xml == null || xml.strip () == "") { + warning ("[CalDAV] Empty XML response"); + xml = ""; + } + + try { + this.root = new GXml.XDocument.from_string (xml).document_element; + } catch (Error e) { + warning ("[CalDAV] XML parse error: %s", e.message); + warning ("[CalDAV] XML content (first 1000 chars): %s", xml.substring(0, int.min(1000, xml.length))); + throw e; + } } public void debug_print () { From 0fe4c7c524cdbaf7165cb6dd0098ee75c0a3a0c9 Mon Sep 17 00:00:00 2001 From: Alain Date: Mon, 13 Oct 2025 04:55:34 -0500 Subject: [PATCH 3/4] fix logs --- core/Services/CalDAV/WebDAVClient.vala | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/core/Services/CalDAV/WebDAVClient.vala b/core/Services/CalDAV/WebDAVClient.vala index 131cae706..c2f5ddd7f 100644 --- a/core/Services/CalDAV/WebDAVClient.vala +++ b/core/Services/CalDAV/WebDAVClient.vala @@ -135,7 +135,12 @@ public class Services.CalDAV.WebDAVClient : GLib.Object { if (!ok) { var response_text = (string) response.get_data (); - warning ("[CalDAV] Unexpected status %u, expected one of: %s", msg.status_code, string.joinv(", ", expected_statuses)); + var expected_codes = new StringBuilder (); + foreach (var code in expected_statuses) { + if (expected_codes.len > 0) expected_codes.append (", "); + expected_codes.append_printf ("%u", code); + } + warning ("[CalDAV] Unexpected status %u, expected: %s", msg.status_code, expected_codes.str); warning ("[CalDAV] Response (first 500 chars): %s", response_text != null ? response_text.substring(0, int.min(500, response_text.length)) : "(null)"); if (msg.status_code == Soup.Status.UNAUTHORIZED) { From 4ff8a05b86f02c261b229ac1bd2be48135193029 Mon Sep 17 00:00:00 2001 From: Alain Date: Mon, 13 Oct 2025 18:41:56 -0500 Subject: [PATCH 4/4] clean xml --- core/Services/CalDAV/WebDAVClient.vala | 57 ++++++++++++++------------ 1 file changed, 30 insertions(+), 27 deletions(-) diff --git a/core/Services/CalDAV/WebDAVClient.vala b/core/Services/CalDAV/WebDAVClient.vala index c2f5ddd7f..380e7aa75 100644 --- a/core/Services/CalDAV/WebDAVClient.vala +++ b/core/Services/CalDAV/WebDAVClient.vala @@ -66,22 +66,20 @@ public class Services.CalDAV.WebDAVClient : GLib.Object { if (abs_url == null) throw new GLib.IOError.FAILED ("Invalid URL: %s".printf (url)); - debug ("[CalDAV] %s request to: %s", method, abs_url); var msg = new Soup.Message (method, abs_url); msg.request_headers.append ("User-Agent", Constants.SOUP_USER_AGENT); msg.authenticate.connect ((auth, retrying) => { if (retrying) { - warning ("[CalDAV] Authentication retry failed for user: %s", this.username); + warning ("Authentication failed\n"); return false; } if (auth.scheme_name == "Digest" || auth.scheme_name == "Basic") { - debug ("[CalDAV] Authenticating with scheme: %s, username: %s, password length: %d", auth.scheme_name, this.username, this.password.length); auth.authenticate (this.username, this.password); return true; } - warning ("[CalDAV] Unsupported auth schema: %s", auth.scheme_name); + warning ("Unsupported auth schema: %s", auth.scheme_name); return false; }); @@ -115,13 +113,10 @@ public class Services.CalDAV.WebDAVClient : GLib.Object { GLib.Bytes response; try { response = yield session.send_and_read_async (msg, Priority.DEFAULT, cancellable); - debug ("[CalDAV] Response status: %u %s", msg.status_code, msg.reason_phrase ?? ""); } catch (Error e) { if (e is GLib.IOError.CANCELLED) { - debug ("[CalDAV] Request cancelled"); throw e; } - warning ("[CalDAV] Request failed: %s", e.message); throw new GLib.IOError.FAILED ("Request failed: %s".printf (e.message)); } @@ -135,28 +130,13 @@ public class Services.CalDAV.WebDAVClient : GLib.Object { if (!ok) { var response_text = (string) response.get_data (); - var expected_codes = new StringBuilder (); - foreach (var code in expected_statuses) { - if (expected_codes.len > 0) expected_codes.append (", "); - expected_codes.append_printf ("%u", code); - } - warning ("[CalDAV] Unexpected status %u, expected: %s", msg.status_code, expected_codes.str); - warning ("[CalDAV] Response (first 500 chars): %s", response_text != null ? response_text.substring(0, int.min(500, response_text.length)) : "(null)"); - - if (msg.status_code == Soup.Status.UNAUTHORIZED) { - warning ("[CalDAV] Auth failed for user: %s", this.username); - throw new GLib.IOError.PERMISSION_DENIED ("Authentication failed. Token may be expired or revoked."); - } - throw new GLib.IOError.FAILED ( "%s %s failed: HTTP %u %s\n%s".printf ( method, abs_url, msg.status_code, msg.reason_phrase ?? "", response_text ?? "") ); } - var response_data = (string) response.get_data (); - debug ("[CalDAV] Response length: %d bytes", response_data != null ? response_data.length : 0); - return response_data; + return (string) response.get_data (); } } @@ -168,21 +148,44 @@ public class Services.CalDAV.WebDAVMultiStatus : Object { public WebDAVMultiStatus.from_string (string xml) throws GLib.Error { this.xml_content = xml; - debug ("[CalDAV] Parsing XML response, length: %d", xml != null ? xml.length : 0); + debug ("[CalDAV] Parsing XML, length: %d", xml != null ? xml.length : 0); if (xml == null || xml.strip () == "") { - warning ("[CalDAV] Empty XML response"); + warning ("[CalDAV] Empty XML"); xml = ""; } + var cleaned = clean_xml (xml); + try { - this.root = new GXml.XDocument.from_string (xml).document_element; + this.root = new GXml.XDocument.from_string (cleaned).document_element; } catch (Error e) { warning ("[CalDAV] XML parse error: %s", e.message); - warning ("[CalDAV] XML content (first 1000 chars): %s", xml.substring(0, int.min(1000, xml.length))); + warning ("[CalDAV] First 1000 chars: %s", cleaned.substring(0, int.min(1000, cleaned.length))); + warning ("[CalDAV] Last 200 chars: %s", cleaned.substring(int.max(0, cleaned.length - 200))); throw e; } } + + private string clean_xml (string xml) { + var trimmed = xml.strip (); + + var last_close = trimmed.last_index_of (""); + if (last_close == -1) { + last_close = trimmed.last_index_of (""); + } + + if (last_close > 0) { + var tag_len = trimmed.has_suffix ("") ? 16 : 14; + var end_pos = last_close + tag_len; + if (end_pos < trimmed.length) { + debug ("[CalDAV] Removing %d extra bytes", trimmed.length - end_pos); + return trimmed.substring (0, end_pos); + } + } + + return trimmed; + } public void debug_print () { print ("-------------------------------\n");