Bug Summary

File:src/calendar/backends/webdav-notes/e-cal-backend-webdav-notes.c
Warning:line 1210, column 28
Null pointer passed to 1st parameter expecting 'nonnull'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -O3 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name e-cal-backend-webdav-notes.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -relaxed-aliasing -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/builds/GNOME/evolution-data-server/_build -fcoverage-compilation-dir=/builds/GNOME/evolution-data-server/_build -resource-dir /usr/bin/../lib/clang/22 -D BACKENDDIR="/home/user/_prefix/lib/evolution-data-server/calendar-backends" -D GLIB_VERSION_MAX_ALLOWED=GLIB_VERSION_2_68 -D GLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_68 -D G_LOG_DOMAIN="e-cal-backend-webdav-notes" -D LDAP_DEPRECATED -D SOUP_VERSION_MAX_ALLOWED=SOUP_VERSION_3_2 -D SOUP_VERSION_MIN_REQUIRED=SOUP_VERSION_3_2 -D _LARGEFILE64_SOURCE=1 -D ecalbackendwebdavnotes_EXPORTS -I /builds/GNOME/evolution-data-server/_build -I /builds/GNOME/evolution-data-server/_build/src -I /builds/GNOME/evolution-data-server/src -I /builds/GNOME/evolution-data-server/_build/src/calendar -I /builds/GNOME/evolution-data-server/src/calendar -I /usr/include/libsoup-3.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/libxml2 -I /builds/GNOME/evolution-data-server/_build/src/private -I /builds/GNOME/evolution-data-server/src/private -I /builds/GNOME/evolution-data-server/_build/src/libebackend -I /builds/GNOME/evolution-data-server/src/libebackend -I /usr/include/nss3 -I /usr/include/nspr4 -I /usr/include/gio-unix-2.0 -I /builds/GNOME/evolution-data-server/_build/src/libedataserver -I /builds/GNOME/evolution-data-server/src/libedataserver -I /usr/include/libsecret-1 -I /usr/include/p11-kit-1 -I /usr/include/json-glib-1.0 -I /usr/include/uuid -I /builds/GNOME/evolution-data-server/_build/src/camel -I /builds/GNOME/evolution-data-server/src/camel -I /builds/GNOME/evolution-data-server/_build/src/calendar/libecal -I /builds/GNOME/evolution-data-server/src/calendar/libecal -I /builds/GNOME/evolution-data-server/_build/src/calendar/libedata-cal -D NDEBUG -I /usr/include -I /usr/include/libsoup-3.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/libxml2 -D WITH_GZFILEOP -D LIBICAL_GLIB_UNSTABLE_API=1 -I /usr/include/nss3 -I /usr/include/nspr4 -I /usr/include/gio-unix-2.0 -I /usr/include/libsecret-1 -I /usr/include/p11-kit-1 -I /usr/include/json-glib-1.0 -I /usr/include/uuid -internal-isystem /usr/bin/../lib/clang/22/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/16/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-unused-parameter -Wno-sign-compare -Wno-missing-field-initializers -Wno-missing-include-dirs -Wno-deprecated-declarations -Wno-cast-function-type -Wwrite-strings -fconst-strings -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -fdwarf2-cfi-asm -o /builds/GNOME/evolution-data-server/_build/scan-build/2026-08-11-054813-10-1 -x c /builds/GNOME/evolution-data-server/src/calendar/backends/webdav-notes/e-cal-backend-webdav-notes.c
1/*
2 * SPDX-FileCopyrightText: (C) 2020 Red Hat (www.redhat.com)
3 * SPDX-License-Identifier: LGPL-2.0-or-later
4 */
5
6#include "evolution-data-server-config.h"
7
8#include <string.h>
9#include <glib/gi18n-lib.h>
10
11#include <libedataserver/libedataserver.h>
12
13#include "e-cal-backend-webdav-notes.h"
14
15#define E_WEBDAV_NOTES_X_ETAG"X-EVOLUTION-WEBDAV-NOTES-ETAG" "X-EVOLUTION-WEBDAV-NOTES-ETAG"
16#define E_WEBDAV_NOTES_X_IS_MARKDOWN"X-EVOLUTION-IS-MARKDOWN" "X-EVOLUTION-IS-MARKDOWN"
17
18#define EC_ERROR(_code)e_client_error_create (_code, ((void*)0)) e_client_error_create (_code, NULL((void*)0))
19#define ECC_ERROR(_code)e_cal_client_error_create (_code, ((void*)0)) e_cal_client_error_create (_code, NULL((void*)0))
20#define ECC_ERROR_EX(_code, _msg)e_cal_client_error_create (_code, _msg) e_cal_client_error_create (_code, _msg)
21
22struct _ECalBackendWebDAVNotesPrivate {
23 /* The main WebDAV session */
24 EWebDAVSession *webdav;
25 GUri *last_uri;
26 GMutex webdav_lock;
27
28 /* If already been connected, then the connect_sync() will relax server checks,
29 to avoid unnecessary requests towards the server. */
30 gboolean been_connected;
31
32 gboolean etag_supported;
33};
34
35G_DEFINE_TYPE_WITH_PRIVATE (ECalBackendWebDAVNotes, e_cal_backend_webdav_notes, E_TYPE_CAL_META_BACKEND)static void e_cal_backend_webdav_notes_init (ECalBackendWebDAVNotes
*self); static void e_cal_backend_webdav_notes_class_init (ECalBackendWebDAVNotesClass
*klass); static GType e_cal_backend_webdav_notes_get_type_once
(void); static gpointer e_cal_backend_webdav_notes_parent_class
= ((void*)0); static gint ECalBackendWebDAVNotes_private_offset
; static void e_cal_backend_webdav_notes_class_intern_init (gpointer
klass) { e_cal_backend_webdav_notes_parent_class = g_type_class_peek_parent
(klass); if (ECalBackendWebDAVNotes_private_offset != 0) g_type_class_adjust_private_offset
(klass, &ECalBackendWebDAVNotes_private_offset); e_cal_backend_webdav_notes_class_init
((ECalBackendWebDAVNotesClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer e_cal_backend_webdav_notes_get_instance_private
(ECalBackendWebDAVNotes *self) { return (((gpointer) ((guint8
*) (self) + (glong) (ECalBackendWebDAVNotes_private_offset)))
); } GType e_cal_backend_webdav_notes_get_type (void) { static
gsize static_g_define_type_id = 0; if ((__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); (void) (0 ? (gpointer) *(
&static_g_define_type_id) : ((void*)0)); (!(__extension__
({ _Static_assert (sizeof *(&static_g_define_type_id) ==
sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter (&static_g_define_type_id
)); }))) { GType g_define_type_id = e_cal_backend_webdav_notes_get_type_once
(); (__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); 0 ?
(void) (*(&static_g_define_type_id) = (g_define_type_id)
) : (void) 0; g_once_init_leave ((&static_g_define_type_id
), (gsize) (g_define_type_id)); })); } return static_g_define_type_id
; } __attribute__ ((__noinline__)) static GType e_cal_backend_webdav_notes_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
((e_cal_meta_backend_get_type ()), g_intern_static_string ("ECalBackendWebDAVNotes"
), sizeof (ECalBackendWebDAVNotesClass), (GClassInitFunc)(void
(*)(void)) e_cal_backend_webdav_notes_class_intern_init, sizeof
(ECalBackendWebDAVNotes), (GInstanceInitFunc)(void (*)(void)
) e_cal_backend_webdav_notes_init, (GTypeFlags) 0); { {{ ECalBackendWebDAVNotes_private_offset
= g_type_add_instance_private (g_define_type_id, sizeof (ECalBackendWebDAVNotesPrivate
)); };} } return g_define_type_id; }
36
37static gboolean
38ecb_webdav_notes_has_supported_extension (const gchar *filename,
39 gint *out_ext_len,
40 const gchar **out_ext,
41 const gchar **out_ext_num_suffix,
42 const gchar **out_content_type)
43{
44 if (!filename || !*filename)
45 return FALSE(0);
46
47 if (g_str_has_suffix (filename, ".txt")(__builtin_constant_p (".txt")? __extension__ ({ const char *
const __str = (filename); const char * const __suffix = (".txt"
); gboolean __result = (0); if (__builtin_expect (__extension__
({ int _g_boolean_var_64 = 0; if (__str == ((void*)0) || __suffix
== ((void*)0)) _g_boolean_var_64 = 1; _g_boolean_var_64; }),
0)) __result = (g_str_has_suffix) (__str, __suffix); else { const
size_t __str_len = strlen (((__str) + !(__str))); const size_t
__suffix_len = strlen (((__suffix) + !(__suffix))); if (__str_len
>= __suffix_len) __result = memcmp (__str + __str_len - __suffix_len
, ((__suffix) + !(__suffix)), __suffix_len) == 0; } __result;
}) : (g_str_has_suffix) (filename, ".txt") )
) {
48 if (out_ext_len)
49 *out_ext_len = 4;
50 if (out_ext)
51 *out_ext = ".txt";
52 if (out_ext_num_suffix)
53 *out_ext_num_suffix = ").txt";
54 if (out_content_type)
55 *out_content_type = "text/plain; charset=\"utf-8\"";
56
57 return TRUE(!(0));
58 }
59
60 if (g_str_has_suffix (filename, ".md")(__builtin_constant_p (".md")? __extension__ ({ const char * const
__str = (filename); const char * const __suffix = (".md"); gboolean
__result = (0); if (__builtin_expect (__extension__ ({ int _g_boolean_var_65
= 0; if (__str == ((void*)0) || __suffix == ((void*)0)) _g_boolean_var_65
= 1; _g_boolean_var_65; }), 0)) __result = (g_str_has_suffix
) (__str, __suffix); else { const size_t __str_len = strlen (
((__str) + !(__str))); const size_t __suffix_len = strlen (((
__suffix) + !(__suffix))); if (__str_len >= __suffix_len) __result
= memcmp (__str + __str_len - __suffix_len, ((__suffix) + !(
__suffix)), __suffix_len) == 0; } __result; }) : (g_str_has_suffix
) (filename, ".md") )
) {
61 if (out_ext_len)
62 *out_ext_len = 3;
63 if (out_ext)
64 *out_ext = ".md";
65 if (out_ext_num_suffix)
66 *out_ext_num_suffix = ").md";
67 if (out_content_type)
68 *out_content_type = "text/markdown; charset=\"utf-8\"";
69
70 return TRUE(!(0));
71 }
72
73 return FALSE(0);
74}
75
76static EWebDAVSession *
77ecb_webdav_notes_ref_session (ECalBackendWebDAVNotes *cbnotes)
78{
79 EWebDAVSession *webdav;
80
81 g_return_val_if_fail (E_IS_CAL_BACKEND_WEBDAV_NOTES (cbnotes), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_66
= 0; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((cbnotes)); GType __t = ((e_cal_backend_webdav_notes_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_66 = 1; _g_boolean_var_66; }), 1)
)) { } else { g_return_if_fail_warning ("e-cal-backend-webdav-notes"
, ((const char*) (__func__)), "E_IS_CAL_BACKEND_WEBDAV_NOTES (cbnotes)"
); return (((void*)0)); } } while (0)
;
82
83 g_mutex_lock (&cbnotes->priv->webdav_lock);
84 if (cbnotes->priv->webdav)
85 webdav = g_object_ref (cbnotes->priv->webdav)((__typeof__ (cbnotes->priv->webdav)) (g_object_ref) (cbnotes
->priv->webdav))
;
86 else
87 webdav = NULL((void*)0);
88 g_mutex_unlock (&cbnotes->priv->webdav_lock);
89
90 return webdav;
91}
92
93static gboolean
94ecb_webdav_notes_connect_sync (ECalMetaBackend *meta_backend,
95 const ENamedParameters *credentials,
96 ESourceAuthenticationResult *out_auth_result,
97 gchar **out_certificate_pem,
98 GTlsCertificateFlags *out_certificate_errors,
99 GCancellable *cancellable,
100 GError **error)
101{
102 ECalBackendWebDAVNotes *cbnotes;
103 EWebDAVSession *webdav;
104 GHashTable *capabilities = NULL((void*)0), *allows = NULL((void*)0);
105 ESource *source;
106 gboolean success, is_writable = FALSE(0), uri_changed = FALSE(0);
107 GError *local_error = NULL((void*)0);
108
109 g_return_val_if_fail (E_IS_CAL_BACKEND_WEBDAV_NOTES (meta_backend), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_67
= 0; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((meta_backend)); GType __t = ((e_cal_backend_webdav_notes_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_67 = 1; _g_boolean_var_67; }), 1)
)) { } else { g_return_if_fail_warning ("e-cal-backend-webdav-notes"
, ((const char*) (__func__)), "E_IS_CAL_BACKEND_WEBDAV_NOTES (meta_backend)"
); return ((0)); } } while (0)
;
110 g_return_val_if_fail (out_auth_result != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_68
= 0; if (out_auth_result != ((void*)0)) _g_boolean_var_68 = 1
; _g_boolean_var_68; }), 1))) { } else { g_return_if_fail_warning
("e-cal-backend-webdav-notes", ((const char*) (__func__)), "out_auth_result != NULL"
); return ((0)); } } while (0)
;
111
112 *out_auth_result = E_SOURCE_AUTHENTICATION_ACCEPTED;
113
114 cbnotes = E_CAL_BACKEND_WEBDAV_NOTES (meta_backend)((((ECalBackendWebDAVNotes*) (void *) ((meta_backend)))));
115 source = e_backend_get_source (E_BACKEND (meta_backend)((((EBackend*) (void *) ((meta_backend))))));
116
117 g_mutex_lock (&cbnotes->priv->webdav_lock);
118 if (cbnotes->priv->webdav) {
119 g_mutex_unlock (&cbnotes->priv->webdav_lock);
120 return TRUE(!(0));
121 }
122
123 if (e_source_has_extension (source, E_SOURCE_EXTENSION_WEBDAV_BACKEND"WebDAV Backend")) {
124 ESourceWebdav *webdav_extension;
125 GUri *current_uri;
126
127 webdav_extension = e_source_get_extension (source, E_SOURCE_EXTENSION_WEBDAV_BACKEND"WebDAV Backend");
128 current_uri = e_source_webdav_dup_uri (webdav_extension);
129
130 #define uri_str_equal(_func) (g_strcmp0 (_func (cbnotes->priv->last_uri), _func (current_uri)) == 0)
131
132 uri_changed = cbnotes->priv->last_uri && current_uri && (
133 g_uri_get_port (cbnotes->priv->last_uri) != g_uri_get_port (current_uri) ||
134 !uri_str_equal (g_uri_get_auth_params) ||
135 !uri_str_equal (g_uri_get_host) ||
136 !uri_str_equal (g_uri_get_path) ||
137 !uri_str_equal (g_uri_get_query) ||
138 !uri_str_equal (g_uri_get_fragment) ||
139 !uri_str_equal (g_uri_get_scheme) ||
140 !uri_str_equal (g_uri_get_userinfo) ||
141 !uri_str_equal (g_uri_get_user) ||
142 !uri_str_equal (g_uri_get_password));
143
144 #undef uri_str_equal
145
146 if (!cbnotes->priv->last_uri || uri_changed) {
147 g_clear_pointer (&cbnotes->priv->last_uri, g_uri_unref)do { _Static_assert (sizeof *(&cbnotes->priv->last_uri
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&cbnotes->priv->last_uri)) _pp = (&cbnotes->
priv->last_uri); __typeof__ (*(&cbnotes->priv->last_uri
)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_uri_unref) (_ptr
); } while (0)
;
148 cbnotes->priv->last_uri = current_uri;
149 } else if (current_uri) {
150 g_uri_unref (current_uri);
151 }
152 }
153 g_mutex_unlock (&cbnotes->priv->webdav_lock);
154
155 if (uri_changed)
156 e_cal_meta_backend_set_sync_tag (meta_backend, NULL((void*)0));
157
158 webdav = e_webdav_session_new (source);
159
160 e_soup_session_setup_logging (E_SOUP_SESSION (webdav)((((ESoupSession*) (void *) ((webdav))))), g_getenv ("WEBDAV_NOTES_DEBUG"));
161
162 e_binding_bind_property (
163 cbnotes, "proxy-resolver",
164 webdav, "proxy-resolver",
165 G_BINDING_SYNC_CREATE);
166
167 e_source_set_connection_status (source, E_SOURCE_CONNECTION_STATUS_CONNECTING);
168
169 e_soup_session_set_credentials (E_SOUP_SESSION (webdav)((((ESoupSession*) (void *) ((webdav))))), credentials);
170
171 if (cbnotes->priv->been_connected) {
172 g_mutex_lock (&cbnotes->priv->webdav_lock);
173 cbnotes->priv->webdav = webdav;
174 g_mutex_unlock (&cbnotes->priv->webdav_lock);
175
176 return TRUE(!(0));
177 }
178
179 /* This is just to make it similar to the CalDAV backend. */
180 cbnotes->priv->etag_supported = TRUE(!(0));
181
182 success = e_webdav_session_options_sync (webdav, NULL((void*)0),
183 &capabilities, &allows, cancellable, &local_error);
184
185 if (success && !g_cancellable_is_cancelled (cancellable)) {
186 GSList *privileges = NULL((void*)0), *link;
187
188 /* Ignore any errors here */
189 if (e_webdav_session_get_current_user_privilege_set_full_sync (webdav, NULL((void*)0), &privileges,
190 capabilities ? NULL((void*)0) : &capabilities,
191 allows ? NULL((void*)0) : &allows, cancellable, NULL((void*)0))) {
192 for (link = privileges; link && !is_writable; link = g_slist_next (link)((link) ? (((GSList *)(link))->next) : ((void*)0))) {
193 EWebDAVPrivilege *privilege = link->data;
194
195 if (privilege) {
196 is_writable =
197 privilege->hint == E_WEBDAV_PRIVILEGE_HINT_WRITE ||
198 privilege->hint == E_WEBDAV_PRIVILEGE_HINT_WRITE_CONTENT ||
199 privilege->hint == E_WEBDAV_PRIVILEGE_HINT_ALL;
200 }
201 }
202
203 g_slist_free_full (privileges, e_webdav_privilege_free);
204 } else {
205 is_writable = allows && (
206 g_hash_table_contains (allows, "PUT") ||
207 g_hash_table_contains (allows, "POST") ||
208 g_hash_table_contains (allows, "DELETE"));
209 }
210 }
211
212 if (success) {
213 e_cal_backend_set_writable (E_CAL_BACKEND (cbnotes)((((ECalBackend*) (void *) ((cbnotes))))), is_writable);
214 e_source_set_connection_status (source, E_SOURCE_CONNECTION_STATUS_CONNECTED);
215 }
216
217 if (success) {
218 gchar *ctag = NULL((void*)0);
219
220 /* Some servers, notably Google, allow OPTIONS when not
221 authorized (aka without credentials), thus try something
222 more aggressive, just in case.
223
224 The 'getctag' extension is not required, thus check
225 for unauthorized error only. */
226 if (!e_webdav_session_getctag_sync (webdav, NULL((void*)0), &ctag, cancellable, &local_error) &&
227 g_error_matches (local_error, E_SOUP_SESSION_ERROR(e_soup_session_error_quark()), SOUP_STATUS_UNAUTHORIZED)) {
228 success = FALSE(0);
229 } else {
230 g_clear_error (&local_error);
231 }
232
233 g_free (ctag);
234 }
235
236 if (success) {
237 e_source_set_connection_status (source, E_SOURCE_CONNECTION_STATUS_CONNECTED);
238 } else {
239 e_soup_session_handle_authentication_failure (E_SOUP_SESSION (webdav)((((ESoupSession*) (void *) ((webdav))))), credentials,
240 local_error, out_auth_result, out_certificate_pem, out_certificate_errors, error);
241 }
242
243 g_clear_error (&local_error);
244
245 if (capabilities)
246 g_hash_table_destroy (capabilities);
247 if (allows)
248 g_hash_table_destroy (allows);
249
250 if (success && !g_cancellable_set_error_if_cancelled (cancellable, error)) {
251 g_mutex_lock (&cbnotes->priv->webdav_lock);
252 cbnotes->priv->webdav = webdav;
253 g_mutex_unlock (&cbnotes->priv->webdav_lock);
254 cbnotes->priv->been_connected = TRUE(!(0));
255 } else {
256 if (success) {
257 e_source_set_connection_status (source, E_SOURCE_CONNECTION_STATUS_DISCONNECTED);
258 success = FALSE(0);
259 }
260
261 g_clear_object (&webdav)do { _Static_assert (sizeof *((&webdav)) == sizeof (gpointer
), "Expression evaluates to false"); __typeof__ (((&webdav
))) _pp = ((&webdav)); __typeof__ (*((&webdav))) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_object_unref) (_ptr)
; } while (0)
;
262 }
263
264 return success;
265}
266
267static gboolean
268ecb_webdav_notes_disconnect_sync (ECalMetaBackend *meta_backend,
269 GCancellable *cancellable,
270 GError **error)
271{
272 ECalBackendWebDAVNotes *cbnotes;
273 ESource *source;
274
275 g_return_val_if_fail (E_IS_CAL_BACKEND_WEBDAV_NOTES (meta_backend), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_69
= 0; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((meta_backend)); GType __t = ((e_cal_backend_webdav_notes_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_69 = 1; _g_boolean_var_69; }), 1)
)) { } else { g_return_if_fail_warning ("e-cal-backend-webdav-notes"
, ((const char*) (__func__)), "E_IS_CAL_BACKEND_WEBDAV_NOTES (meta_backend)"
); return ((0)); } } while (0)
;
276
277 cbnotes = E_CAL_BACKEND_WEBDAV_NOTES (meta_backend)((((ECalBackendWebDAVNotes*) (void *) ((meta_backend)))));
278
279 g_mutex_lock (&cbnotes->priv->webdav_lock);
280 if (cbnotes->priv->webdav)
281 soup_session_abort (SOUP_SESSION (cbnotes->priv->webdav));
282
283 g_clear_object (&cbnotes->priv->webdav)do { _Static_assert (sizeof *((&cbnotes->priv->webdav
)) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(((&cbnotes->priv->webdav))) _pp = ((&cbnotes->
priv->webdav)); __typeof__ (*((&cbnotes->priv->webdav
))) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_object_unref
) (_ptr); } while (0)
;
284 g_mutex_unlock (&cbnotes->priv->webdav_lock);
285
286 source = e_backend_get_source (E_BACKEND (meta_backend)((((EBackend*) (void *) ((meta_backend))))));
287 e_source_set_connection_status (source, E_SOURCE_CONNECTION_STATUS_DISCONNECTED);
288
289 return TRUE(!(0));
290}
291
292typedef struct _WebDAVNotesChangesData {
293 GSList **out_modified_objects;
294 GSList **out_removed_objects;
295 GHashTable *known_items; /* gchar *href ~> ECalMetaBackendInfo * */
296} WebDAVNotesChangesData;
297
298static gboolean
299ecb_webdav_notes_search_changes_cb (ECalCache *cal_cache,
300 const gchar *uid,
301 const gchar *rid,
302 const gchar *revision,
303 const gchar *object,
304 const gchar *extra,
305 guint32 custom_flags,
306 EOfflineState offline_state,
307 gpointer user_data)
308{
309 WebDAVNotesChangesData *ccd = user_data;
310
311 g_return_val_if_fail (ccd != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_70
= 0; if (ccd != ((void*)0)) _g_boolean_var_70 = 1; _g_boolean_var_70
; }), 1))) { } else { g_return_if_fail_warning ("e-cal-backend-webdav-notes"
, ((const char*) (__func__)), "ccd != NULL"); return ((0)); }
} while (0)
;
312 g_return_val_if_fail (uid != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_71
= 0; if (uid != ((void*)0)) _g_boolean_var_71 = 1; _g_boolean_var_71
; }), 1))) { } else { g_return_if_fail_warning ("e-cal-backend-webdav-notes"
, ((const char*) (__func__)), "uid != NULL"); return ((0)); }
} while (0)
;
313
314 /* The 'extra' can be NULL for added components in offline mode */
315 if (((extra && *extra) || offline_state != E_OFFLINE_STATE_LOCALLY_CREATED) && (!rid || !*rid)) {
316 ECalMetaBackendInfo *nfo;
317
318 nfo = (extra && *extra) ? g_hash_table_lookup (ccd->known_items, extra) : NULL((void*)0);
319 if (nfo) {
320 if (g_strcmp0 (revision, nfo->revision) == 0) {
321 g_hash_table_remove (ccd->known_items, extra);
322 } else {
323 if (!nfo->uid || !*(nfo->uid)) {
324 g_free (nfo->uid);
325 nfo->uid = g_strdup (uid)g_strdup_inline (uid);
326 }
327
328 *(ccd->out_modified_objects) = g_slist_prepend (*(ccd->out_modified_objects),
329 e_cal_meta_backend_info_copy (nfo));
330
331 g_hash_table_remove (ccd->known_items, extra);
332 }
333 } else {
334 *(ccd->out_removed_objects) = g_slist_prepend (*(ccd->out_removed_objects),
335 e_cal_meta_backend_info_new (uid, revision, object, extra));
336 }
337 }
338
339 return TRUE(!(0));
340}
341
342static void
343ecb_webdav_notes_check_credentials_error (ECalBackendWebDAVNotes *cbnotes,
344 EWebDAVSession *webdav,
345 GError *op_error)
346{
347 g_return_if_fail (E_IS_CAL_BACKEND_WEBDAV_NOTES (cbnotes))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_72
= 0; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((cbnotes)); GType __t = ((e_cal_backend_webdav_notes_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_72 = 1; _g_boolean_var_72; }), 1)
)) { } else { g_return_if_fail_warning ("e-cal-backend-webdav-notes"
, ((const char*) (__func__)), "E_IS_CAL_BACKEND_WEBDAV_NOTES (cbnotes)"
); return; } } while (0)
;
348
349 if (g_error_matches (op_error, G_TLS_ERROR(g_tls_error_quark ()), G_TLS_ERROR_BAD_CERTIFICATE) && webdav) {
350 op_error->domain = E_CLIENT_ERRORe_client_error_quark ();
351 op_error->code = E_CLIENT_ERROR_TLS_NOT_AVAILABLE;
352 } else if (g_error_matches (op_error, E_SOUP_SESSION_ERROR(e_soup_session_error_quark()), SOUP_STATUS_UNAUTHORIZED) ||
353 g_error_matches (op_error, E_SOUP_SESSION_ERROR(e_soup_session_error_quark()), SOUP_STATUS_FORBIDDEN)) {
354 gboolean was_forbidden = g_error_matches (op_error, E_SOUP_SESSION_ERROR(e_soup_session_error_quark()), SOUP_STATUS_FORBIDDEN);
355
356 op_error->domain = E_CLIENT_ERRORe_client_error_quark ();
357 op_error->code = E_CLIENT_ERROR_AUTHENTICATION_REQUIRED;
358
359 cbnotes->priv->been_connected = FALSE(0);
360
361 if (webdav) {
362 ENamedParameters *credentials;
363 gboolean empty_credentials;
364
365 credentials = e_soup_session_dup_credentials (E_SOUP_SESSION (webdav)((((ESoupSession*) (void *) ((webdav))))));
366 empty_credentials = !credentials || !e_named_parameters_count (credentials);
367 e_named_parameters_free (credentials);
368
369 if (!empty_credentials) {
370 if (was_forbidden) {
371 if (e_webdav_session_get_last_dav_error_is_permission (webdav)) {
372 op_error->code = E_CLIENT_ERROR_PERMISSION_DENIED;
373 g_free (op_error->message);
374 op_error->message = g_strdup (e_client_error_to_string (op_error->code))g_strdup_inline (e_client_error_to_string (op_error->code)
)
;
375 } else {
376 /* To avoid credentials prompt */
377 op_error->code = E_CLIENT_ERROR_OTHER_ERROR;
378 }
379 } else {
380 op_error->code = E_CLIENT_ERROR_AUTHENTICATION_FAILED;
381 }
382 }
383 }
384 }
385}
386
387static gboolean
388ecb_webdav_notes_getetag_cb (EWebDAVSession *webdav,
389 xmlNodePtr prop_node,
390 const GUri *request_uri,
391 const gchar *href,
392 guint status_code,
393 gpointer user_data)
394{
395 if (status_code == SOUP_STATUS_OK) {
396 gchar **out_etag = user_data;
397 const xmlChar *etag;
398
399 g_return_val_if_fail (out_etag != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_73
= 0; if (out_etag != ((void*)0)) _g_boolean_var_73 = 1; _g_boolean_var_73
; }), 1))) { } else { g_return_if_fail_warning ("e-cal-backend-webdav-notes"
, ((const char*) (__func__)), "out_etag != NULL"); return ((0
)); } } while (0)
;
400
401 etag = e_xml_find_child_and_get_text (prop_node, E_WEBDAV_NS_DAV"DAV:", "getetag");
402
403 if (etag && *etag)
404 *out_etag = e_webdav_session_util_maybe_dequote (g_strdup ((const gchar *) etag)g_strdup_inline ((const gchar *) etag));
405 }
406
407 return FALSE(0);
408}
409
410static gboolean
411ecb_webdav_notes_getetag_sync (EWebDAVSession *webdav,
412 const gchar *uri,
413 gchar **out_etag,
414 GCancellable *cancellable,
415 GError **error)
416{
417 EXmlDocument *xml;
418 gboolean success;
419
420 g_return_val_if_fail (E_IS_WEBDAV_SESSION (webdav), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_74
= 0; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((webdav)); GType __t = ((e_webdav_session_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) _g_boolean_var_74
= 1; _g_boolean_var_74; }), 1))) { } else { g_return_if_fail_warning
("e-cal-backend-webdav-notes", ((const char*) (__func__)), "E_IS_WEBDAV_SESSION (webdav)"
); return ((0)); } } while (0)
;
421 g_return_val_if_fail (out_etag != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_75
= 0; if (out_etag != ((void*)0)) _g_boolean_var_75 = 1; _g_boolean_var_75
; }), 1))) { } else { g_return_if_fail_warning ("e-cal-backend-webdav-notes"
, ((const char*) (__func__)), "out_etag != NULL"); return ((0
)); } } while (0)
;
422
423 *out_etag = NULL((void*)0);
424
425 xml = e_xml_document_new (E_WEBDAV_NS_DAV"DAV:", "propfind");
426 g_return_val_if_fail (xml != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_76
= 0; if (xml != ((void*)0)) _g_boolean_var_76 = 1; _g_boolean_var_76
; }), 1))) { } else { g_return_if_fail_warning ("e-cal-backend-webdav-notes"
, ((const char*) (__func__)), "xml != NULL"); return ((0)); }
} while (0)
;
427
428 e_xml_document_start_element (xml, NULL((void*)0), "prop");
429 e_xml_document_add_empty_element (xml, NULL((void*)0), "getetag");
430 e_xml_document_end_element (xml); /* prop */
431
432 success = e_webdav_session_propfind_sync (webdav, uri, E_WEBDAV_DEPTH_THIS"0", xml,
433 ecb_webdav_notes_getetag_cb, out_etag, cancellable, error);
434
435 g_object_unref (xml);
436
437 return success && *out_etag != NULL((void*)0);
438}
439
440static ICalComponent *
441ecb_webdav_notes_new_icomp (glong creation_date,
442 glong last_modified,
443 const gchar *uid,
444 const gchar *revision,
445 const gchar *summary,
446 const gchar *description)
447{
448 ICalComponent *icomp;
449 ICalTime *itt;
450 glong tt;
451 gint ext_len = 0;
452
453 icomp = i_cal_component_new_vjournal ();
454
455 if (creation_date > 0)
456 tt = creation_date;
457 else if (last_modified > 0)
458 tt = last_modified;
459 else
460 tt = (time_t) time (NULL((void*)0));
461
462 itt = i_cal_time_new_from_timet_with_zone ((time_t) tt, FALSE(0), i_cal_timezone_get_utc_timezone ());
463 i_cal_component_take_property (icomp, i_cal_property_new_created (itt));
464 g_object_unref (itt);
465
466 if (last_modified > 0)
467 tt = last_modified;
468 else
469 tt = (time_t) time (NULL((void*)0));
470
471 itt = i_cal_time_new_from_timet_with_zone ((time_t) tt, FALSE(0), i_cal_timezone_get_utc_timezone ());
472 i_cal_component_take_property (icomp, i_cal_property_new_lastmodified (itt));
473 g_object_unref (itt);
474
475 i_cal_component_set_uid (icomp, uid);
476
477 if (ecb_webdav_notes_has_supported_extension (summary, &ext_len, NULL((void*)0), NULL((void*)0), NULL((void*)0))) {
478 gchar *tmp;
479
480 tmp = g_strndup (summary, strlen (summary) - ext_len);
481 i_cal_component_set_summary (icomp, tmp);
482 g_free (tmp);
483 } else if (summary && *summary) {
484 i_cal_component_set_summary (icomp, summary);
485 }
486
487 if ((uid && g_str_has_suffix (uid, ".md")(__builtin_constant_p (".md")? __extension__ ({ const char * const
__str = (uid); const char * const __suffix = (".md"); gboolean
__result = (0); if (__builtin_expect (__extension__ ({ int _g_boolean_var_77
= 0; if (__str == ((void*)0) || __suffix == ((void*)0)) _g_boolean_var_77
= 1; _g_boolean_var_77; }), 0)) __result = (g_str_has_suffix
) (__str, __suffix); else { const size_t __str_len = strlen (
((__str) + !(__str))); const size_t __suffix_len = strlen (((
__suffix) + !(__suffix))); if (__str_len >= __suffix_len) __result
= memcmp (__str + __str_len - __suffix_len, ((__suffix) + !(
__suffix)), __suffix_len) == 0; } __result; }) : (g_str_has_suffix
) (uid, ".md") )
) ||
488 (summary && g_str_has_suffix (summary, ".md")(__builtin_constant_p (".md")? __extension__ ({ const char * const
__str = (summary); const char * const __suffix = (".md"); gboolean
__result = (0); if (__builtin_expect (__extension__ ({ int _g_boolean_var_78
= 0; if (__str == ((void*)0) || __suffix == ((void*)0)) _g_boolean_var_78
= 1; _g_boolean_var_78; }), 0)) __result = (g_str_has_suffix
) (__str, __suffix); else { const size_t __str_len = strlen (
((__str) + !(__str))); const size_t __suffix_len = strlen (((
__suffix) + !(__suffix))); if (__str_len >= __suffix_len) __result
= memcmp (__str + __str_len - __suffix_len, ((__suffix) + !(
__suffix)), __suffix_len) == 0; } __result; }) : (g_str_has_suffix
) (summary, ".md") )
))
489 e_cal_util_component_set_x_property (icomp, E_WEBDAV_NOTES_X_IS_MARKDOWN"X-EVOLUTION-IS-MARKDOWN", "1");
490
491 if (description && *description) {
492 const gchar *current_summary;
493
494 i_cal_component_set_description (icomp, description);
495
496 current_summary = i_cal_component_get_summary (icomp);
497
498 if (!current_summary || !*current_summary) {
499 const gchar *pos;
500
501 pos = strchr (description, '\n');
502 if (pos && pos > description && pos[-1] == '\r')
503 pos--;
504
505 if (!pos) {
506 /* single line description */
507 i_cal_component_set_summary (icomp, description);
508 } else if (pos > description) {
509 gchar *tmp;
510
511 tmp = g_strndup (description, pos - description);
512 i_cal_component_set_summary (icomp, tmp);
513 g_free (tmp);
514 }
515 }
516 }
517
518 e_cal_util_component_set_x_property (icomp, E_WEBDAV_NOTES_X_ETAG"X-EVOLUTION-WEBDAV-NOTES-ETAG", revision);
519
520 return icomp;
521}
522
523static gboolean
524ecb_webdav_notes_get_objects_sync (EWebDAVSession *webdav,
525 GHashTable *resources_hash, /* gchar *href ~> EWebDAVResource * */
526 GSList *infos, /* ECalMetaBackendInfo * */
527 GCancellable *cancellable,
528 GError **error)
529{
530 GSList *link;
531 gboolean success = TRUE(!(0));
532
533 g_return_val_if_fail (E_IS_WEBDAV_SESSION (webdav), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_79
= 0; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((webdav)); GType __t = ((e_webdav_session_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) _g_boolean_var_79
= 1; _g_boolean_var_79; }), 1))) { } else { g_return_if_fail_warning
("e-cal-backend-webdav-notes", ((const char*) (__func__)), "E_IS_WEBDAV_SESSION (webdav)"
); return ((0)); } } while (0)
;
534
535 for (link = infos; success && link; link = g_slist_next (link)((link) ? (((GSList *)(link))->next) : ((void*)0))) {
536 ECalMetaBackendInfo *nfo = link->data;
537 gchar *etag = NULL((void*)0), *bytes = NULL((void*)0);
538
539 if (!nfo)
540 continue;
541
542 success = e_webdav_session_get_data_sync (webdav, nfo->extra, NULL((void*)0), &etag, NULL((void*)0), &bytes, NULL((void*)0), cancellable, error);
543
544 if (success) {
545 EWebDAVResource *resource;
546
547 resource = g_hash_table_lookup (resources_hash, nfo->extra);
548
549 if (resource) {
550 ICalComponent *icomp;
551
552 if (g_strcmp0 (nfo->revision, etag) != 0) {
553 g_free (nfo->revision);
554 nfo->revision = etag;
555 etag = NULL((void*)0);
556 }
557
558 icomp = ecb_webdav_notes_new_icomp (resource->creation_date,
559 resource->last_modified,
560 nfo->uid,
561 nfo->revision,
562 resource->display_name,
563 bytes);
564
565 g_warn_if_fail (nfo->object == NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_80
= 0; if (nfo->object == ((void*)0)) _g_boolean_var_80 = 1
; _g_boolean_var_80; }), 1)) ; else g_warn_message ("e-cal-backend-webdav-notes"
, "/builds/GNOME/evolution-data-server/src/calendar/backends/webdav-notes/e-cal-backend-webdav-notes.c"
, 565, ((const char*) (__func__)), "nfo->object == NULL");
} while (0)
;
566
567 nfo->object = i_cal_component_as_ical_string (icomp);
568
569 g_object_unref (icomp);
570 } else { /* !resource */
571 g_warn_if_reached ()do { g_warn_message ("e-cal-backend-webdav-notes", "/builds/GNOME/evolution-data-server/src/calendar/backends/webdav-notes/e-cal-backend-webdav-notes.c"
, 571, ((const char*) (__func__)), ((void*)0)); } while (0)
;
572 }
573 }
574
575 g_free (etag);
576 g_free (bytes);
577 }
578
579 return success;
580}
581
582static gchar *
583ecb_webdav_notes_href_to_uid (const gchar *href)
584{
585 const gchar *filename;
586
587 if (!href || !*href)
588 return NULL((void*)0);
589
590 filename = strrchr (href, '/');
591
592 if (filename && filename[1])
593 return g_uri_unescape_string (filename + 1, NULL((void*)0));
594
595 return g_uri_unescape_string (href, NULL((void*)0));
596}
597
598static gboolean
599ecb_webdav_notes_get_changes_sync (ECalMetaBackend *meta_backend,
600 const gchar *last_sync_tag,
601 gboolean is_repeat,
602 gchar **out_new_sync_tag,
603 gboolean *out_repeat,
604 GSList **out_created_objects,
605 GSList **out_modified_objects,
606 GSList **out_removed_objects,
607 GCancellable *cancellable,
608 GError **error)
609{
610 ECalBackendWebDAVNotes *cbnotes;
611 EWebDAVSession *webdav;
612 GHashTable *known_items; /* gchar *href ~> ECalMetaBackendInfo * */
613 GHashTable *resources_hash; /* gchar *href ~> EWebDAVResource *, both borrowed from 'resources' GSList */
614 GHashTableIter iter;
615 GSList *resources = NULL((void*)0), *link;
616 gpointer key = NULL((void*)0), value = NULL((void*)0);
617 gboolean success;
618 GError *local_error = NULL((void*)0);
619
620 g_return_val_if_fail (E_IS_CAL_BACKEND_WEBDAV_NOTES (meta_backend), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_81
= 0; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((meta_backend)); GType __t = ((e_cal_backend_webdav_notes_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_81 = 1; _g_boolean_var_81; }), 1)
)) { } else { g_return_if_fail_warning ("e-cal-backend-webdav-notes"
, ((const char*) (__func__)), "E_IS_CAL_BACKEND_WEBDAV_NOTES (meta_backend)"
); return ((0)); } } while (0)
;
621 g_return_val_if_fail (out_new_sync_tag, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_82
= 0; if (out_new_sync_tag) _g_boolean_var_82 = 1; _g_boolean_var_82
; }), 1))) { } else { g_return_if_fail_warning ("e-cal-backend-webdav-notes"
, ((const char*) (__func__)), "out_new_sync_tag"); return ((0
)); } } while (0)
;
622 g_return_val_if_fail (out_created_objects, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_83
= 0; if (out_created_objects) _g_boolean_var_83 = 1; _g_boolean_var_83
; }), 1))) { } else { g_return_if_fail_warning ("e-cal-backend-webdav-notes"
, ((const char*) (__func__)), "out_created_objects"); return (
(0)); } } while (0)
;
623 g_return_val_if_fail (out_modified_objects, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_84
= 0; if (out_modified_objects) _g_boolean_var_84 = 1; _g_boolean_var_84
; }), 1))) { } else { g_return_if_fail_warning ("e-cal-backend-webdav-notes"
, ((const char*) (__func__)), "out_modified_objects"); return
((0)); } } while (0)
;
624 g_return_val_if_fail (out_removed_objects, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_85
= 0; if (out_removed_objects) _g_boolean_var_85 = 1; _g_boolean_var_85
; }), 1))) { } else { g_return_if_fail_warning ("e-cal-backend-webdav-notes"
, ((const char*) (__func__)), "out_removed_objects"); return (
(0)); } } while (0)
;
625
626 *out_new_sync_tag = NULL((void*)0);
627 *out_created_objects = NULL((void*)0);
628 *out_modified_objects = NULL((void*)0);
629 *out_removed_objects = NULL((void*)0);
630
631 cbnotes = E_CAL_BACKEND_WEBDAV_NOTES (meta_backend)((((ECalBackendWebDAVNotes*) (void *) ((meta_backend)))));
632 webdav = ecb_webdav_notes_ref_session (cbnotes);
633
634 if (cbnotes->priv->etag_supported) {
635 gchar *new_sync_tag = NULL((void*)0);
636
637 success = ecb_webdav_notes_getetag_sync (webdav, NULL((void*)0), &new_sync_tag, cancellable, NULL((void*)0));
638 if (!success) {
639 cbnotes->priv->etag_supported = g_cancellable_set_error_if_cancelled (cancellable, error);
640 if (cbnotes->priv->etag_supported || !webdav) {
641 g_clear_object (&webdav)do { _Static_assert (sizeof *((&webdav)) == sizeof (gpointer
), "Expression evaluates to false"); __typeof__ (((&webdav
))) _pp = ((&webdav)); __typeof__ (*((&webdav))) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_object_unref) (_ptr)
; } while (0)
;
642 return FALSE(0);
643 }
644 } else if (new_sync_tag && last_sync_tag && g_strcmp0 (last_sync_tag, new_sync_tag) == 0) {
645 *out_new_sync_tag = new_sync_tag;
646 g_clear_object (&webdav)do { _Static_assert (sizeof *((&webdav)) == sizeof (gpointer
), "Expression evaluates to false"); __typeof__ (((&webdav
))) _pp = ((&webdav)); __typeof__ (*((&webdav))) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_object_unref) (_ptr)
; } while (0)
;
647 return TRUE(!(0));
648 }
649
650 *out_new_sync_tag = new_sync_tag;
651 }
652
653 known_items = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, e_cal_meta_backend_info_free);
654 resources_hash = g_hash_table_new (g_str_hash, g_str_equal);
655
656 success = e_webdav_session_list_sync (webdav, NULL((void*)0), E_WEBDAV_DEPTH_THIS_AND_CHILDREN"1",
657 E_WEBDAV_LIST_ETAG | E_WEBDAV_LIST_DISPLAY_NAME | E_WEBDAV_LIST_CREATION_DATE | E_WEBDAV_LIST_LAST_MODIFIED,
658 &resources, cancellable, &local_error);
659
660 if (success) {
661 ECalCache *cal_cache;
662 WebDAVNotesChangesData ccd;
663
664 for (link = resources; link; link = g_slist_next (link)((link) ? (((GSList *)(link))->next) : ((void*)0))) {
665 EWebDAVResource *resource = link->data;
666
667 if (resource && resource->kind == E_WEBDAV_RESOURCE_KIND_RESOURCE && resource->href &&
668 ecb_webdav_notes_has_supported_extension (resource->href, NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0))) {
669 gchar *filename = ecb_webdav_notes_href_to_uid (resource->href);
670
671 g_hash_table_insert (known_items, g_strdup (resource->href)g_strdup_inline (resource->href),
672 e_cal_meta_backend_info_new (filename, resource->etag, NULL((void*)0), resource->href));
673
674 g_hash_table_insert (resources_hash, resource->href, resource);
675
676 g_free (filename);
677 }
678 }
679
680 ccd.out_modified_objects = out_modified_objects;
681 ccd.out_removed_objects = out_removed_objects;
682 ccd.known_items = known_items;
683
684 cal_cache = e_cal_meta_backend_ref_cache (meta_backend);
685
686 success = e_cal_cache_search_with_callback (cal_cache, NULL((void*)0), ecb_webdav_notes_search_changes_cb, &ccd, cancellable, &local_error);
687
688 g_clear_object (&cal_cache)do { _Static_assert (sizeof *((&cal_cache)) == sizeof (gpointer
), "Expression evaluates to false"); __typeof__ (((&cal_cache
))) _pp = ((&cal_cache)); __typeof__ (*((&cal_cache))
) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_object_unref) (
_ptr); } while (0)
;
689 }
690
691 if (success) {
692 g_hash_table_iter_init (&iter, known_items);
693 while (g_hash_table_iter_next (&iter, &key, &value)) {
694 *out_created_objects = g_slist_prepend (*out_created_objects, e_cal_meta_backend_info_copy (value));
695 }
696 }
697
698 g_hash_table_destroy (known_items);
699
700 if (success && (*out_created_objects || *out_modified_objects)) {
701 success = ecb_webdav_notes_get_objects_sync (webdav, resources_hash, *out_created_objects, cancellable, &local_error);
702 success = success && ecb_webdav_notes_get_objects_sync (webdav, resources_hash, *out_modified_objects, cancellable, &local_error);
703 }
704
705 if (local_error) {
706 ecb_webdav_notes_check_credentials_error (cbnotes, webdav, local_error);
707 g_propagate_error (error, local_error);
708 }
709
710 g_slist_free_full (resources, e_webdav_resource_free);
711 g_hash_table_destroy (resources_hash);
712 g_clear_object (&webdav)do { _Static_assert (sizeof *((&webdav)) == sizeof (gpointer
), "Expression evaluates to false"); __typeof__ (((&webdav
))) _pp = ((&webdav)); __typeof__ (*((&webdav))) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_object_unref) (_ptr)
; } while (0)
;
713
714 return success;
715}
716
717static gboolean
718ecb_webdav_notes_list_existing_sync (ECalMetaBackend *meta_backend,
719 gchar **out_new_sync_tag,
720 GSList **out_existing_objects,
721 GCancellable *cancellable,
722 GError **error)
723{
724 ECalBackendWebDAVNotes *cbnotes;
725 EWebDAVSession *webdav;
726 GSList *resources = NULL((void*)0);
727 GError *local_error = NULL((void*)0);
728 gboolean success;
729
730 g_return_val_if_fail (E_IS_CAL_BACKEND_WEBDAV_NOTES (meta_backend), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_86
= 0; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((meta_backend)); GType __t = ((e_cal_backend_webdav_notes_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_86 = 1; _g_boolean_var_86; }), 1)
)) { } else { g_return_if_fail_warning ("e-cal-backend-webdav-notes"
, ((const char*) (__func__)), "E_IS_CAL_BACKEND_WEBDAV_NOTES (meta_backend)"
); return ((0)); } } while (0)
;
731 g_return_val_if_fail (out_existing_objects != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_87
= 0; if (out_existing_objects != ((void*)0)) _g_boolean_var_87
= 1; _g_boolean_var_87; }), 1))) { } else { g_return_if_fail_warning
("e-cal-backend-webdav-notes", ((const char*) (__func__)), "out_existing_objects != NULL"
); return ((0)); } } while (0)
;
732
733 *out_existing_objects = NULL((void*)0);
734
735 cbnotes = E_CAL_BACKEND_WEBDAV_NOTES (meta_backend)((((ECalBackendWebDAVNotes*) (void *) ((meta_backend)))));
736 webdav = ecb_webdav_notes_ref_session (cbnotes);
737
738 success = e_webdav_session_list_sync (webdav, NULL((void*)0), E_WEBDAV_DEPTH_THIS_AND_CHILDREN"1", E_WEBDAV_LIST_ETAG, &resources, cancellable, &local_error);
739
740 if (success) {
741 GSList *link;
742
743 for (link = resources; link; link = g_slist_next (link)((link) ? (((GSList *)(link))->next) : ((void*)0))) {
744 EWebDAVResource *resource = link->data;
745
746 if (resource && resource->kind == E_WEBDAV_RESOURCE_KIND_RESOURCE && resource->href &&
747 ecb_webdav_notes_has_supported_extension (resource->href, NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0))) {
748 gchar *filename = ecb_webdav_notes_href_to_uid (resource->href);
749
750 *out_existing_objects = g_slist_prepend (*out_existing_objects,
751 e_cal_meta_backend_info_new (filename, resource->etag, NULL((void*)0), resource->href));
752
753 g_free (filename);
754 }
755 }
756
757 *out_existing_objects = g_slist_reverse (*out_existing_objects);
758 }
759
760 if (local_error) {
761 ecb_webdav_notes_check_credentials_error (cbnotes, webdav, local_error);
762 g_propagate_error (error, local_error);
763 }
764
765 g_slist_free_full (resources, e_webdav_resource_free);
766 g_clear_object (&webdav)do { _Static_assert (sizeof *((&webdav)) == sizeof (gpointer
), "Expression evaluates to false"); __typeof__ (((&webdav
))) _pp = ((&webdav)); __typeof__ (*((&webdav))) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_object_unref) (_ptr)
; } while (0)
;
767
768 return success;
769}
770
771static gchar *
772ecb_webdav_notes_uid_to_uri (ECalBackendWebDAVNotes *cbnotes,
773 const gchar *uid)
774{
775 ESourceWebdav *webdav_extension;
776 GUri *parsed_uri;
777 gchar *uri, *tmp, *filename, *uid_hash = NULL((void*)0);
778
779 g_return_val_if_fail (E_IS_CAL_BACKEND_WEBDAV_NOTES (cbnotes), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_88
= 0; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((cbnotes)); GType __t = ((e_cal_backend_webdav_notes_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_88 = 1; _g_boolean_var_88; }), 1)
)) { } else { g_return_if_fail_warning ("e-cal-backend-webdav-notes"
, ((const char*) (__func__)), "E_IS_CAL_BACKEND_WEBDAV_NOTES (cbnotes)"
); return (((void*)0)); } } while (0)
;
780 g_return_val_if_fail (uid != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_89
= 0; if (uid != ((void*)0)) _g_boolean_var_89 = 1; _g_boolean_var_89
; }), 1))) { } else { g_return_if_fail_warning ("e-cal-backend-webdav-notes"
, ((const char*) (__func__)), "uid != NULL"); return (((void*
)0)); } } while (0)
;
781
782 webdav_extension = e_source_get_extension (e_backend_get_source (E_BACKEND (cbnotes)((((EBackend*) (void *) ((cbnotes)))))), E_SOURCE_EXTENSION_WEBDAV_BACKEND"WebDAV Backend");
783 parsed_uri = e_source_webdav_dup_uri (webdav_extension);
784 g_return_val_if_fail (parsed_uri != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_90
= 0; if (parsed_uri != ((void*)0)) _g_boolean_var_90 = 1; _g_boolean_var_90
; }), 1))) { } else { g_return_if_fail_warning ("e-cal-backend-webdav-notes"
, ((const char*) (__func__)), "parsed_uri != NULL"); return (
((void*)0)); } } while (0)
;
785
786 /* UIDs with forward slashes can cause trouble, because the destination server can
787 consider them as a path delimiter. Double-encode the URL doesn't always work,
788 thus rather cause a mismatch between stored UID and its href on the server. */
789 if (strchr (uid, '/')) {
790 uid_hash = g_compute_checksum_for_string (G_CHECKSUM_SHA1, uid, -1);
791
792 if (uid_hash)
793 uid = uid_hash;
794 }
795
796 filename = g_uri_escape_string (uid, NULL((void*)0), FALSE(0));
797
798 if (*g_uri_get_path (parsed_uri)) {
799 const gchar *slash = strrchr (g_uri_get_path (parsed_uri), '/');
800
801 if (slash && !slash[1])
802 tmp = g_strconcat (g_uri_get_path (parsed_uri), filename, NULL((void*)0));
803 else
804 tmp = g_strconcat (g_uri_get_path (parsed_uri), "/", filename, NULL((void*)0));
805 } else
806 tmp = g_strconcat ("/", filename, NULL((void*)0));
807
808 e_util_change_uri_component (&parsed_uri, SOUP_URI_PATH, tmp);
809 uri = g_uri_to_string_partial (parsed_uri, G_URI_HIDE_USERINFO | G_URI_HIDE_PASSWORD);
810
811 g_uri_unref (parsed_uri);
812 g_free (filename);
813 g_free (uid_hash);
814
815 return uri;
816}
817
818static void
819ecb_webdav_notes_store_component_etag (ICalComponent *icomp,
820 const gchar *etag)
821{
822 ICalComponent *subcomp;
823
824 g_return_if_fail (icomp != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_91
= 0; if (icomp != ((void*)0)) _g_boolean_var_91 = 1; _g_boolean_var_91
; }), 1))) { } else { g_return_if_fail_warning ("e-cal-backend-webdav-notes"
, ((const char*) (__func__)), "icomp != NULL"); return; } } while
(0)
;
825 g_return_if_fail (etag != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_92
= 0; if (etag != ((void*)0)) _g_boolean_var_92 = 1; _g_boolean_var_92
; }), 1))) { } else { g_return_if_fail_warning ("e-cal-backend-webdav-notes"
, ((const char*) (__func__)), "etag != NULL"); return; } } while
(0)
;
826
827 e_cal_util_component_set_x_property (icomp, E_WEBDAV_NOTES_X_ETAG"X-EVOLUTION-WEBDAV-NOTES-ETAG", etag);
828
829 for (subcomp = i_cal_component_get_first_component (icomp, I_CAL_ANY_COMPONENT);
830 subcomp;
831 g_object_unref (subcomp), subcomp = i_cal_component_get_next_component (icomp, I_CAL_ANY_COMPONENT)) {
832 ICalComponentKind kind = i_cal_component_isa (subcomp);
833
834 if (kind == I_CAL_VJOURNAL_COMPONENT) {
835 e_cal_util_component_set_x_property (subcomp, E_WEBDAV_NOTES_X_ETAG"X-EVOLUTION-WEBDAV-NOTES-ETAG", etag);
836 }
837 }
838}
839
840static gboolean
841ecb_webdav_notes_load_component_sync (ECalMetaBackend *meta_backend,
842 const gchar *uid,
843 const gchar *extra,
844 ICalComponent **out_component,
845 gchar **out_extra,
846 GCancellable *cancellable,
847 GError **error)
848{
849 ECalBackendWebDAVNotes *cbnotes;
850 EWebDAVSession *webdav;
851 EWebDAVResource *use_resource = NULL((void*)0);
852 gchar *uri = NULL((void*)0), *href = NULL((void*)0), *etag = NULL((void*)0), *bytes = NULL((void*)0);
853 gsize length = -1;
854 gboolean success = FALSE(0);
855 GError *local_error = NULL((void*)0);
856
857 g_return_val_if_fail (E_IS_CAL_BACKEND_WEBDAV_NOTES (meta_backend), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_93
= 0; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((meta_backend)); GType __t = ((e_cal_backend_webdav_notes_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_93 = 1; _g_boolean_var_93; }), 1)
)) { } else { g_return_if_fail_warning ("e-cal-backend-webdav-notes"
, ((const char*) (__func__)), "E_IS_CAL_BACKEND_WEBDAV_NOTES (meta_backend)"
); return ((0)); } } while (0)
;
858 g_return_val_if_fail (uid != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_94
= 0; if (uid != ((void*)0)) _g_boolean_var_94 = 1; _g_boolean_var_94
; }), 1))) { } else { g_return_if_fail_warning ("e-cal-backend-webdav-notes"
, ((const char*) (__func__)), "uid != NULL"); return ((0)); }
} while (0)
;
859 g_return_val_if_fail (out_component != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_95
= 0; if (out_component != ((void*)0)) _g_boolean_var_95 = 1;
_g_boolean_var_95; }), 1))) { } else { g_return_if_fail_warning
("e-cal-backend-webdav-notes", ((const char*) (__func__)), "out_component != NULL"
); return ((0)); } } while (0)
;
860 g_return_val_if_fail (out_extra != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_96
= 0; if (out_extra != ((void*)0)) _g_boolean_var_96 = 1; _g_boolean_var_96
; }), 1))) { } else { g_return_if_fail_warning ("e-cal-backend-webdav-notes"
, ((const char*) (__func__)), "out_extra != NULL"); return ((
0)); } } while (0)
;
861
862 cbnotes = E_CAL_BACKEND_WEBDAV_NOTES (meta_backend)((((ECalBackendWebDAVNotes*) (void *) ((meta_backend)))));
863
864 /* When called immediately after save and the server didn't change the component,
865 then the 'extra' contains "href" + "\n" + "vCalendar", to avoid unneeded GET
866 from the server. */
867 if (extra && *extra) {
868 const gchar *newline;
869
870 newline = strchr (extra, '\n');
871 if (newline && newline[1] && newline != extra) {
872 ICalComponent *vcalendar;
873
874 vcalendar = i_cal_component_new_from_string (newline + 1);
875 if (vcalendar) {
876 *out_extra = g_strndup (extra, newline - extra);
877 *out_component = vcalendar;
878
879 return TRUE(!(0));
880 }
881 }
882 }
883
884 webdav = ecb_webdav_notes_ref_session (cbnotes);
885
886 if (extra && *extra) {
887 uri = g_strdup (extra)g_strdup_inline (extra);
888
889 success = e_webdav_session_get_data_sync (webdav, uri, &href, &etag, NULL((void*)0), &bytes, &length, cancellable, &local_error);
890
891 if (!success) {
892 g_free (uri);
893 uri = NULL((void*)0);
894 }
895 }
896
897 if (!success && cbnotes->priv->etag_supported) {
898 gchar *new_sync_tag = NULL((void*)0);
899
900 if (ecb_webdav_notes_getetag_sync (webdav, NULL((void*)0), &new_sync_tag, cancellable, NULL((void*)0)) && new_sync_tag) {
901 gchar *last_sync_tag;
902
903 last_sync_tag = e_cal_meta_backend_dup_sync_tag (meta_backend);
904
905 /* The calendar didn't change, thus the component cannot be there */
906 if (g_strcmp0 (last_sync_tag, new_sync_tag) == 0) {
907 g_clear_error (&local_error);
908 g_clear_object (&webdav)do { _Static_assert (sizeof *((&webdav)) == sizeof (gpointer
), "Expression evaluates to false"); __typeof__ (((&webdav
))) _pp = ((&webdav)); __typeof__ (*((&webdav))) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_object_unref) (_ptr)
; } while (0)
;
909 g_free (last_sync_tag);
910 g_free (new_sync_tag);
911
912 g_propagate_error (error, ECC_ERROR (E_CAL_CLIENT_ERROR_OBJECT_NOT_FOUND)e_cal_client_error_create (E_CAL_CLIENT_ERROR_OBJECT_NOT_FOUND
, ((void*)0))
);
913
914 return FALSE(0);
915 }
916
917 g_free (last_sync_tag);
918 }
919
920 g_free (new_sync_tag);
921 }
922
923 if (!success) {
924 uri = ecb_webdav_notes_uid_to_uri (cbnotes, uid);
925 g_return_val_if_fail (uri != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_97
= 0; if (uri != ((void*)0)) _g_boolean_var_97 = 1; _g_boolean_var_97
; }), 1))) { } else { g_return_if_fail_warning ("e-cal-backend-webdav-notes"
, ((const char*) (__func__)), "uri != NULL"); return ((0)); }
} while (0)
;
926
927 g_clear_error (&local_error);
928
929 success = e_webdav_session_get_data_sync (webdav, uri, &href, &etag, NULL((void*)0), &bytes, &length, cancellable, &local_error);
930 }
931
932 if (success) {
933 GSList *resources = NULL((void*)0);
934
935 success = e_webdav_session_list_sync (webdav, href, E_WEBDAV_DEPTH_THIS"0",
936 E_WEBDAV_LIST_DISPLAY_NAME | E_WEBDAV_LIST_CREATION_DATE | E_WEBDAV_LIST_LAST_MODIFIED,
937 &resources, cancellable, &local_error);
938
939 if (success) {
940 GSList *link;
941
942 for (link = resources; link; link = g_slist_next (link)((link) ? (((GSList *)(link))->next) : ((void*)0))) {
943 EWebDAVResource *resource = link->data;
944
945 if (resource && resource->kind == E_WEBDAV_RESOURCE_KIND_RESOURCE && g_strcmp0 (resource->href, href) == 0) {
946 use_resource = resource;
947 link->data = NULL((void*)0);
948 break;
949 }
950 }
951
952 g_slist_free_full (resources, e_webdav_resource_free);
953
954 success = use_resource != NULL((void*)0);
955
956 if (!success)
957 local_error = ECC_ERROR (E_CAL_CLIENT_ERROR_OBJECT_NOT_FOUND)e_cal_client_error_create (E_CAL_CLIENT_ERROR_OBJECT_NOT_FOUND
, ((void*)0))
;
958 }
959 }
960
961 if (success) {
962 *out_component = NULL((void*)0);
963
964 if (href && etag && length != ((gsize) -1)) {
965 ICalComponent *icomp;
966 gchar *filename = ecb_webdav_notes_href_to_uid (use_resource->href);
967
968 icomp = ecb_webdav_notes_new_icomp (use_resource->creation_date,
969 use_resource->last_modified,
970 filename,
971 etag,
972 use_resource->display_name,
973 bytes);
974
975 g_free (filename);
976
977 if (icomp) {
978 ecb_webdav_notes_store_component_etag (icomp, etag);
979
980 *out_component = icomp;
981 }
982 }
983
984 if (!*out_component) {
985 success = FALSE(0);
986
987 if (!href)
988 g_propagate_error (&local_error, ECC_ERROR_EX (E_CAL_CLIENT_ERROR_INVALID_OBJECT, _("Server didn’t return object’s href"))e_cal_client_error_create (E_CAL_CLIENT_ERROR_INVALID_OBJECT,
((char *) g_dgettext ("evolution-data-server", "Server didn’t return object’s href"
)))
);
989 else if (!etag)
990 g_propagate_error (&local_error, ECC_ERROR_EX (E_CAL_CLIENT_ERROR_INVALID_OBJECT, _("Server didn’t return object’s ETag"))e_cal_client_error_create (E_CAL_CLIENT_ERROR_INVALID_OBJECT,
((char *) g_dgettext ("evolution-data-server", "Server didn’t return object’s ETag"
)))
);
991 else
992 g_propagate_error (&local_error, ECC_ERROR (E_CAL_CLIENT_ERROR_INVALID_OBJECT)e_cal_client_error_create (E_CAL_CLIENT_ERROR_INVALID_OBJECT,
((void*)0))
);
993 } else if (out_extra) {
994 *out_extra = g_strdup (href)g_strdup_inline (href);
995 }
996 }
997
998 e_webdav_resource_free (use_resource);
999 g_free (uri);
1000 g_free (href);
1001 g_free (etag);
1002 g_free (bytes);
1003
1004 if (local_error) {
1005 ecb_webdav_notes_check_credentials_error (cbnotes, webdav, local_error);
1006
1007 if (g_error_matches (local_error, E_SOUP_SESSION_ERROR(e_soup_session_error_quark()), SOUP_STATUS_NOT_FOUND)) {
1008 local_error->domain = E_CAL_CLIENT_ERRORe_cal_client_error_quark ();
1009 local_error->code = E_CAL_CLIENT_ERROR_OBJECT_NOT_FOUND;
1010 }
1011
1012 g_propagate_error (error, local_error);
1013 }
1014
1015 g_clear_object (&webdav)do { _Static_assert (sizeof *((&webdav)) == sizeof (gpointer
), "Expression evaluates to false"); __typeof__ (((&webdav
))) _pp = ((&webdav)); __typeof__ (*((&webdav))) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_object_unref) (_ptr)
; } while (0)
;
1016
1017 return success;
1018}
1019
1020/* A rough code to mimic what Nextcloud does, it's not accurate, but it's close
1021 enough to work similarly. It skips leading whitespaces and uses up to the first
1022 100 letters of the first non-empty line as the base file name. */
1023static gchar *
1024ecb_webdav_notes_construct_base_filename (const gchar *description)
1025{
1026 GString *base_filename;
1027 gunichar uchr;
1028 gboolean add_space = FALSE(0);
1029
1030 if (!description || !*description || !g_utf8_validate (description, -1, NULL((void*)0)))
1031 return g_strdup (_("New note"))g_strdup_inline (((char *) g_dgettext ("evolution-data-server"
, "New note")))
;
1032
1033 base_filename = g_string_sized_new (102);
1034
1035 while (uchr = g_utf8_get_char (description), g_unichar_isspace (uchr))
1036 description = g_utf8_next_char (description)((description) + g_utf8_skip[*(const guchar *)(description)]);
1037
1038 while (uchr = g_utf8_get_char (description), uchr && uchr != '\r' && uchr != '\n') {
1039 if (g_unichar_isspace (uchr)) {
1040 add_space = TRUE(!(0));
1041 } else if ((uchr >> 8) != 0 || !strchr ("\"/\\?:*|", (uchr & 0xFF))) {
1042 if (base_filename->len >= 98)
1043 break;
1044
1045 if (add_space) {
1046 g_string_append_c (base_filename, ' ')g_string_append_c_inline (base_filename, ' ');
1047 add_space = FALSE(0);
1048 }
1049
1050 g_string_append_unichar (base_filename, uchr);
1051
1052 if (base_filename->len >= 100)
1053 break;
1054 }
1055
1056 description = g_utf8_next_char (description)((description) + g_utf8_skip[*(const guchar *)(description)]);
1057 }
1058
1059 if (!base_filename->len)
1060 g_string_append (base_filename, _("New note"))(__builtin_constant_p (((char *) g_dgettext ("evolution-data-server"
, "New note"))) ? __extension__ ({ const char * const __val =
(((char *) g_dgettext ("evolution-data-server", "New note"))
); g_string_append_len_inline (base_filename, __val, (__builtin_expect
(__extension__ ({ int _g_boolean_var_98 = 0; if (__val != ((
void*)0)) _g_boolean_var_98 = 1; _g_boolean_var_98; }), 1)) ?
(gssize) strlen (((__val) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(base_filename, ((char *) g_dgettext ("evolution-data-server"
, "New note")), (gssize) -1))
;
1061
1062 return g_string_free (base_filename, FALSE(0));
1063}
1064
1065static gboolean
1066ecb_webdav_notes_save_component_sync (ECalMetaBackend *meta_backend,
1067 gboolean overwrite_existing,
1068 EConflictResolution conflict_resolution,
1069 const GSList *instances,
1070 const gchar *extra,
1071 ECalOperationFlags opflags,
1072 gchar **out_new_uid,
1073 gchar **out_new_extra,
1074 GCancellable *cancellable,
1075 GError **error)
1076{
1077 ECalBackendWebDAVNotes *cbnotes;
1078 EWebDAVSession *webdav;
1079 ICalComponent *icomp;
1080 gchar *href = NULL((void*)0), *etag = NULL((void*)0);
1081 const gchar *description = NULL((void*)0), *uid = NULL((void*)0);
1082 gboolean success;
1083 GError *local_error = NULL((void*)0);
1084
1085 g_return_val_if_fail (E_IS_CAL_BACKEND_WEBDAV_NOTES (meta_backend), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_99
= 0; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((meta_backend)); GType __t = ((e_cal_backend_webdav_notes_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_99 = 1; _g_boolean_var_99; }), 1)
)) { } else { g_return_if_fail_warning ("e-cal-backend-webdav-notes"
, ((const char*) (__func__)), "E_IS_CAL_BACKEND_WEBDAV_NOTES (meta_backend)"
); return ((0)); } } while (0)
;
1
Assuming '__inst' is non-null
2
Taking false branch
3
Assuming field 'g_class' is null
4
Assuming the condition is true
5
Taking true branch
6
Taking true branch
7
Loop condition is false. Exiting loop
1086 g_return_val_if_fail (instances != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_100
= 0; if (instances != ((void*)0)) _g_boolean_var_100 = 1; _g_boolean_var_100
; }), 1))) { } else { g_return_if_fail_warning ("e-cal-backend-webdav-notes"
, ((const char*) (__func__)), "instances != NULL"); return ((
0)); } } while (0)
;
8
Assuming 'instances' is not equal to null
9
Taking true branch
10
Taking true branch
11
Loop condition is false. Exiting loop
1087 g_return_val_if_fail (instances->data != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_101
= 0; if (instances->data != ((void*)0)) _g_boolean_var_101
= 1; _g_boolean_var_101; }), 1))) { } else { g_return_if_fail_warning
("e-cal-backend-webdav-notes", ((const char*) (__func__)), "instances->data != NULL"
); return ((0)); } } while (0)
;
12
Assuming field 'data' is not equal to null
13
Taking true branch
14
Taking true branch
15
Loop condition is false. Exiting loop
1088 g_return_val_if_fail (instances->next == NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_102
= 0; if (instances->next == ((void*)0)) _g_boolean_var_102
= 1; _g_boolean_var_102; }), 1))) { } else { g_return_if_fail_warning
("e-cal-backend-webdav-notes", ((const char*) (__func__)), "instances->next == NULL"
); return ((0)); } } while (0)
;
16
Assuming field 'next' is equal to null
17
Taking true branch
18
Taking true branch
19
Loop condition is false. Exiting loop
1089 g_return_val_if_fail (out_new_uid, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_103
= 0; if (out_new_uid) _g_boolean_var_103 = 1; _g_boolean_var_103
; }), 1))) { } else { g_return_if_fail_warning ("e-cal-backend-webdav-notes"
, ((const char*) (__func__)), "out_new_uid"); return ((0)); }
} while (0)
;
20
Assuming 'out_new_uid' is non-null
21
Taking true branch
22
Taking true branch
23
Loop condition is false. Exiting loop
1090 g_return_val_if_fail (out_new_extra, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_104
= 0; if (out_new_extra) _g_boolean_var_104 = 1; _g_boolean_var_104
; }), 1))) { } else { g_return_if_fail_warning ("e-cal-backend-webdav-notes"
, ((const char*) (__func__)), "out_new_extra"); return ((0));
} } while (0)
;
24
Assuming 'out_new_extra' is non-null
25
Taking true branch
26
Taking true branch
27
Loop condition is false. Exiting loop
1091
1092 icomp = e_cal_component_get_icalcomponent (instances->data);
1093 g_return_val_if_fail (i_cal_component_isa (icomp) == I_CAL_VJOURNAL_COMPONENT, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_105
= 0; if (i_cal_component_isa (icomp) == I_CAL_VJOURNAL_COMPONENT
) _g_boolean_var_105 = 1; _g_boolean_var_105; }), 1))) { } else
{ g_return_if_fail_warning ("e-cal-backend-webdav-notes", ((
const char*) (__func__)), "i_cal_component_isa (icomp) == I_CAL_VJOURNAL_COMPONENT"
); return ((0)); } } while (0)
;
28
Assuming the condition is true
29
Taking true branch
30
Taking true branch
31
Loop condition is false. Exiting loop
1094
1095 cbnotes = E_CAL_BACKEND_WEBDAV_NOTES (meta_backend)((((ECalBackendWebDAVNotes*) (void *) ((meta_backend)))));
1096
1097 description = i_cal_component_get_description (icomp);
1098 etag = e_cal_util_component_dup_x_property (icomp, E_WEBDAV_NOTES_X_ETAG"X-EVOLUTION-WEBDAV-NOTES-ETAG");
1099 uid = i_cal_component_get_uid (icomp);
1100
1101 webdav = ecb_webdav_notes_ref_session (cbnotes);
1102
1103 if (uid && (!overwrite_existing || (extra && *extra))) {
32
Assuming 'uid' is non-null
33
Assuming 'overwrite_existing' is not equal to 0
34
Assuming 'extra' is non-null
35
Assuming the condition is true
36
Taking true branch
1104 gchar *new_extra = NULL((void*)0), *new_etag = NULL((void*)0);
1105 gchar *base_filename, *expected_filename = NULL((void*)0);
1106 gboolean force_write = FALSE(0), new_filename = FALSE(0);
1107 guint counter = 1;
1108 const gchar *use_ext = NULL((void*)0), *use_ext_num_suffix = NULL((void*)0), *use_content_type = NULL((void*)0);
1109 gint ext_len = 0;
1110
1111 base_filename = ecb_webdav_notes_construct_base_filename (description);
1112 if (!ecb_webdav_notes_has_supported_extension (uid, &ext_len, &use_ext, &use_ext_num_suffix, &use_content_type)) {
37
Taking false branch
1113 ESource *source;
1114 ESourceWebDAVNotes *notes_extension;
1115 const gchar *default_ext;
1116
1117 source = e_backend_get_source (E_BACKEND (meta_backend)((((EBackend*) (void *) ((meta_backend))))));
1118 notes_extension = e_source_get_extension (source, E_SOURCE_EXTENSION_WEBDAV_NOTES"WebDAV Notes");
1119
1120 e_source_extension_property_lock (E_SOURCE_EXTENSION (notes_extension)((((ESourceExtension*) (void *) ((notes_extension))))));
1121 default_ext = e_source_webdav_notes_get_default_ext (notes_extension);
1122
1123 if (!ecb_webdav_notes_has_supported_extension (default_ext, &ext_len, &use_ext, &use_ext_num_suffix, &use_content_type)) {
1124 /* Fallback to the markdown format in case of broken setup */
1125 g_warn_if_fail (ecb_webdav_notes_has_supported_extension (".md", &ext_len, &use_ext, &use_ext_num_suffix, &use_content_type))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_106
= 0; if (ecb_webdav_notes_has_supported_extension (".md", &
ext_len, &use_ext, &use_ext_num_suffix, &use_content_type
)) _g_boolean_var_106 = 1; _g_boolean_var_106; }), 1)) ; else
g_warn_message ("e-cal-backend-webdav-notes", "/builds/GNOME/evolution-data-server/src/calendar/backends/webdav-notes/e-cal-backend-webdav-notes.c"
, 1125, ((const char*) (__func__)), "ecb_webdav_notes_has_supported_extension (\".md\", &ext_len, &use_ext, &use_ext_num_suffix, &use_content_type)"
); } while (0)
;
1126 }
1127
1128 e_source_extension_property_unlock (E_SOURCE_EXTENSION (notes_extension)((((ESourceExtension*) (void *) ((notes_extension))))));
1129 }
1130
1131 expected_filename = g_strconcat (base_filename, use_ext, NULL((void*)0));
38
Value assigned to 'expected_filename'
1132
1133 if (overwrite_existing
38.1
'overwrite_existing' is not equal to 0
) {
39
Taking true branch
1134 switch (conflict_resolution) {
40
Control jumps to 'case E_CONFLICT_RESOLUTION_WRITE_COPY:' at line 1138
1135 case E_CONFLICT_RESOLUTION_FAIL:
1136 case E_CONFLICT_RESOLUTION_USE_NEWER:
1137 case E_CONFLICT_RESOLUTION_KEEP_SERVER:
1138 case E_CONFLICT_RESOLUTION_WRITE_COPY:
1139 break;
1140 case E_CONFLICT_RESOLUTION_KEEP_LOCAL:
1141 force_write = TRUE(!(0));
1142 break;
1143 }
1144 }
1145
1146 new_filename = g_strcmp0 (expected_filename, uid) != 0;
41
Assuming the condition is true
1147
1148 /* Checks whether the saved file on the server is already with the "(nnn)" suffix */
1149 if (new_filename
41.1
'new_filename' is 1
&& expected_filename
&& uid &&
42
Assuming pointer value is null
43
Assuming 'expected_filename' is null
1150 g_str_has_suffix (uid, use_ext_num_suffix)(__builtin_constant_p (use_ext_num_suffix)? __extension__ ({ const
char * const __str = (uid); const char * const __suffix = (use_ext_num_suffix
); gboolean __result = (0); if (__builtin_expect (__extension__
({ int _g_boolean_var_107 = 0; if (__str == ((void*)0) || __suffix
== ((void*)0)) _g_boolean_var_107 = 1; _g_boolean_var_107; }
), 0)) __result = (g_str_has_suffix) (__str, __suffix); else {
const size_t __str_len = strlen (((__str) + !(__str))); const
size_t __suffix_len = strlen (((__suffix) + !(__suffix))); if
(__str_len >= __suffix_len) __result = memcmp (__str + __str_len
- __suffix_len, ((__suffix) + !(__suffix)), __suffix_len) ==
0; } __result; }) : (g_str_has_suffix) (uid, use_ext_num_suffix
) )
&& g_ascii_strncasecmp (uid, expected_filename, strlen (expected_filename) - ext_len) == 0) {
1151 gint ii = strlen (expected_filename) - ext_len;
1152
1153 if (uid[ii] == ' ' && uid[ii + 1] == '(') {
1154 ii += 2;
1155
1156 while (uid[ii] >= '0' && uid[ii] <= '9')
1157 ii++;
1158
1159 if (g_strcmp0 (uid + ii, use_ext_num_suffix) == 0)
1160 new_filename = FALSE(0);
1161 }
1162 }
1163
1164 if (!extra
43.1
'extra' is non-null
|| !*extra || new_filename
43.2
'new_filename' is 1
) {
44
Taking true branch
1165 href = ecb_webdav_notes_uid_to_uri (cbnotes, expected_filename);
1166 uid = expected_filename;
45
Null pointer value stored to 'uid'
1167 force_write = FALSE(0);
1168 }
1169
1170 do {
1171 if (!counter
45.1
'counter' is 1
)
46
Taking false branch
1172 break;
1173
1174 g_clear_error (&local_error);
1175
1176 if (counter
46.1
'counter' is <= 1
> 1) {
47
Taking false branch
1177 g_free (expected_filename);
1178 expected_filename = g_strdup_printf ("%s (%u)%s", base_filename, counter, use_ext);
1179
1180 g_free (href);
1181 href = ecb_webdav_notes_uid_to_uri (cbnotes, expected_filename);
1182
1183 uid = expected_filename;
1184 }
1185
1186 success = e_webdav_session_put_data_sync (webdav, (!new_filename
47.1
'new_filename' is 1
&& extra && *extra) ? extra : href,
1187 force_write
47.2
'force_write' is 0
? "" : (overwrite_existing
47.3
'overwrite_existing' is not equal to 0
&& !new_filename
47.4
'new_filename' is 1
) ? etag : NULL((void*)0), use_content_type,
48
'?' condition is false
1188 NULL((void*)0), description
48.1
'description' is non-null
? description : "", -1, &new_extra, &new_etag, NULL((void*)0), cancellable, &local_error);
49
'?' condition is true
1189
1190 counter++;
1191 } while (!success && new_filename && !g_cancellable_is_cancelled (cancellable) &&
50
Assuming 'success' is not equal to 0
1192 g_error_matches (local_error, E_SOUP_SESSION_ERROR(e_soup_session_error_quark()), SOUP_STATUS_PRECONDITION_FAILED));
1193
1194 if (success
50.1
'success' is not equal to 0
&& new_filename
50.2
'new_filename' is 1
&& extra
50.3
'extra' is non-null
&& *extra) {
51
Taking true branch
1195 /* The name on the server changed, remove the old file */
1196 e_webdav_session_delete_sync (webdav, extra, E_WEBDAV_DEPTH_THIS"0", etag, cancellable, NULL((void*)0));
1197 }
1198
1199 if (success
51.1
'success' is not equal to 0
) {
52
Taking true branch
1200 ICalComponent *icomp_copy = NULL((void*)0);
1201
1202 /* Only if both are returned and it's not a weak ETag */
1203 if (new_extra && *new_extra && new_etag && *new_etag &&
53
Assuming 'new_extra' is non-null
54
Assuming the condition is true
55
Assuming 'new_etag' is non-null
56
Assuming the condition is true
58
Taking true branch
1204 g_ascii_strncasecmp (new_etag, "W/", 2) != 0) {
57
Assuming the condition is true
1205 gchar *tmp = NULL((void*)0);
1206 glong now = (glong) time (NULL((void*)0));
1207 gint len = 0;
1208
1209 if (ecb_webdav_notes_has_supported_extension (uid, &len, NULL((void*)0), NULL((void*)0), NULL((void*)0)))
59
Assuming the condition is true
60
Taking true branch
1210 tmp = g_strndup (uid, strlen (uid) - len);
61
Null pointer passed to 1st parameter expecting 'nonnull'
1211
1212 icomp_copy = ecb_webdav_notes_new_icomp (now, now, uid, new_etag,
1213 tmp ? tmp : uid, description);
1214
1215 g_free (tmp);
1216 } else if (out_new_extra && new_extra && *new_extra) {
1217 gchar *is_markdown_str;
1218
1219 is_markdown_str = e_cal_util_component_dup_x_property (icomp, E_WEBDAV_NOTES_X_IS_MARKDOWN"X-EVOLUTION-IS-MARKDOWN");
1220
1221 /* add or remove is-markdown notice, if needed */
1222 if (g_str_has_suffix (uid, ".md")(__builtin_constant_p (".md")? __extension__ ({ const char * const
__str = (uid); const char * const __suffix = (".md"); gboolean
__result = (0); if (__builtin_expect (__extension__ ({ int _g_boolean_var_108
= 0; if (__str == ((void*)0) || __suffix == ((void*)0)) _g_boolean_var_108
= 1; _g_boolean_var_108; }), 0)) __result = (g_str_has_suffix
) (__str, __suffix); else { const size_t __str_len = strlen (
((__str) + !(__str))); const size_t __suffix_len = strlen (((
__suffix) + !(__suffix))); if (__str_len >= __suffix_len) __result
= memcmp (__str + __str_len - __suffix_len, ((__suffix) + !(
__suffix)), __suffix_len) == 0; } __result; }) : (g_str_has_suffix
) (uid, ".md") )
) {
1223 if (g_strcmp0 (is_markdown_str, "1") != 0) {
1224 icomp_copy = i_cal_component_clone (icomp);
1225 e_cal_util_component_set_x_property (icomp_copy, E_WEBDAV_NOTES_X_IS_MARKDOWN"X-EVOLUTION-IS-MARKDOWN", "1");
1226 }
1227 } else if (g_strcmp0 (is_markdown_str, "1") == 0) {
1228 icomp_copy = i_cal_component_clone (icomp);
1229 while (e_cal_util_component_remove_x_property (icomp_copy, E_WEBDAV_NOTES_X_IS_MARKDOWN"X-EVOLUTION-IS-MARKDOWN")) {
1230 /* remove all */
1231 }
1232 }
1233
1234 g_free (is_markdown_str);
1235 }
1236
1237 if (icomp_copy != NULL((void*)0)) {
1238 gchar *tmp, *ical_string;
1239
1240 ical_string = i_cal_component_as_ical_string (icomp_copy);
1241
1242 /* Encodes the href and the component into one string, which
1243 will be decoded in the load function */
1244 tmp = g_strconcat (new_extra, "\n", ical_string, NULL((void*)0));
1245 g_free (new_extra);
1246 new_extra = tmp;
1247
1248 g_object_unref (icomp_copy);
1249 g_free (ical_string);
1250 }
1251
1252 /* To read the component back, either from the new_extra
1253 or from the server, because the server could change it */
1254 *out_new_uid = g_strdup (uid)g_strdup_inline (uid);
1255
1256 if (out_new_extra)
1257 *out_new_extra = new_extra;
1258 else
1259 g_free (new_extra);
1260 }
1261
1262 g_free (base_filename);
1263 g_free (expected_filename);
1264 g_free (new_etag);
1265 } else if (uid) {
1266 ECalCache *cache;
1267
1268 cache = e_cal_meta_backend_ref_cache (meta_backend);
1269 success = FALSE(0);
1270
1271 g_propagate_error (error, e_cal_client_error_create_fmt (E_CAL_CLIENT_ERROR_INVALID_OBJECT,
1272 _("Missing information about component URL, local cache is possibly incomplete or broken. You can try to remove it and restart background evolution-data-server processes. Cache file: %s")((char *) g_dgettext ("evolution-data-server", "Missing information about component URL, local cache is possibly incomplete or broken. You can try to remove it and restart background evolution-data-server processes. Cache file: %s"
))
,
1273 e_cache_get_filename (E_CACHE (cache)((((ECache*) (void *) ((cache))))))));
1274
1275 g_clear_object (&cache)do { _Static_assert (sizeof *((&cache)) == sizeof (gpointer
), "Expression evaluates to false"); __typeof__ (((&cache
))) _pp = ((&cache)); __typeof__ (*((&cache))) _ptr =
*_pp; *_pp = ((void*)0); if (_ptr) (g_object_unref) (_ptr); }
while (0)
;
1276 } else {
1277 success = FALSE(0);
1278 g_propagate_error (error, ECC_ERROR (E_CAL_CLIENT_ERROR_INVALID_OBJECT)e_cal_client_error_create (E_CAL_CLIENT_ERROR_INVALID_OBJECT,
((void*)0))
);
1279 }
1280
1281 g_free (href);
1282 g_free (etag);
1283
1284 if (overwrite_existing && g_error_matches (local_error, E_SOUP_SESSION_ERROR(e_soup_session_error_quark()), SOUP_STATUS_PRECONDITION_FAILED)) {
1285 g_clear_error (&local_error);
1286
1287 /* Pretend success when using the serer version on conflict,
1288 the component will be updated during the refresh */
1289 if (conflict_resolution == E_CONFLICT_RESOLUTION_KEEP_SERVER)
1290 success = TRUE(!(0));
1291 else
1292 local_error = EC_ERROR (E_CLIENT_ERROR_OUT_OF_SYNC)e_client_error_create (E_CLIENT_ERROR_OUT_OF_SYNC, ((void*)0)
)
;
1293 }
1294
1295 if (local_error) {
1296 ecb_webdav_notes_check_credentials_error (cbnotes, webdav, local_error);
1297 g_propagate_error (error, local_error);
1298 }
1299
1300 g_clear_object (&webdav)do { _Static_assert (sizeof *((&webdav)) == sizeof (gpointer
), "Expression evaluates to false"); __typeof__ (((&webdav
))) _pp = ((&webdav)); __typeof__ (*((&webdav))) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_object_unref) (_ptr)
; } while (0)
;
1301
1302 return success;
1303}
1304
1305static gboolean
1306ecb_webdav_notes_remove_component_sync (ECalMetaBackend *meta_backend,
1307 EConflictResolution conflict_resolution,
1308 const gchar *uid,
1309 const gchar *extra,
1310 const gchar *object,
1311 ECalOperationFlags opflags,
1312 GCancellable *cancellable,
1313 GError **error)
1314{
1315 ECalBackendWebDAVNotes *cbnotes;
1316 EWebDAVSession *webdav;
1317 ICalComponent *icomp;
1318 gchar *etag = NULL((void*)0);
1319 gboolean success;
1320 GError *local_error = NULL((void*)0);
1321
1322 g_return_val_if_fail (E_IS_CAL_BACKEND_WEBDAV_NOTES (meta_backend), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_109
= 0; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((meta_backend)); GType __t = ((e_cal_backend_webdav_notes_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_109 = 1; _g_boolean_var_109; }), 1
))) { } else { g_return_if_fail_warning ("e-cal-backend-webdav-notes"
, ((const char*) (__func__)), "E_IS_CAL_BACKEND_WEBDAV_NOTES (meta_backend)"
); return ((0)); } } while (0)
;
1323 g_return_val_if_fail (uid != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_110
= 0; if (uid != ((void*)0)) _g_boolean_var_110 = 1; _g_boolean_var_110
; }), 1))) { } else { g_return_if_fail_warning ("e-cal-backend-webdav-notes"
, ((const char*) (__func__)), "uid != NULL"); return ((0)); }
} while (0)
;
1324 g_return_val_if_fail (object != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_111
= 0; if (object != ((void*)0)) _g_boolean_var_111 = 1; _g_boolean_var_111
; }), 1))) { } else { g_return_if_fail_warning ("e-cal-backend-webdav-notes"
, ((const char*) (__func__)), "object != NULL"); return ((0))
; } } while (0)
;
1325
1326 cbnotes = E_CAL_BACKEND_WEBDAV_NOTES (meta_backend)((((ECalBackendWebDAVNotes*) (void *) ((meta_backend)))));
1327
1328 if (!extra || !*extra) {
1329 g_propagate_error (error, ECC_ERROR (E_CAL_CLIENT_ERROR_INVALID_OBJECT)e_cal_client_error_create (E_CAL_CLIENT_ERROR_INVALID_OBJECT,
((void*)0))
);
1330 return FALSE(0);
1331 }
1332
1333 icomp = i_cal_component_new_from_string (object);
1334 if (!icomp) {
1335 g_propagate_error (error, ECC_ERROR (E_CAL_CLIENT_ERROR_INVALID_OBJECT)e_cal_client_error_create (E_CAL_CLIENT_ERROR_INVALID_OBJECT,
((void*)0))
);
1336 return FALSE(0);
1337 }
1338
1339 if (conflict_resolution == E_CONFLICT_RESOLUTION_FAIL)
1340 etag = e_cal_util_component_dup_x_property (icomp, E_WEBDAV_NOTES_X_ETAG"X-EVOLUTION-WEBDAV-NOTES-ETAG");
1341
1342 webdav = ecb_webdav_notes_ref_session (cbnotes);
1343
1344 success = e_webdav_session_delete_sync (webdav, extra,
1345 NULL((void*)0), etag, cancellable, &local_error);
1346
1347 g_object_unref (icomp);
1348 g_free (etag);
1349
1350 /* Ignore not found errors, this was a delete and the resource is gone.
1351 It can be that it had been deleted on the server by other application. */
1352 if (g_error_matches (local_error, E_SOUP_SESSION_ERROR(e_soup_session_error_quark()), SOUP_STATUS_NOT_FOUND)) {
1353 g_clear_error (&local_error);
1354 success = TRUE(!(0));
1355 } else if (g_error_matches (local_error, E_SOUP_SESSION_ERROR(e_soup_session_error_quark()), SOUP_STATUS_PRECONDITION_FAILED)) {
1356 g_clear_error (&local_error);
1357
1358 /* Pretend success when using the serer version on conflict,
1359 the component will be updated during the refresh */
1360 if (conflict_resolution == E_CONFLICT_RESOLUTION_KEEP_SERVER)
1361 success = TRUE(!(0));
1362 else
1363 local_error = EC_ERROR (E_CLIENT_ERROR_OUT_OF_SYNC)e_client_error_create (E_CLIENT_ERROR_OUT_OF_SYNC, ((void*)0)
)
;
1364 }
1365
1366 if (local_error) {
1367 ecb_webdav_notes_check_credentials_error (cbnotes, webdav, local_error);
1368 g_propagate_error (error, local_error);
1369 }
1370
1371 g_clear_object (&webdav)do { _Static_assert (sizeof *((&webdav)) == sizeof (gpointer
), "Expression evaluates to false"); __typeof__ (((&webdav
))) _pp = ((&webdav)); __typeof__ (*((&webdav))) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_object_unref) (_ptr)
; } while (0)
;
1372
1373 return success;
1374}
1375
1376static gboolean
1377ecb_webdav_notes_get_ssl_error_details (ECalMetaBackend *meta_backend,
1378 gchar **out_certificate_pem,
1379 GTlsCertificateFlags *out_certificate_errors)
1380{
1381 ECalBackendWebDAVNotes *cbnotes;
1382 EWebDAVSession *webdav;
1383 gboolean res;
1384
1385 g_return_val_if_fail (E_IS_CAL_BACKEND_WEBDAV_NOTES (meta_backend), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_112
= 0; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((meta_backend)); GType __t = ((e_cal_backend_webdav_notes_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_112 = 1; _g_boolean_var_112; }), 1
))) { } else { g_return_if_fail_warning ("e-cal-backend-webdav-notes"
, ((const char*) (__func__)), "E_IS_CAL_BACKEND_WEBDAV_NOTES (meta_backend)"
); return ((0)); } } while (0)
;
1386
1387 cbnotes = E_CAL_BACKEND_WEBDAV_NOTES (meta_backend)((((ECalBackendWebDAVNotes*) (void *) ((meta_backend)))));
1388 webdav = ecb_webdav_notes_ref_session (cbnotes);
1389
1390 if (!webdav)
1391 return FALSE(0);
1392
1393 res = e_soup_session_get_ssl_error_details (E_SOUP_SESSION (webdav)((((ESoupSession*) (void *) ((webdav))))), out_certificate_pem, out_certificate_errors);
1394
1395 g_clear_object (&webdav)do { _Static_assert (sizeof *((&webdav)) == sizeof (gpointer
), "Expression evaluates to false"); __typeof__ (((&webdav
))) _pp = ((&webdav)); __typeof__ (*((&webdav))) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_object_unref) (_ptr)
; } while (0)
;
1396
1397 return res;
1398}
1399
1400static gchar *
1401ecb_webdav_notes_get_usermail (ECalBackendWebDAVNotes *cbnotes)
1402{
1403 ESource *source;
1404 ESourceAuthentication *auth_extension;
1405 ESourceWebdav *webdav_extension;
1406 const gchar *extension_name;
1407 gchar *usermail;
1408 gchar *username;
1409 gchar *res = NULL((void*)0);
1410
1411 g_return_val_if_fail (E_IS_CAL_BACKEND_WEBDAV_NOTES (cbnotes), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_113
= 0; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((cbnotes)); GType __t = ((e_cal_backend_webdav_notes_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_113 = 1; _g_boolean_var_113; }), 1
))) { } else { g_return_if_fail_warning ("e-cal-backend-webdav-notes"
, ((const char*) (__func__)), "E_IS_CAL_BACKEND_WEBDAV_NOTES (cbnotes)"
); return (((void*)0)); } } while (0)
;
1412
1413 source = e_backend_get_source (E_BACKEND (cbnotes)((((EBackend*) (void *) ((cbnotes))))));
1414
1415 extension_name = E_SOURCE_EXTENSION_WEBDAV_BACKEND"WebDAV Backend";
1416 webdav_extension = e_source_get_extension (source, extension_name);
1417
1418 /* This will never return an empty string. */
1419 usermail = e_source_webdav_dup_email_address (webdav_extension);
1420
1421 if (usermail)
1422 return usermail;
1423
1424 extension_name = E_SOURCE_EXTENSION_AUTHENTICATION"Authentication";
1425 auth_extension = e_source_get_extension (source, extension_name);
1426 username = e_source_authentication_dup_user (auth_extension);
1427
1428 if (username && strchr (username, '@') && strrchr (username, '.') > strchr (username, '@')) {
1429 res = username;
1430 username = NULL((void*)0);
1431 }
1432
1433 g_free (username);
1434
1435 return res;
1436}
1437
1438static gchar *
1439ecb_webdav_notes_get_backend_property (ECalBackend *backend,
1440 const gchar *prop_name)
1441{
1442 g_return_val_if_fail (prop_name != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_114
= 0; if (prop_name != ((void*)0)) _g_boolean_var_114 = 1; _g_boolean_var_114
; }), 1))) { } else { g_return_if_fail_warning ("e-cal-backend-webdav-notes"
, ((const char*) (__func__)), "prop_name != NULL"); return ((
(void*)0)); } } while (0)
;
1443
1444 if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_CAPABILITIES)(strcmp ((const char *) (prop_name), (const char *) ("capabilities"
)) == 0)
) {
1445 return g_strjoin (",",
1446 e_cal_meta_backend_get_capabilities (E_CAL_META_BACKEND (backend)((((ECalMetaBackend*) (void *) ((backend)))))),
1447 E_CAL_STATIC_CAPABILITY_REFRESH_SUPPORTED"refresh-supported",
1448 E_CAL_STATIC_CAPABILITY_SIMPLE_MEMO"simple-memo",
1449 NULL((void*)0));
1450 } else if (g_str_equal (prop_name, E_CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS)(strcmp ((const char *) (prop_name), (const char *) ("cal-email-address"
)) == 0)
||
1451 g_str_equal (prop_name, E_CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS)(strcmp ((const char *) (prop_name), (const char *) ("alarm-email-address"
)) == 0)
) {
1452 return ecb_webdav_notes_get_usermail (E_CAL_BACKEND_WEBDAV_NOTES (backend)((((ECalBackendWebDAVNotes*) (void *) ((backend))))));
1453 }
1454
1455 /* Chain up to parent's method. */
1456 return E_CAL_BACKEND_CLASS (e_cal_backend_webdav_notes_parent_class)((((ECalBackendClass*) (void *) ((e_cal_backend_webdav_notes_parent_class
)))))
->impl_get_backend_property (backend, prop_name);
1457}
1458
1459static void
1460ecb_webdav_notes_notify_property_changed_cb (GObject *object,
1461 GParamSpec *param,
1462 gpointer user_data)
1463{
1464 ECalBackendWebDAVNotes *cbnotes = user_data;
1465 ECalBackend *cal_backend;
1466 gboolean email_address_changed;
1467 gchar *value;
1468
1469 g_return_if_fail (E_IS_CAL_BACKEND_WEBDAV_NOTES (cbnotes))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_115
= 0; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((cbnotes)); GType __t = ((e_cal_backend_webdav_notes_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_115 = 1; _g_boolean_var_115; }), 1
))) { } else { g_return_if_fail_warning ("e-cal-backend-webdav-notes"
, ((const char*) (__func__)), "E_IS_CAL_BACKEND_WEBDAV_NOTES (cbnotes)"
); return; } } while (0)
;
1470
1471 cal_backend = E_CAL_BACKEND (cbnotes)((((ECalBackend*) (void *) ((cbnotes)))));
1472
1473 email_address_changed = param && g_strcmp0 (param->name, "email-address") == 0;
1474
1475 if (email_address_changed) {
1476 value = ecb_webdav_notes_get_backend_property (cal_backend, E_CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS"cal-email-address");
1477 e_cal_backend_notify_property_changed (cal_backend, E_CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS"cal-email-address", value);
1478 e_cal_backend_notify_property_changed (cal_backend, E_CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS"alarm-email-address", value);
1479 g_free (value);
1480 }
1481}
1482
1483static void
1484ecb_webdav_notes_refresh_sync (ECalBackendSync *sync_backend,
1485 EDataCal *cal,
1486 GCancellable *cancellable,
1487 GError **error)
1488{
1489 ECalBackendWebDAVNotes *cbnotes;
1490
1491 g_return_if_fail (E_IS_CAL_BACKEND_WEBDAV_NOTES (sync_backend))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_116
= 0; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((sync_backend)); GType __t = ((e_cal_backend_webdav_notes_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_116 = 1; _g_boolean_var_116; }), 1
))) { } else { g_return_if_fail_warning ("e-cal-backend-webdav-notes"
, ((const char*) (__func__)), "E_IS_CAL_BACKEND_WEBDAV_NOTES (sync_backend)"
); return; } } while (0)
;
1492
1493 cbnotes = E_CAL_BACKEND_WEBDAV_NOTES (sync_backend)((((ECalBackendWebDAVNotes*) (void *) ((sync_backend)))));
1494 cbnotes->priv->been_connected = FALSE(0);
1495
1496 /* Chain up to parent's method. */
1497 E_CAL_BACKEND_SYNC_CLASS (e_cal_backend_webdav_notes_parent_class)((((ECalBackendSyncClass*) (void *) ((e_cal_backend_webdav_notes_parent_class
)))))
->refresh_sync (sync_backend, cal, cancellable, error);
1498}
1499
1500static gchar *
1501ecb_webdav_notes_dup_component_revision_cb (ECalCache *cal_cache,
1502 ICalComponent *icomp)
1503{
1504 g_return_val_if_fail (icomp != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_117
= 0; if (icomp != ((void*)0)) _g_boolean_var_117 = 1; _g_boolean_var_117
; }), 1))) { } else { g_return_if_fail_warning ("e-cal-backend-webdav-notes"
, ((const char*) (__func__)), "icomp != NULL"); return (((void
*)0)); } } while (0)
;
1505
1506 return e_cal_util_component_dup_x_property (icomp, E_WEBDAV_NOTES_X_ETAG"X-EVOLUTION-WEBDAV-NOTES-ETAG");
1507}
1508
1509static void
1510e_cal_backend_webdav_notes_constructed (GObject *object)
1511{
1512 ECalBackendWebDAVNotes *cbnotes = E_CAL_BACKEND_WEBDAV_NOTES (object)((((ECalBackendWebDAVNotes*) (void *) ((object)))));
1513 ECalCache *cal_cache;
1514 ESource *source;
1515 ESourceWebdav *webdav_extension;
1516
1517 /* Chain up to parent's method. */
1518 G_OBJECT_CLASS (e_cal_backend_webdav_notes_parent_class)((((GObjectClass*) (void *) ((e_cal_backend_webdav_notes_parent_class
)))))
->constructed (object);
1519
1520 cal_cache = e_cal_meta_backend_ref_cache (E_CAL_META_BACKEND (cbnotes)((((ECalMetaBackend*) (void *) ((cbnotes))))));
1521
1522 g_signal_connect (cal_cache, "dup-component-revision",g_signal_connect_data ((cal_cache), ("dup-component-revision"
), (((GCallback) (ecb_webdav_notes_dup_component_revision_cb)
)), (((void*)0)), ((void*)0), (GConnectFlags) 0)
1523 G_CALLBACK (ecb_webdav_notes_dup_component_revision_cb), NULL)g_signal_connect_data ((cal_cache), ("dup-component-revision"
), (((GCallback) (ecb_webdav_notes_dup_component_revision_cb)
)), (((void*)0)), ((void*)0), (GConnectFlags) 0)
;
1524
1525 g_clear_object (&cal_cache)do { _Static_assert (sizeof *((&cal_cache)) == sizeof (gpointer
), "Expression evaluates to false"); __typeof__ (((&cal_cache
))) _pp = ((&cal_cache)); __typeof__ (*((&cal_cache))
) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_object_unref) (
_ptr); } while (0)
;
1526
1527 source = e_backend_get_source (E_BACKEND (cbnotes)((((EBackend*) (void *) ((cbnotes))))));
1528 webdav_extension = e_source_get_extension (source, E_SOURCE_EXTENSION_WEBDAV_BACKEND"WebDAV Backend");
1529
1530 g_signal_connect_object (webdav_extension, "notify::email-address",
1531 G_CALLBACK (ecb_webdav_notes_notify_property_changed_cb)((GCallback) (ecb_webdav_notes_notify_property_changed_cb)), cbnotes, 0);
1532}
1533
1534static void
1535e_cal_backend_webdav_notes_dispose (GObject *object)
1536{
1537 ECalBackendWebDAVNotes *cbnotes = E_CAL_BACKEND_WEBDAV_NOTES (object)((((ECalBackendWebDAVNotes*) (void *) ((object)))));
1538
1539 g_mutex_lock (&cbnotes->priv->webdav_lock);
1540 g_clear_object (&cbnotes->priv->webdav)do { _Static_assert (sizeof *((&cbnotes->priv->webdav
)) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(((&cbnotes->priv->webdav))) _pp = ((&cbnotes->
priv->webdav)); __typeof__ (*((&cbnotes->priv->webdav
))) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_object_unref
) (_ptr); } while (0)
;
1541 g_clear_pointer (&cbnotes->priv->last_uri, g_uri_unref)do { _Static_assert (sizeof *(&cbnotes->priv->last_uri
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&cbnotes->priv->last_uri)) _pp = (&cbnotes->
priv->last_uri); __typeof__ (*(&cbnotes->priv->last_uri
)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_uri_unref) (_ptr
); } while (0)
;
1542 g_mutex_unlock (&cbnotes->priv->webdav_lock);
1543
1544 /* Chain up to parent's method. */
1545 G_OBJECT_CLASS (e_cal_backend_webdav_notes_parent_class)((((GObjectClass*) (void *) ((e_cal_backend_webdav_notes_parent_class
)))))
->dispose (object);
1546}
1547
1548static void
1549e_cal_backend_webdav_notes_finalize (GObject *object)
1550{
1551 ECalBackendWebDAVNotes *cbnotes = E_CAL_BACKEND_WEBDAV_NOTES (object)((((ECalBackendWebDAVNotes*) (void *) ((object)))));
1552
1553 g_mutex_clear (&cbnotes->priv->webdav_lock);
1554
1555 /* Chain up to parent's method. */
1556 G_OBJECT_CLASS (e_cal_backend_webdav_notes_parent_class)((((GObjectClass*) (void *) ((e_cal_backend_webdav_notes_parent_class
)))))
->finalize (object);
1557}
1558
1559static void
1560e_cal_backend_webdav_notes_init (ECalBackendWebDAVNotes *cbnotes)
1561{
1562 cbnotes->priv = e_cal_backend_webdav_notes_get_instance_private (cbnotes);
1563
1564 g_mutex_init (&cbnotes->priv->webdav_lock);
1565}
1566
1567static void
1568e_cal_backend_webdav_notes_class_init (ECalBackendWebDAVNotesClass *klass)
1569{
1570 GObjectClass *object_class;
1571 ECalBackendClass *cal_backend_class;
1572 ECalBackendSyncClass *cal_backend_sync_class;
1573 ECalMetaBackendClass *cal_meta_backend_class;
1574
1575 cal_meta_backend_class = E_CAL_META_BACKEND_CLASS (klass)((((ECalMetaBackendClass*) (void *) ((klass)))));
1576 cal_meta_backend_class->connect_sync = ecb_webdav_notes_connect_sync;
1577 cal_meta_backend_class->disconnect_sync = ecb_webdav_notes_disconnect_sync;
1578 cal_meta_backend_class->get_changes_sync = ecb_webdav_notes_get_changes_sync;
1579 cal_meta_backend_class->list_existing_sync = ecb_webdav_notes_list_existing_sync;
1580 cal_meta_backend_class->load_component_sync = ecb_webdav_notes_load_component_sync;
1581 cal_meta_backend_class->save_component_sync = ecb_webdav_notes_save_component_sync;
1582 cal_meta_backend_class->remove_component_sync = ecb_webdav_notes_remove_component_sync;
1583 cal_meta_backend_class->get_ssl_error_details = ecb_webdav_notes_get_ssl_error_details;
1584
1585 cal_backend_sync_class = E_CAL_BACKEND_SYNC_CLASS (klass)((((ECalBackendSyncClass*) (void *) ((klass)))));
1586 cal_backend_sync_class->refresh_sync = ecb_webdav_notes_refresh_sync;
1587
1588 cal_backend_class = E_CAL_BACKEND_CLASS (klass)((((ECalBackendClass*) (void *) ((klass)))));
1589 cal_backend_class->impl_get_backend_property = ecb_webdav_notes_get_backend_property;
1590
1591 object_class = G_OBJECT_CLASS (klass)((((GObjectClass*) (void *) ((klass)))));
1592 object_class->constructed = e_cal_backend_webdav_notes_constructed;
1593 object_class->dispose = e_cal_backend_webdav_notes_dispose;
1594 object_class->finalize = e_cal_backend_webdav_notes_finalize;
1595}