1 /*
2 * e-source-webdav.c
3 *
4 * This library is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation.
7 *
8 * This library is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
11 * for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this library. If not, see <http://www.gnu.org/licenses/>.
15 *
16 */
17
18 /**
19 * SECTION: e-source-webdav
20 * @include: libedataserver/libedataserver.h
21 * @short_description: #ESource extension for WebDAV settings
22 *
23 * The #ESourceWebdav extension tracks settings for accessing resources
24 * on a remote WebDAV server.
25 *
26 * This class exists in libedataserver because we have several
27 * WebDAV-based backends. Each of these backends is free to use
28 * this class directly or subclass it with additional settings.
29 * Subclasses should override the extension name.
30 *
31 * The #SoupURI is parsed into components and distributed across
32 * several other built-in extensions such as #ESourceAuthentication
33 * and #ESourceSecurity.
34 *
35 * Access the extension as follows:
36 *
37 * |[
38 * #include <libedataserver/libedataserver.h>
39 *
40 * ESourceWebdav *extension;
41 *
42 * extension = e_source_get_extension (source, E_SOURCE_EXTENSION_WEBDAV_BACKEND);
43 * ]|
44 **/
45
46 #include "evolution-data-server-config.h"
47
48 #include <glib/gi18n-lib.h>
49
50 #include "e-data-server-util.h"
51 #include "e-source-address-book.h"
52 #include "e-source-authentication.h"
53 #include "e-source-calendar.h"
54 #include "e-source-memo-list.h"
55 #include "e-source-registry.h"
56 #include "e-source-security.h"
57 #include "e-source-task-list.h"
58
59 #include "e-source-webdav.h"
60
61 struct _ESourceWebdavPrivate {
62 gchar *display_name;
63 gchar *color;
64 gchar *email_address;
65 gchar *resource_path;
66 gchar *resource_query;
67 gchar *ssl_trust;
68 gboolean avoid_ifmatch;
69 gboolean calendar_auto_schedule;
70 SoupURI *soup_uri;
71 guint order;
72 };
73
74 enum {
75 PROP_0,
76 PROP_AVOID_IFMATCH,
77 PROP_CALENDAR_AUTO_SCHEDULE,
78 PROP_COLOR,
79 PROP_DISPLAY_NAME,
80 PROP_EMAIL_ADDRESS,
81 PROP_RESOURCE_PATH,
82 PROP_RESOURCE_QUERY,
83 PROP_SOUP_URI,
84 PROP_SSL_TRUST,
85 PROP_ORDER
86 };
87
G_DEFINE_TYPE_WITH_PRIVATE(ESourceWebdav,e_source_webdav,E_TYPE_SOURCE_EXTENSION)88 G_DEFINE_TYPE_WITH_PRIVATE (
89 ESourceWebdav,
90 e_source_webdav,
91 E_TYPE_SOURCE_EXTENSION)
92
93 static void
94 source_webdav_notify_cb (GObject *object,
95 GParamSpec *pspec,
96 ESourceWebdav *extension)
97 {
98 g_object_notify (G_OBJECT (extension), "soup-uri");
99 }
100
101 static gboolean
source_webdav_user_to_method(GBinding * binding,const GValue * source_value,GValue * target_value,gpointer user_data)102 source_webdav_user_to_method (GBinding *binding,
103 const GValue *source_value,
104 GValue *target_value,
105 gpointer user_data)
106 {
107 GObject *target_object;
108 ESourceAuthentication *extension;
109 const gchar *user;
110 gchar *method;
111 gboolean success = TRUE;
112
113 target_object = g_binding_get_target (binding);
114 extension = E_SOURCE_AUTHENTICATION (target_object);
115 method = e_source_authentication_dup_method (extension);
116 g_return_val_if_fail (method != NULL, FALSE);
117
118 /* Be careful not to stomp on a custom method name.
119 * Only change it under the following conditions:
120 *
121 * 1) If "user" is empty and "method" is empty,
122 * set "method" to "none".
123 * 2) If "user" is not empty and "method" is "none",
124 * set "method" to "plain/password" (corresponds
125 * to HTTP Basic authentication).
126 * 3) Otherwise preserve the current "method" value.
127 */
128
129 user = g_value_get_string (source_value);
130 if ((user == NULL || *user == '\0') && !*method) {
131 g_value_set_string (target_value, "none");
132 } else if (g_str_equal (method, "none")) {
133 g_value_set_string (target_value, "plain/password");
134 } else {
135 success = FALSE;
136 }
137
138 g_free (method);
139
140 return success;
141 }
142
143 static void
source_webdav_update_properties_from_soup_uri(ESourceWebdav * webdav_extension)144 source_webdav_update_properties_from_soup_uri (ESourceWebdav *webdav_extension)
145 {
146 ESource *source;
147 ESourceExtension *extension;
148 SoupURI *soup_uri;
149 const gchar *extension_name;
150
151 /* Do not use e_source_webdav_dup_soup_uri() here. That
152 * builds the URI from properties we haven't yet updated. */
153 e_source_extension_property_lock (E_SOURCE_EXTENSION (webdav_extension));
154 soup_uri = soup_uri_copy (webdav_extension->priv->soup_uri);
155 e_source_extension_property_unlock (E_SOURCE_EXTENSION (webdav_extension));
156
157 extension = E_SOURCE_EXTENSION (webdav_extension);
158 source = e_source_extension_ref_source (extension);
159
160 g_object_set (
161 extension,
162 "resource-path", soup_uri->path,
163 "resource-query", soup_uri->query,
164 NULL);
165
166 extension_name = E_SOURCE_EXTENSION_AUTHENTICATION;
167 extension = e_source_get_extension (source, extension_name);
168
169 g_object_set (
170 extension,
171 "host", soup_uri->host,
172 "port", soup_uri->port,
173 NULL);
174
175 if (soup_uri->user && *soup_uri->user)
176 g_object_set (
177 extension,
178 "user", soup_uri->user,
179 NULL);
180
181 extension_name = E_SOURCE_EXTENSION_SECURITY;
182 extension = e_source_get_extension (source, extension_name);
183
184 g_object_set (
185 extension,
186 "secure", (soup_uri->scheme == SOUP_URI_SCHEME_HTTPS),
187 NULL);
188
189 g_object_unref (source);
190
191 soup_uri_free (soup_uri);
192 }
193
194 static void
source_webdav_update_soup_uri_from_properties(ESourceWebdav * webdav_extension)195 source_webdav_update_soup_uri_from_properties (ESourceWebdav *webdav_extension)
196 {
197 ESource *source;
198 ESourceExtension *extension;
199 SoupURI *soup_uri;
200 const gchar *extension_name;
201 gchar *user;
202 gchar *host;
203 gchar *path;
204 gchar *query;
205 guint port;
206 gboolean secure;
207
208 extension = E_SOURCE_EXTENSION (webdav_extension);
209 source = e_source_extension_ref_source (extension);
210
211 g_object_get (
212 extension,
213 "resource-path", &path,
214 "resource-query", &query,
215 NULL);
216
217 extension_name = E_SOURCE_EXTENSION_AUTHENTICATION;
218 extension = e_source_get_extension (source, extension_name);
219
220 g_object_get (
221 extension,
222 "user", &user,
223 "host", &host,
224 "port", &port,
225 NULL);
226
227 extension_name = E_SOURCE_EXTENSION_SECURITY;
228 extension = e_source_get_extension (source, extension_name);
229
230 g_object_get (
231 extension,
232 "secure", &secure,
233 NULL);
234
235 g_object_unref (source);
236
237 e_source_extension_property_lock (E_SOURCE_EXTENSION (webdav_extension));
238
239 soup_uri = webdav_extension->priv->soup_uri;
240
241 /* Try not to disturb the scheme, in case it's "webcal" or some
242 * other non-standard value. But if we have to change it, do it. */
243 if (secure && soup_uri->scheme != SOUP_URI_SCHEME_HTTPS)
244 soup_uri_set_scheme (soup_uri, SOUP_URI_SCHEME_HTTPS);
245 if (!secure && soup_uri->scheme == SOUP_URI_SCHEME_HTTPS)
246 soup_uri_set_scheme (soup_uri, SOUP_URI_SCHEME_HTTP);
247
248 soup_uri_set_user (soup_uri, user);
249 soup_uri_set_host (soup_uri, host);
250
251 if (port > 0)
252 soup_uri_set_port (soup_uri, port);
253
254 /* SoupURI doesn't like NULL paths. */
255 soup_uri_set_path (soup_uri, (path != NULL) ? path : "");
256
257 soup_uri_set_query (soup_uri, query);
258
259 e_source_extension_property_unlock (E_SOURCE_EXTENSION (webdav_extension));
260
261 g_free (user);
262 g_free (host);
263 g_free (path);
264 g_free (query);
265 }
266
267 static void
source_webdav_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)268 source_webdav_set_property (GObject *object,
269 guint property_id,
270 const GValue *value,
271 GParamSpec *pspec)
272 {
273 switch (property_id) {
274 case PROP_AVOID_IFMATCH:
275 e_source_webdav_set_avoid_ifmatch (
276 E_SOURCE_WEBDAV (object),
277 g_value_get_boolean (value));
278 return;
279
280 case PROP_CALENDAR_AUTO_SCHEDULE:
281 e_source_webdav_set_calendar_auto_schedule (
282 E_SOURCE_WEBDAV (object),
283 g_value_get_boolean (value));
284 return;
285
286 case PROP_COLOR:
287 e_source_webdav_set_color (
288 E_SOURCE_WEBDAV (object),
289 g_value_get_string (value));
290 return;
291
292 case PROP_DISPLAY_NAME:
293 e_source_webdav_set_display_name (
294 E_SOURCE_WEBDAV (object),
295 g_value_get_string (value));
296 return;
297
298 case PROP_EMAIL_ADDRESS:
299 e_source_webdav_set_email_address (
300 E_SOURCE_WEBDAV (object),
301 g_value_get_string (value));
302 return;
303
304 case PROP_RESOURCE_PATH:
305 e_source_webdav_set_resource_path (
306 E_SOURCE_WEBDAV (object),
307 g_value_get_string (value));
308 return;
309
310 case PROP_RESOURCE_QUERY:
311 e_source_webdav_set_resource_query (
312 E_SOURCE_WEBDAV (object),
313 g_value_get_string (value));
314 return;
315
316 case PROP_SOUP_URI:
317 e_source_webdav_set_soup_uri (
318 E_SOURCE_WEBDAV (object),
319 g_value_get_boxed (value));
320 return;
321
322 case PROP_SSL_TRUST:
323 e_source_webdav_set_ssl_trust (
324 E_SOURCE_WEBDAV (object),
325 g_value_get_string (value));
326 return;
327
328 case PROP_ORDER:
329 e_source_webdav_set_order (
330 E_SOURCE_WEBDAV (object),
331 g_value_get_uint (value));
332 return;
333 }
334
335 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
336 }
337
338 static void
source_webdav_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)339 source_webdav_get_property (GObject *object,
340 guint property_id,
341 GValue *value,
342 GParamSpec *pspec)
343 {
344 switch (property_id) {
345 case PROP_AVOID_IFMATCH:
346 g_value_set_boolean (
347 value,
348 e_source_webdav_get_avoid_ifmatch (
349 E_SOURCE_WEBDAV (object)));
350 return;
351
352 case PROP_CALENDAR_AUTO_SCHEDULE:
353 g_value_set_boolean (
354 value,
355 e_source_webdav_get_calendar_auto_schedule (
356 E_SOURCE_WEBDAV (object)));
357 return;
358
359 case PROP_COLOR:
360 g_value_take_string (
361 value,
362 e_source_webdav_dup_color (
363 E_SOURCE_WEBDAV (object)));
364 return;
365
366 case PROP_DISPLAY_NAME:
367 g_value_take_string (
368 value,
369 e_source_webdav_dup_display_name (
370 E_SOURCE_WEBDAV (object)));
371 return;
372
373 case PROP_EMAIL_ADDRESS:
374 g_value_take_string (
375 value,
376 e_source_webdav_dup_email_address (
377 E_SOURCE_WEBDAV (object)));
378 return;
379
380 case PROP_RESOURCE_PATH:
381 g_value_take_string (
382 value,
383 e_source_webdav_dup_resource_path (
384 E_SOURCE_WEBDAV (object)));
385 return;
386
387 case PROP_RESOURCE_QUERY:
388 g_value_take_string (
389 value,
390 e_source_webdav_dup_resource_query (
391 E_SOURCE_WEBDAV (object)));
392 return;
393
394 case PROP_SOUP_URI:
395 g_value_take_boxed (
396 value,
397 e_source_webdav_dup_soup_uri (
398 E_SOURCE_WEBDAV (object)));
399 return;
400
401 case PROP_SSL_TRUST:
402 g_value_take_string (
403 value,
404 e_source_webdav_dup_ssl_trust (
405 E_SOURCE_WEBDAV (object)));
406 return;
407
408 case PROP_ORDER:
409 g_value_set_uint (
410 value,
411 e_source_webdav_get_order (
412 E_SOURCE_WEBDAV (object)));
413 return;
414 }
415
416 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
417 }
418
419 static void
source_webdav_finalize(GObject * object)420 source_webdav_finalize (GObject *object)
421 {
422 ESourceWebdavPrivate *priv;
423
424 priv = E_SOURCE_WEBDAV (object)->priv;
425
426 g_free (priv->color);
427 g_free (priv->display_name);
428 g_free (priv->email_address);
429 g_free (priv->resource_path);
430 g_free (priv->resource_query);
431 g_free (priv->ssl_trust);
432
433 soup_uri_free (priv->soup_uri);
434
435 /* Chain up to parent's finalize() method. */
436 G_OBJECT_CLASS (e_source_webdav_parent_class)->finalize (object);
437 }
438
439 static void
source_webdav_constructed(GObject * object)440 source_webdav_constructed (GObject *object)
441 {
442 ESource *source;
443 ESourceExtension *extension;
444 const gchar *extension_name;
445
446 /* Chain up to parent's constructed() method. */
447 G_OBJECT_CLASS (e_source_webdav_parent_class)->constructed (object);
448
449 /* XXX I *think* we don't need to worry about disconnecting the
450 * signals. ESourceExtensions are only added, never removed,
451 * and they all finalize with their ESource. At least that's
452 * how it's supposed to work if everyone follows the rules. */
453
454 extension = E_SOURCE_EXTENSION (object);
455 source = e_source_extension_ref_source (extension);
456
457 g_signal_connect (
458 extension, "notify::resource-path",
459 G_CALLBACK (source_webdav_notify_cb), object);
460
461 g_signal_connect (
462 extension, "notify::resource-query",
463 G_CALLBACK (source_webdav_notify_cb), object);
464
465 extension_name = E_SOURCE_EXTENSION_AUTHENTICATION;
466 extension = e_source_get_extension (source, extension_name);
467
468 g_signal_connect (
469 extension, "notify::host",
470 G_CALLBACK (source_webdav_notify_cb), object);
471
472 g_signal_connect (
473 extension, "notify::port",
474 G_CALLBACK (source_webdav_notify_cb), object);
475
476 g_signal_connect (
477 extension, "notify::user",
478 G_CALLBACK (source_webdav_notify_cb), object);
479
480 /* This updates the authentication method
481 * based on whether a user name was given. */
482 e_binding_bind_property_full (
483 extension, "user",
484 extension, "method",
485 G_BINDING_SYNC_CREATE,
486 source_webdav_user_to_method,
487 NULL,
488 NULL, (GDestroyNotify) NULL);
489
490 extension_name = E_SOURCE_EXTENSION_SECURITY;
491 extension = e_source_get_extension (source, extension_name);
492
493 g_signal_connect (
494 extension, "notify::secure",
495 G_CALLBACK (source_webdav_notify_cb), object);
496
497 g_object_unref (source);
498 }
499
500 static void
e_source_webdav_class_init(ESourceWebdavClass * class)501 e_source_webdav_class_init (ESourceWebdavClass *class)
502 {
503 GObjectClass *object_class;
504 ESourceExtensionClass *extension_class;
505
506 object_class = G_OBJECT_CLASS (class);
507 object_class->set_property = source_webdav_set_property;
508 object_class->get_property = source_webdav_get_property;
509 object_class->finalize = source_webdav_finalize;
510 object_class->constructed = source_webdav_constructed;
511
512 extension_class = E_SOURCE_EXTENSION_CLASS (class);
513 extension_class->name = E_SOURCE_EXTENSION_WEBDAV_BACKEND;
514
515 g_object_class_install_property (
516 object_class,
517 PROP_AVOID_IFMATCH,
518 g_param_spec_boolean (
519 "avoid-ifmatch",
520 "Avoid If-Match",
521 "Work around a bug in old Apache servers",
522 FALSE,
523 G_PARAM_READWRITE |
524 G_PARAM_CONSTRUCT |
525 G_PARAM_EXPLICIT_NOTIFY |
526 G_PARAM_STATIC_STRINGS |
527 E_SOURCE_PARAM_SETTING));
528
529 g_object_class_install_property (
530 object_class,
531 PROP_CALENDAR_AUTO_SCHEDULE,
532 g_param_spec_boolean (
533 "calendar-auto-schedule",
534 "Calendar Auto-Schedule",
535 "Whether the server handles meeting "
536 "invitations (CalDAV-only)",
537 FALSE,
538 G_PARAM_READWRITE |
539 G_PARAM_CONSTRUCT |
540 G_PARAM_EXPLICIT_NOTIFY |
541 G_PARAM_STATIC_STRINGS |
542 E_SOURCE_PARAM_SETTING));
543
544 g_object_class_install_property (
545 object_class,
546 PROP_COLOR,
547 g_param_spec_string (
548 "color",
549 "Color",
550 "Color of the WebDAV resource",
551 "",
552 G_PARAM_READWRITE |
553 G_PARAM_CONSTRUCT |
554 G_PARAM_EXPLICIT_NOTIFY |
555 G_PARAM_STATIC_STRINGS |
556 E_SOURCE_PARAM_SETTING));
557
558 g_object_class_install_property (
559 object_class,
560 PROP_DISPLAY_NAME,
561 g_param_spec_string (
562 "display-name",
563 "Display Name",
564 "Display name of the WebDAV resource",
565 "",
566 G_PARAM_READWRITE |
567 G_PARAM_CONSTRUCT |
568 G_PARAM_EXPLICIT_NOTIFY |
569 G_PARAM_STATIC_STRINGS |
570 E_SOURCE_PARAM_SETTING));
571
572 g_object_class_install_property (
573 object_class,
574 PROP_EMAIL_ADDRESS,
575 g_param_spec_string (
576 "email-address",
577 "Email Address",
578 "The user's email address",
579 "",
580 G_PARAM_READWRITE |
581 G_PARAM_CONSTRUCT |
582 G_PARAM_EXPLICIT_NOTIFY |
583 G_PARAM_STATIC_STRINGS |
584 E_SOURCE_PARAM_SETTING));
585
586 g_object_class_install_property (
587 object_class,
588 PROP_RESOURCE_PATH,
589 g_param_spec_string (
590 "resource-path",
591 "Resource Path",
592 "Absolute path to a WebDAV resource",
593 NULL,
594 G_PARAM_READWRITE |
595 G_PARAM_CONSTRUCT |
596 G_PARAM_EXPLICIT_NOTIFY |
597 G_PARAM_STATIC_STRINGS |
598 E_SOURCE_PARAM_SETTING));
599
600 g_object_class_install_property (
601 object_class,
602 PROP_RESOURCE_QUERY,
603 g_param_spec_string (
604 "resource-query",
605 "Resource Query",
606 "Query to access a WebDAV resource",
607 NULL,
608 G_PARAM_READWRITE |
609 G_PARAM_CONSTRUCT |
610 G_PARAM_EXPLICIT_NOTIFY |
611 G_PARAM_STATIC_STRINGS |
612 E_SOURCE_PARAM_SETTING));
613
614 g_object_class_install_property (
615 object_class,
616 PROP_SOUP_URI,
617 g_param_spec_boxed (
618 "soup-uri",
619 "SoupURI",
620 "WebDAV service as a SoupURI",
621 SOUP_TYPE_URI,
622 G_PARAM_READWRITE |
623 G_PARAM_EXPLICIT_NOTIFY |
624 G_PARAM_STATIC_STRINGS));
625
626 g_object_class_install_property (
627 object_class,
628 PROP_SSL_TRUST,
629 g_param_spec_string (
630 "ssl-trust",
631 "SSL/TLS Trust",
632 "SSL/TLS certificate trust setting, for invalid server certificates",
633 NULL,
634 G_PARAM_READWRITE |
635 G_PARAM_CONSTRUCT |
636 G_PARAM_EXPLICIT_NOTIFY |
637 G_PARAM_STATIC_STRINGS |
638 E_SOURCE_PARAM_SETTING));
639
640 g_object_class_install_property (
641 object_class,
642 PROP_ORDER,
643 g_param_spec_uint (
644 "order",
645 "Order",
646 "A sorting order of the resource",
647 0, G_MAXUINT, (guint) -1,
648 G_PARAM_READWRITE |
649 G_PARAM_CONSTRUCT |
650 G_PARAM_EXPLICIT_NOTIFY |
651 G_PARAM_STATIC_STRINGS |
652 E_SOURCE_PARAM_SETTING));
653 }
654
655 static void
e_source_webdav_init(ESourceWebdav * extension)656 e_source_webdav_init (ESourceWebdav *extension)
657 {
658 extension->priv = e_source_webdav_get_instance_private (extension);
659
660 /* Initialize this enough for SOUP_URI_IS_VALID() to pass. */
661 extension->priv->soup_uri = soup_uri_new (NULL);
662 extension->priv->soup_uri->scheme = SOUP_URI_SCHEME_HTTP;
663 extension->priv->soup_uri->path = g_strdup ("");
664 }
665
666 /**
667 * e_source_webdav_get_avoid_ifmatch:
668 * @extension: an #ESourceWebdav
669 *
670 * This setting works around a
671 * <ulink url="https://issues.apache.org/bugzilla/show_bug.cgi?id=38034">
672 * bug</ulink> in older Apache mod_dav versions.
673 *
674 * <note>
675 * <para>
676 * We may deprecate this once Apache 2.2.8 or newer becomes
677 * sufficiently ubiquitous, or we figure out a way to detect
678 * and work around the bug automatically.
679 * </para>
680 * </note>
681 *
682 * Returns: whether the WebDAV server is known to exhibit the bug
683 *
684 * Since: 3.6
685 **/
686 gboolean
e_source_webdav_get_avoid_ifmatch(ESourceWebdav * extension)687 e_source_webdav_get_avoid_ifmatch (ESourceWebdav *extension)
688 {
689 g_return_val_if_fail (E_IS_SOURCE_WEBDAV (extension), FALSE);
690
691 return extension->priv->avoid_ifmatch;
692 }
693
694 /**
695 * e_source_webdav_set_avoid_ifmatch:
696 * @extension: an #ESourceWebdav
697 * @avoid_ifmatch: whether the WebDAV server is known to exhibit the bug
698 *
699 * This setting works around a
700 * <ulink url="https://issues.apache.org/bugzilla/show_bug.cgi?id=38034">
701 * bug</ulink> in older Apache mod_dav versions.
702 *
703 * <note>
704 * <para>
705 * We may deprecate this once Apache 2.2.8 or newer becomes
706 * sufficiently ubiquitous, or we figure out a way to detect
707 * and work around the bug automatically.
708 * </para>
709 * </note>
710 *
711 * Since: 3.6
712 **/
713 void
e_source_webdav_set_avoid_ifmatch(ESourceWebdav * extension,gboolean avoid_ifmatch)714 e_source_webdav_set_avoid_ifmatch (ESourceWebdav *extension,
715 gboolean avoid_ifmatch)
716 {
717 g_return_if_fail (E_IS_SOURCE_WEBDAV (extension));
718
719 if (extension->priv->avoid_ifmatch == avoid_ifmatch)
720 return;
721
722 extension->priv->avoid_ifmatch = avoid_ifmatch;
723
724 g_object_notify (G_OBJECT (extension), "avoid-ifmatch");
725 }
726
727 /**
728 * e_source_webdav_get_calendar_auto_schedule:
729 * @extension: an #ESourceWebdav
730 *
731 * FIXME Document me!
732 *
733 * Since: 3.6
734 **/
735 gboolean
e_source_webdav_get_calendar_auto_schedule(ESourceWebdav * extension)736 e_source_webdav_get_calendar_auto_schedule (ESourceWebdav *extension)
737 {
738 g_return_val_if_fail (E_IS_SOURCE_WEBDAV (extension), FALSE);
739
740 return extension->priv->calendar_auto_schedule;
741 }
742
743 /**
744 * e_source_webdav_set_calendar_auto_schedule:
745 * @extension: an #ESourceWebdav
746 * @calendar_auto_schedule: whether the server supports the
747 * "calendar-auto-schedule" feature of CalDAV
748 *
749 * FIXME Document me!
750 *
751 * Since: 3.6
752 **/
753 void
e_source_webdav_set_calendar_auto_schedule(ESourceWebdav * extension,gboolean calendar_auto_schedule)754 e_source_webdav_set_calendar_auto_schedule (ESourceWebdav *extension,
755 gboolean calendar_auto_schedule)
756 {
757 g_return_if_fail (E_IS_SOURCE_WEBDAV (extension));
758
759 if (extension->priv->calendar_auto_schedule == calendar_auto_schedule)
760 return;
761
762 extension->priv->calendar_auto_schedule = calendar_auto_schedule;
763
764 g_object_notify (G_OBJECT (extension), "calendar-auto-schedule");
765 }
766
767 /**
768 * e_source_webdav_get_display_name:
769 * @extension: an #ESourceWebdav
770 *
771 * Returns the last known display name of a WebDAV resource, which may
772 * differ from the #ESource:display-name property of the #ESource to which
773 * @extension belongs.
774 *
775 * Returns: (nullable): the display name of the WebDAV resource
776 *
777 * Since: 3.6
778 **/
779 const gchar *
e_source_webdav_get_display_name(ESourceWebdav * extension)780 e_source_webdav_get_display_name (ESourceWebdav *extension)
781 {
782 g_return_val_if_fail (E_IS_SOURCE_WEBDAV (extension), NULL);
783
784 return extension->priv->display_name;
785 }
786
787 /**
788 * e_source_webdav_dup_display_name:
789 * @extension: an #ESourceWebdav
790 *
791 * Thread-safe variation of e_source_webdav_get_display_name().
792 * Use this function when accessing @extension from multiple threads.
793 *
794 * The returned string should be freed with g_free() when no longer needed.
795 *
796 * Returns: (nullable): a newly-allocated copy of #ESourceWebdav:display-name
797 *
798 * Since: 3.6
799 **/
800 gchar *
e_source_webdav_dup_display_name(ESourceWebdav * extension)801 e_source_webdav_dup_display_name (ESourceWebdav *extension)
802 {
803 const gchar *protected;
804 gchar *duplicate;
805
806 g_return_val_if_fail (E_IS_SOURCE_WEBDAV (extension), NULL);
807
808 e_source_extension_property_lock (E_SOURCE_EXTENSION (extension));
809
810 protected = e_source_webdav_get_display_name (extension);
811 duplicate = g_strdup (protected);
812
813 e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
814
815 return duplicate;
816 }
817
818 /**
819 * e_source_webdav_set_display_name:
820 * @extension: an #ESourceWebdav
821 * @display_name: (nullable): the display name of the WebDAV resource,
822 * or %NULL
823 *
824 * Updates the last known display name of a WebDAV resource, which may
825 * differ from the #ESource:display-name property of the #ESource to which
826 * @extension belongs.
827 *
828 * The internal copy of @display_name is automatically stripped of leading
829 * and trailing whitespace. If the resulting string is empty, %NULL is set
830 * instead.
831 *
832 * Since: 3.6
833 **/
834 void
e_source_webdav_set_display_name(ESourceWebdav * extension,const gchar * display_name)835 e_source_webdav_set_display_name (ESourceWebdav *extension,
836 const gchar *display_name)
837 {
838 g_return_if_fail (E_IS_SOURCE_WEBDAV (extension));
839
840 e_source_extension_property_lock (E_SOURCE_EXTENSION (extension));
841
842 if (e_util_strcmp0 (extension->priv->display_name, display_name) == 0) {
843 e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
844 return;
845 }
846
847 g_free (extension->priv->display_name);
848 extension->priv->display_name = e_util_strdup_strip (display_name);
849
850 e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
851
852 g_object_notify (G_OBJECT (extension), "display-name");
853 }
854
855 /**
856 * e_source_webdav_get_color:
857 * @extension: an #ESourceWebdav
858 *
859 * Returns the last known color of a WebDAV resource as provided by the server.
860 *
861 * Returns: (nullable): the color of the WebDAV resource, if any set on the server
862 *
863 * Since: 3.30
864 **/
865 const gchar *
e_source_webdav_get_color(ESourceWebdav * extension)866 e_source_webdav_get_color (ESourceWebdav *extension)
867 {
868 g_return_val_if_fail (E_IS_SOURCE_WEBDAV (extension), NULL);
869
870 return extension->priv->color;
871 }
872
873 /**
874 * e_source_webdav_dup_color:
875 * @extension: an #ESourceWebdav
876 *
877 * Thread-safe variation of e_source_webdav_get_color().
878 * Use this function when accessing @extension from multiple threads.
879 *
880 * The returned string should be freed with g_free() when no longer needed.
881 *
882 * Returns: (nullable): a newly-allocated copy of #ESourceWebdav:color
883 *
884 * Since: 3.30
885 **/
886 gchar *
e_source_webdav_dup_color(ESourceWebdav * extension)887 e_source_webdav_dup_color (ESourceWebdav *extension)
888 {
889 const gchar *protected;
890 gchar *duplicate;
891
892 g_return_val_if_fail (E_IS_SOURCE_WEBDAV (extension), NULL);
893
894 e_source_extension_property_lock (E_SOURCE_EXTENSION (extension));
895
896 protected = e_source_webdav_get_color (extension);
897 duplicate = g_strdup (protected);
898
899 e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
900
901 return duplicate;
902 }
903
904 /**
905 * e_source_webdav_set_color:
906 * @extension: an #ESourceWebdav
907 * @color: (nullable): the color of the WebDAV resource, or %NULL
908 *
909 * Updates the last known color of a WebDAV resource, as provided by the server.
910 *
911 * The internal copy of @color is automatically stripped of leading
912 * and trailing whitespace. If the resulting string is empty, %NULL is set
913 * instead.
914 *
915 * Since: 3.30
916 **/
917 void
e_source_webdav_set_color(ESourceWebdav * extension,const gchar * color)918 e_source_webdav_set_color (ESourceWebdav *extension,
919 const gchar *color)
920 {
921 g_return_if_fail (E_IS_SOURCE_WEBDAV (extension));
922
923 e_source_extension_property_lock (E_SOURCE_EXTENSION (extension));
924
925 if (e_util_strcmp0 (extension->priv->color, color) == 0) {
926 e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
927 return;
928 }
929
930 g_free (extension->priv->color);
931 extension->priv->color = e_util_strdup_strip (color);
932
933 e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
934
935 g_object_notify (G_OBJECT (extension), "color");
936 }
937
938 /**
939 * e_source_webdav_get_email_address:
940 * @extension: an #ESourceWebdav
941 *
942 * Returns the user's email address which can be passed to a CalDAV server
943 * if the user wishes to receive scheduling messages.
944 *
945 * Returns: (nullable): the user's email address
946 *
947 * Since: 3.6
948 **/
949 const gchar *
e_source_webdav_get_email_address(ESourceWebdav * extension)950 e_source_webdav_get_email_address (ESourceWebdav *extension)
951 {
952 g_return_val_if_fail (E_IS_SOURCE_WEBDAV (extension), NULL);
953
954 return extension->priv->email_address;
955 }
956
957 /**
958 * e_source_webdav_dup_email_address:
959 * @extension: an #ESourceWebdav
960 *
961 * Thread-safe variation of e_source_webdav_get_email_address().
962 * Use this function when accessing @extension from multiple threads.
963 *
964 * The returned string should be freed with g_free() when no longer needed.
965 *
966 * Returns: (nullable): the newly-allocated copy of #ESourceWebdav:email-address
967 *
968 * Since: 3.6
969 **/
970 gchar *
e_source_webdav_dup_email_address(ESourceWebdav * extension)971 e_source_webdav_dup_email_address (ESourceWebdav *extension)
972 {
973 const gchar *protected;
974 gchar *duplicate;
975
976 g_return_val_if_fail (E_IS_SOURCE_WEBDAV (extension), NULL);
977
978 e_source_extension_property_lock (E_SOURCE_EXTENSION (extension));
979
980 protected = e_source_webdav_get_email_address (extension);
981 duplicate = g_strdup (protected);
982
983 e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
984
985 return duplicate;
986 }
987
988 /**
989 * e_source_webdav_set_email_address:
990 * @extension: an #ESourceWebdav
991 * @email_address: (nullable): the user's email address, or %NULL
992 *
993 * Sets the user's email address which can be passed to a CalDAV server if
994 * the user wishes to receive scheduling messages.
995 *
996 * The internal copy of @email_address is automatically stripped of leading
997 * and trailing whitespace. If the resulting string is empty, %NULL is set
998 * instead.
999 *
1000 * Since: 3.6
1001 **/
1002 void
e_source_webdav_set_email_address(ESourceWebdav * extension,const gchar * email_address)1003 e_source_webdav_set_email_address (ESourceWebdav *extension,
1004 const gchar *email_address)
1005 {
1006 g_return_if_fail (E_IS_SOURCE_WEBDAV (extension));
1007
1008 e_source_extension_property_lock (E_SOURCE_EXTENSION (extension));
1009
1010 if (e_util_strcmp0 (extension->priv->email_address, email_address) == 0) {
1011 e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
1012 return;
1013 }
1014
1015 g_free (extension->priv->email_address);
1016 extension->priv->email_address = e_util_strdup_strip (email_address);
1017
1018 e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
1019
1020 g_object_notify (G_OBJECT (extension), "email-address");
1021 }
1022
1023 /**
1024 * e_source_webdav_get_resource_path:
1025 * @extension: an #ESourceWebdav
1026 *
1027 * Returns the absolute path to a resource on a WebDAV server.
1028 *
1029 * Returns: (nullable): the absolute path to a WebDAV resource
1030 *
1031 * Since: 3.6
1032 **/
1033 const gchar *
e_source_webdav_get_resource_path(ESourceWebdav * extension)1034 e_source_webdav_get_resource_path (ESourceWebdav *extension)
1035 {
1036 g_return_val_if_fail (E_IS_SOURCE_WEBDAV (extension), NULL);
1037
1038 return extension->priv->resource_path;
1039 }
1040
1041 /**
1042 * e_source_webdav_dup_resource_path:
1043 * @extension: an #ESourceWebdav
1044 *
1045 * Thread-safe variation of e_source_webdav_get_resource_path().
1046 * Use this function when accessing @extension from multiple threads.
1047 *
1048 * The returned string should be freed with g_free() when no longer needed.
1049 *
1050 * Returns: (nullable): the newly-allocated copy of #ESourceWebdav:resource-path
1051 *
1052 * Since: 3.6
1053 **/
1054 gchar *
e_source_webdav_dup_resource_path(ESourceWebdav * extension)1055 e_source_webdav_dup_resource_path (ESourceWebdav *extension)
1056 {
1057 const gchar *protected;
1058 gchar *duplicate;
1059
1060 g_return_val_if_fail (E_IS_SOURCE_WEBDAV (extension), NULL);
1061
1062 e_source_extension_property_lock (E_SOURCE_EXTENSION (extension));
1063
1064 protected = e_source_webdav_get_resource_path (extension);
1065 duplicate = g_strdup (protected);
1066
1067 e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
1068
1069 return duplicate;
1070 }
1071
1072 /**
1073 * e_source_webdav_set_resource_path:
1074 * @extension: an #ESourceWebdav
1075 * @resource_path: (nullable): the absolute path to a WebDAV resource,
1076 * or %NULL
1077 *
1078 * Sets the absolute path to a resource on a WebDAV server.
1079 *
1080 * The internal copy of @resource_path is automatically stripped of leading
1081 * and trailing whitespace. If the resulting string is empty, %NULL is set
1082 * instead.
1083 *
1084 * Since: 3.6
1085 **/
1086 void
e_source_webdav_set_resource_path(ESourceWebdav * extension,const gchar * resource_path)1087 e_source_webdav_set_resource_path (ESourceWebdav *extension,
1088 const gchar *resource_path)
1089 {
1090 g_return_if_fail (E_IS_SOURCE_WEBDAV (extension));
1091
1092 e_source_extension_property_lock (E_SOURCE_EXTENSION (extension));
1093
1094 if (e_util_strcmp0 (extension->priv->resource_path, resource_path) == 0) {
1095 e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
1096 return;
1097 }
1098
1099 g_free (extension->priv->resource_path);
1100 extension->priv->resource_path = e_util_strdup_strip (resource_path);
1101
1102 e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
1103
1104 g_object_notify (G_OBJECT (extension), "resource-path");
1105 }
1106
1107 /**
1108 * e_source_webdav_get_resource_query:
1109 * @extension: an #ESourceWebdav
1110 *
1111 * Returns the URI query required to access a resource on a WebDAV server.
1112 *
1113 * This is typically used when the #ESourceWebdav:resource-path points not
1114 * to the resource itself but to a web program that generates the resource
1115 * content on-the-fly. The #ESourceWebdav:resource-query holds the input
1116 * values for the program.
1117 *
1118 * Returns: (nullable): the query to access a WebDAV resource
1119 *
1120 * Since: 3.6
1121 **/
1122 const gchar *
e_source_webdav_get_resource_query(ESourceWebdav * extension)1123 e_source_webdav_get_resource_query (ESourceWebdav *extension)
1124 {
1125 g_return_val_if_fail (E_IS_SOURCE_WEBDAV (extension), NULL);
1126
1127 return extension->priv->resource_query;
1128 }
1129
1130 /**
1131 * e_source_webdav_dup_resource_query:
1132 * @extension: an #ESourceWebdav
1133 *
1134 * Thread-safe variation of e_source_webdav_get_resource_query().
1135 * Use this function when accessing @extension from multiple threads.
1136 *
1137 * The returned string should be freed with g_free() when no longer needed.
1138 *
1139 * Returns: (nullable): the newly-allocated copy of #ESourceWebdav:resource-query
1140 *
1141 * Since: 3.6
1142 **/
1143 gchar *
e_source_webdav_dup_resource_query(ESourceWebdav * extension)1144 e_source_webdav_dup_resource_query (ESourceWebdav *extension)
1145 {
1146 const gchar *protected;
1147 gchar *duplicate;
1148
1149 g_return_val_if_fail (E_IS_SOURCE_WEBDAV (extension), NULL);
1150
1151 e_source_extension_property_lock (E_SOURCE_EXTENSION (extension));
1152
1153 protected = e_source_webdav_get_resource_query (extension);
1154 duplicate = g_strdup (protected);
1155
1156 e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
1157
1158 return duplicate;
1159 }
1160
1161 /**
1162 * e_source_webdav_set_resource_query:
1163 * @extension: an #ESourceWebdav
1164 * @resource_query: (nullable): the query to access a WebDAV resource,
1165 * or %NULL
1166 *
1167 * Sets the URI query required to access a resource on a WebDAV server.
1168 *
1169 * This is typically used when the #ESourceWebdav:resource-path points not
1170 * to the resource itself but to a web program that generates the resource
1171 * content on-the-fly. The #ESourceWebdav:resource-query holds the input
1172 * values for the program.
1173 *
1174 * The internal copy of @resource_query is automatically stripped of leading
1175 * and trailing whitespace. If the resulting string is empty, %NULL is set
1176 * instead.
1177 *
1178 * Since: 3.6
1179 **/
1180 void
e_source_webdav_set_resource_query(ESourceWebdav * extension,const gchar * resource_query)1181 e_source_webdav_set_resource_query (ESourceWebdav *extension,
1182 const gchar *resource_query)
1183 {
1184 g_return_if_fail (E_IS_SOURCE_WEBDAV (extension));
1185
1186 e_source_extension_property_lock (E_SOURCE_EXTENSION (extension));
1187
1188 if (e_util_strcmp0 (extension->priv->resource_query, resource_query) == 0) {
1189 e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
1190 return;
1191 }
1192
1193 g_free (extension->priv->resource_query);
1194 extension->priv->resource_query = e_util_strdup_strip (resource_query);
1195
1196 e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
1197
1198 g_object_notify (G_OBJECT (extension), "resource-query");
1199 }
1200
1201 /**
1202 * e_source_webdav_get_ssl_trust:
1203 * @extension: an #ESourceWebdav
1204 *
1205 * Returns an SSL/TLS certificate trust for the @extension.
1206 * The value encodes three parameters, divided by a pipe '|',
1207 * the first is users preference, can be one of "reject", "accept",
1208 * "temporary-reject" and "temporary-accept". The second is a host
1209 * name for which the trust was set. Finally the last is a SHA256
1210 * hash of the certificate. This is not meant to be changed by a caller,
1211 * it is supposed to be manipulated with e_source_webdav_update_ssl_trust()
1212 * and e_source_webdav_verify_ssl_trust().
1213 *
1214 * Returns: (nullable): an SSL/TLS certificate trust for the @extension
1215 *
1216 * Since: 3.8
1217 **/
1218 const gchar *
e_source_webdav_get_ssl_trust(ESourceWebdav * extension)1219 e_source_webdav_get_ssl_trust (ESourceWebdav *extension)
1220 {
1221 g_return_val_if_fail (E_IS_SOURCE_WEBDAV (extension), NULL);
1222
1223 return extension->priv->ssl_trust;
1224 }
1225
1226 /**
1227 * e_source_webdav_dup_ssl_trust:
1228 * @extension: an #ESourceWebdav
1229 *
1230 * Thread-safe variation of e_source_webdav_get_ssl_trust().
1231 * Use this function when accessing @extension from multiple threads.
1232 *
1233 * The returned string should be freed with g_free() when no longer needed.
1234 *
1235 * Returns: (nullable): the newly-allocated copy of #ESourceWebdav:ssl-trust
1236 *
1237 * Since: 3.8
1238 **/
1239 gchar *
e_source_webdav_dup_ssl_trust(ESourceWebdav * extension)1240 e_source_webdav_dup_ssl_trust (ESourceWebdav *extension)
1241 {
1242 const gchar *protected;
1243 gchar *duplicate;
1244
1245 g_return_val_if_fail (E_IS_SOURCE_WEBDAV (extension), NULL);
1246
1247 e_source_extension_property_lock (E_SOURCE_EXTENSION (extension));
1248
1249 protected = e_source_webdav_get_ssl_trust (extension);
1250 duplicate = g_strdup (protected);
1251
1252 e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
1253
1254 return duplicate;
1255 }
1256
1257 /**
1258 * e_source_webdav_set_ssl_trust:
1259 * @extension: an #ESourceWebdav
1260 * @ssl_trust: (nullable): the ssl_trust to store, or %NULL to unset
1261 *
1262 * Sets the SSL/TLS certificate trust. See e_source_webdav_get_ssl_trust()
1263 * for more infomation about its content and how to use it.
1264 *
1265 * Since: 3.8
1266 **/
1267 void
e_source_webdav_set_ssl_trust(ESourceWebdav * extension,const gchar * ssl_trust)1268 e_source_webdav_set_ssl_trust (ESourceWebdav *extension,
1269 const gchar *ssl_trust)
1270 {
1271 g_return_if_fail (E_IS_SOURCE_WEBDAV (extension));
1272
1273 e_source_extension_property_lock (E_SOURCE_EXTENSION (extension));
1274
1275 if (e_util_strcmp0 (extension->priv->ssl_trust, ssl_trust) == 0) {
1276 e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
1277 return;
1278 }
1279
1280 g_free (extension->priv->ssl_trust);
1281 extension->priv->ssl_trust = g_strdup (ssl_trust);
1282
1283 e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
1284
1285 g_object_notify (G_OBJECT (extension), "ssl-trust");
1286 }
1287
1288 /**
1289 * e_source_webdav_dup_soup_uri:
1290 * @extension: an #ESourceWebdav
1291 *
1292 * This is a convenience function which returns a newly-allocated
1293 * #SoupURI, its contents assembled from the #ESourceAuthentication
1294 * extension, the #ESourceSecurity extension, and @extension itself.
1295 * Free the returned #SoupURI with soup_uri_free().
1296 *
1297 * Returns: (transfer full): a newly-allocated #SoupURI
1298 *
1299 * Since: 3.6
1300 **/
1301 SoupURI *
e_source_webdav_dup_soup_uri(ESourceWebdav * extension)1302 e_source_webdav_dup_soup_uri (ESourceWebdav *extension)
1303 {
1304 SoupURI *duplicate;
1305
1306 g_return_val_if_fail (E_IS_SOURCE_WEBDAV (extension), NULL);
1307
1308 /* Keep this outside of the property lock. */
1309 source_webdav_update_soup_uri_from_properties (extension);
1310
1311 e_source_extension_property_lock (E_SOURCE_EXTENSION (extension));
1312
1313 duplicate = soup_uri_copy (extension->priv->soup_uri);
1314
1315 e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
1316
1317 return duplicate;
1318 }
1319
1320 /**
1321 * e_source_webdav_set_soup_uri:
1322 * @extension: an #ESourceWebdav
1323 * @soup_uri: a #SoupURI
1324 *
1325 * This is a convenience function which propagates the components of
1326 * @uri to the #ESourceAuthentication extension, the #ESourceSecurity
1327 * extension, and @extension itself. (The "fragment" component of
1328 * @uri is ignored.)
1329 *
1330 * Since: 3.6
1331 **/
1332 void
e_source_webdav_set_soup_uri(ESourceWebdav * extension,SoupURI * soup_uri)1333 e_source_webdav_set_soup_uri (ESourceWebdav *extension,
1334 SoupURI *soup_uri)
1335 {
1336 g_return_if_fail (E_IS_SOURCE_WEBDAV (extension));
1337 g_return_if_fail (SOUP_URI_IS_VALID (soup_uri));
1338
1339 e_source_extension_property_lock (E_SOURCE_EXTENSION (extension));
1340
1341 /* Do not test for URI equality because our
1342 * internal SoupURI might not be up-to-date. */
1343
1344 soup_uri_free (extension->priv->soup_uri);
1345 extension->priv->soup_uri = soup_uri_copy (soup_uri);
1346
1347 e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
1348
1349 g_object_freeze_notify (G_OBJECT (extension));
1350 source_webdav_update_properties_from_soup_uri (extension);
1351 g_object_notify (G_OBJECT (extension), "soup-uri");
1352 g_object_thaw_notify (G_OBJECT (extension));
1353 }
1354
1355 static gboolean
decode_ssl_trust(ESourceWebdav * extension,ETrustPromptResponse * response,gchar ** host,gchar ** hash)1356 decode_ssl_trust (ESourceWebdav *extension,
1357 ETrustPromptResponse *response,
1358 gchar **host,
1359 gchar **hash)
1360 {
1361 gchar *ssl_trust, **strv;
1362
1363 g_return_val_if_fail (E_IS_SOURCE_WEBDAV (extension), FALSE);
1364
1365 ssl_trust = e_source_webdav_dup_ssl_trust (extension);
1366 if (!ssl_trust || !*ssl_trust) {
1367 g_free (ssl_trust);
1368 return FALSE;
1369 }
1370
1371 strv = g_strsplit (ssl_trust, "|", 3);
1372 if (!strv || !strv[0] || !strv[1] || !strv[2] || strv[3]) {
1373 g_free (ssl_trust);
1374 g_strfreev (strv);
1375 return FALSE;
1376 }
1377
1378 if (response) {
1379 const gchar *resp = strv[0];
1380
1381 if (g_strcmp0 (resp, "reject") == 0)
1382 *response = E_TRUST_PROMPT_RESPONSE_REJECT;
1383 else if (g_strcmp0 (resp, "accept") == 0)
1384 *response = E_TRUST_PROMPT_RESPONSE_ACCEPT;
1385 else if (g_strcmp0 (resp, "temporary-reject") == 0)
1386 *response = E_TRUST_PROMPT_RESPONSE_REJECT_TEMPORARILY;
1387 else if (g_strcmp0 (resp, "temporary-accept") == 0)
1388 *response = E_TRUST_PROMPT_RESPONSE_ACCEPT_TEMPORARILY;
1389 else
1390 *response = E_TRUST_PROMPT_RESPONSE_UNKNOWN;
1391 }
1392
1393 if (host)
1394 *host = g_strdup (strv[1]);
1395
1396 if (hash)
1397 *hash = g_strdup (strv[2]);
1398
1399 g_free (ssl_trust);
1400 g_strfreev (strv);
1401
1402 return TRUE;
1403 }
1404
1405 static gboolean
encode_ssl_trust(ESourceWebdav * extension,ETrustPromptResponse response,const gchar * host,const gchar * hash)1406 encode_ssl_trust (ESourceWebdav *extension,
1407 ETrustPromptResponse response,
1408 const gchar *host,
1409 const gchar *hash)
1410 {
1411 gchar *ssl_trust;
1412 const gchar *resp;
1413 gboolean changed;
1414
1415 g_return_val_if_fail (E_IS_SOURCE_WEBDAV (extension), FALSE);
1416
1417 if (response == E_TRUST_PROMPT_RESPONSE_REJECT)
1418 resp = "reject";
1419 else if (response == E_TRUST_PROMPT_RESPONSE_ACCEPT)
1420 resp = "accept";
1421 else if (response == E_TRUST_PROMPT_RESPONSE_REJECT_TEMPORARILY)
1422 resp = "temporary-reject";
1423 else if (response == E_TRUST_PROMPT_RESPONSE_ACCEPT_TEMPORARILY)
1424 resp = "temporary-accept";
1425 else
1426 resp = "temporary-reject";
1427
1428 if (host && *host && hash && *hash) {
1429 ssl_trust = g_strconcat (resp, "|", host, "|", hash, NULL);
1430 } else {
1431 ssl_trust = NULL;
1432 }
1433
1434 changed = g_strcmp0 (extension->priv->ssl_trust, ssl_trust) != 0;
1435
1436 if (changed)
1437 e_source_webdav_set_ssl_trust (extension, ssl_trust);
1438
1439 g_free (ssl_trust);
1440
1441 return changed;
1442 }
1443
1444 /**
1445 * e_source_webdav_update_ssl_trust:
1446 * @extension: an #ESourceWebdav
1447 * @host: a host name to store the certificate for
1448 * @cert: the invalid certificate of the connection over which @host is about
1449 * to be sent
1450 * @response: user's response from a trust prompt for @cert
1451 *
1452 * Updates user's response from a trust prompt, thus it is re-used the next
1453 * time it'll be needed. An #E_TRUST_PROMPT_RESPONSE_UNKNOWN is treated as
1454 * a temporary reject, which means the user will be asked again.
1455 *
1456 * Since: 3.16
1457 **/
1458 void
e_source_webdav_update_ssl_trust(ESourceWebdav * extension,const gchar * host,GTlsCertificate * cert,ETrustPromptResponse response)1459 e_source_webdav_update_ssl_trust (ESourceWebdav *extension,
1460 const gchar *host,
1461 GTlsCertificate *cert,
1462 ETrustPromptResponse response)
1463 {
1464 GByteArray *bytes = NULL;
1465 gchar *hash;
1466
1467 g_return_if_fail (E_IS_SOURCE_WEBDAV (extension));
1468 g_return_if_fail (host != NULL);
1469 g_return_if_fail (cert != NULL);
1470
1471 g_object_get (cert, "certificate", &bytes, NULL);
1472
1473 if (!bytes)
1474 return;
1475
1476 hash = g_compute_checksum_for_data (G_CHECKSUM_SHA256, bytes->data, bytes->len);
1477
1478 encode_ssl_trust (extension, response, host, hash);
1479
1480 g_byte_array_unref (bytes);
1481 g_free (hash);
1482 }
1483
1484 /**
1485 * e_source_webdav_verify_ssl_trust:
1486 * @extension: an #ESourceWebdav
1487 * @host: a host name to store the certificate for
1488 * @cert: the invalid certificate of the connection over which @host is about
1489 * to be sent
1490 * @cert_errors: a bit-or of #GTlsCertificateFlags describing the reason
1491 * for the @cert to be considered invalid
1492 *
1493 * Verifies SSL/TLS trust for the given @host and @cert, as previously stored in the @extension
1494 * with e_source_webdav_update_ssl_trust().
1495 **/
1496 ETrustPromptResponse
e_source_webdav_verify_ssl_trust(ESourceWebdav * extension,const gchar * host,GTlsCertificate * cert,GTlsCertificateFlags cert_errors)1497 e_source_webdav_verify_ssl_trust (ESourceWebdav *extension,
1498 const gchar *host,
1499 GTlsCertificate *cert,
1500 GTlsCertificateFlags cert_errors)
1501 {
1502 ETrustPromptResponse response;
1503 GByteArray *bytes = NULL;
1504 gchar *old_host = NULL;
1505 gchar *old_hash = NULL;
1506
1507 g_return_val_if_fail (E_IS_SOURCE_WEBDAV (extension), E_TRUST_PROMPT_RESPONSE_UNKNOWN);
1508 g_return_val_if_fail (host != NULL, E_TRUST_PROMPT_RESPONSE_UNKNOWN);
1509 g_return_val_if_fail (cert != NULL, E_TRUST_PROMPT_RESPONSE_UNKNOWN);
1510
1511 /* Always reject revoked certificates */
1512 if ((cert_errors & G_TLS_CERTIFICATE_REVOKED) != 0)
1513 return E_TRUST_PROMPT_RESPONSE_REJECT;
1514
1515 g_object_get (cert, "certificate", &bytes, NULL);
1516
1517 if (bytes == NULL)
1518 return E_TRUST_PROMPT_RESPONSE_REJECT;
1519
1520 if (decode_ssl_trust (extension, &response, &old_host, &old_hash)) {
1521 gchar *hash;
1522
1523 /* This is required for Flatpak, which can be built with eds before the 3.40, where
1524 had been changed to use SHA256. */
1525 if (old_hash && strlen (old_hash) == g_checksum_type_get_length (G_CHECKSUM_SHA1) * 2)
1526 hash = g_compute_checksum_for_data (G_CHECKSUM_SHA1, bytes->data, bytes->len);
1527 else
1528 hash = g_compute_checksum_for_data (G_CHECKSUM_SHA256, bytes->data, bytes->len);
1529
1530 if (response != E_TRUST_PROMPT_RESPONSE_UNKNOWN &&
1531 g_strcmp0 (old_host, host) == 0 &&
1532 g_strcmp0 (old_hash, hash) == 0) {
1533 g_byte_array_unref (bytes);
1534 g_free (old_host);
1535 g_free (old_hash);
1536 g_free (hash);
1537
1538 return response;
1539 }
1540
1541 g_free (old_host);
1542 g_free (old_hash);
1543 g_free (hash);
1544 }
1545
1546 g_byte_array_unref (bytes);
1547
1548 return E_TRUST_PROMPT_RESPONSE_UNKNOWN;
1549 }
1550
1551 /**
1552 * e_source_webdav_unset_temporary_ssl_trust:
1553 * @extension: an #ESourceWebdav
1554 *
1555 * Unsets temporary trust set on this @extension, but keeps
1556 * it as is for other values.
1557 *
1558 * Since: 3.8
1559 **/
1560 void
e_source_webdav_unset_temporary_ssl_trust(ESourceWebdav * extension)1561 e_source_webdav_unset_temporary_ssl_trust (ESourceWebdav *extension)
1562 {
1563 ETrustPromptResponse response = E_TRUST_PROMPT_RESPONSE_UNKNOWN;
1564
1565 g_return_if_fail (E_IS_SOURCE_WEBDAV (extension));
1566
1567 if (!decode_ssl_trust (extension, &response, NULL, NULL) ||
1568 response == E_TRUST_PROMPT_RESPONSE_UNKNOWN ||
1569 response == E_TRUST_PROMPT_RESPONSE_REJECT_TEMPORARILY ||
1570 response == E_TRUST_PROMPT_RESPONSE_ACCEPT_TEMPORARILY)
1571 e_source_webdav_set_ssl_trust (extension, NULL);
1572 }
1573
1574 /**
1575 * e_source_webdav_get_ssl_trust_response:
1576 * @extension: an #ESourceWebdav
1577 *
1578 * Returns: the last SSL trust response, as #ETrustPromptResponse, if none
1579 * is set, then returns %E_TRUST_PROMPT_RESPONSE_UNKNOWN
1580 *
1581 * Since: 3.32
1582 **/
1583 ETrustPromptResponse
e_source_webdav_get_ssl_trust_response(ESourceWebdav * extension)1584 e_source_webdav_get_ssl_trust_response (ESourceWebdav *extension)
1585 {
1586 ETrustPromptResponse response = E_TRUST_PROMPT_RESPONSE_UNKNOWN;
1587
1588 g_return_val_if_fail (E_IS_SOURCE_WEBDAV (extension), E_TRUST_PROMPT_RESPONSE_UNKNOWN);
1589
1590 if (!decode_ssl_trust (extension, &response, NULL, NULL))
1591 response = E_TRUST_PROMPT_RESPONSE_UNKNOWN;
1592
1593 return response;
1594 }
1595
1596 /**
1597 * e_source_webdav_set_ssl_trust_response:
1598 * @extension: an #ESourceWebdav
1599 * @response: an #ETrustPromptResponse to set
1600 *
1601 * Set the SSL trust response, as #ETrustPromptResponse, while keeping
1602 * the certificate and host information as before. The function does
1603 * nothing, when none SSL trust is set or when %E_TRUST_PROMPT_RESPONSE_UNKNOWN
1604 * is used as the @response.
1605 *
1606 * Since: 3.32
1607 **/
1608 void
e_source_webdav_set_ssl_trust_response(ESourceWebdav * extension,ETrustPromptResponse response)1609 e_source_webdav_set_ssl_trust_response (ESourceWebdav *extension,
1610 ETrustPromptResponse response)
1611 {
1612 gchar *host = NULL, *hash = NULL;
1613
1614 g_return_if_fail (E_IS_SOURCE_WEBDAV (extension));
1615
1616 if (response != E_TRUST_PROMPT_RESPONSE_UNKNOWN &&
1617 decode_ssl_trust (extension, NULL, &host, &hash))
1618 encode_ssl_trust (extension, response, host, hash);
1619
1620 g_free (host);
1621 g_free (hash);
1622 }
1623
1624 /**
1625 * e_source_webdav_get_order:
1626 * @extension: an #ESourceWebdav
1627 *
1628 * Returns: the sorting order of the resource, if known. The default
1629 * is (guint) -1, which means unknown/unset.
1630 *
1631 * Since: 3.40
1632 **/
1633 guint
e_source_webdav_get_order(ESourceWebdav * extension)1634 e_source_webdav_get_order (ESourceWebdav *extension)
1635 {
1636 g_return_val_if_fail (E_IS_SOURCE_WEBDAV (extension), (guint) -1);
1637
1638 return extension->priv->order;
1639 }
1640
1641 /**
1642 * e_source_webdav_set_order:
1643 * @extension: an #ESourceWebdav
1644 * @order: a sorting order
1645 *
1646 * Set the sorting order of the resource.
1647 *
1648 * Since: 3.40
1649 **/
1650 void
e_source_webdav_set_order(ESourceWebdav * extension,guint order)1651 e_source_webdav_set_order (ESourceWebdav *extension,
1652 guint order)
1653 {
1654 g_return_if_fail (E_IS_SOURCE_WEBDAV (extension));
1655
1656 if (extension->priv->order == order)
1657 return;
1658
1659 extension->priv->order = order;
1660
1661 g_object_notify (G_OBJECT (extension), "order");
1662 }
1663