[gnome-calendar] Introduce new source discoverer
- From: Georges Basile Stavracas Neto <gbsneto src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-calendar] Introduce new source discoverer
- Date: Sat, 13 Jul 2019 19:05:42 +0000 (UTC)
commit 371fdbc881e5e92d85a64989eac6a824b151dc52
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date: Wed Jul 10 19:04:50 2019 -0300
Introduce new source discoverer
The new source discoverer is a complete overhaul of
the current code. It is async-only, correctly threaded,
and easier to maintain.
A major new feature of this web source discoverer is
that it now pings the server to see if the URL feeds
us back with an iCalendar file.
Furthermore, it continues to use E-D-S WebDAV discovery
functions as a fallback mechanism.
Fixes #380
src/meson.build | 1 +
src/utils/gcal-source-discoverer.c | 405 +++++++++++++++++++++++++++++++++++++
src/utils/gcal-source-discoverer.h | 52 +++++
tests/gcal-simple-server.c | 2 +-
tests/meson.build | 1 +
tests/test-discoverer.c | 190 +++++++++++++++++
6 files changed, 650 insertions(+), 1 deletion(-)
---
diff --git a/src/meson.build b/src/meson.build
index 90938097..91a06dd3 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -124,6 +124,7 @@ sources = files(
'search/gcal-search-hit-event.c',
'search/gcal-search-model.c',
'utils/gcal-date-time-utils.c',
+ 'utils/gcal-source-discoverer.c',
'utils/gcal-thread-utils.c',
'utils/gcal-utils.c',
'views/gcal-month-cell.c',
diff --git a/src/utils/gcal-source-discoverer.c b/src/utils/gcal-source-discoverer.c
new file mode 100644
index 00000000..6c61cdab
--- /dev/null
+++ b/src/utils/gcal-source-discoverer.c
@@ -0,0 +1,405 @@
+/* gcal-source-discoverer.c
+ *
+ * Copyright 2019 Georges Basile Stavracas Neto <georges stavracas gmail com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#define G_LOG_DOMAIN "GcalSourceDiscoverer"
+
+#include <libecal/libecal.h>
+#include <libsoup/soup.h>
+
+#include "gcal-debug.h"
+#include "gcal-source-discoverer.h"
+#include "gcal-utils.h"
+
+G_DEFINE_QUARK (GcalSourceDiscoverer, gcal_source_discoverer_error);
+
+typedef struct
+{
+ gchar *uri;
+ gchar *username;
+ gchar *password;
+} DiscovererData;
+
+
+/*
+ * Auxiliary methods
+ */
+
+static void
+discoverer_data_free (gpointer data)
+{
+ DiscovererData *discoverer_data = data;
+
+ if (!discoverer_data)
+ return;
+
+ g_free (discoverer_data->uri);
+ g_free (discoverer_data->username);
+ g_free (discoverer_data->password);
+ g_free (discoverer_data);
+}
+
+static ESource*
+create_source_for_uri (DiscovererData *data)
+{
+ ESourceAuthentication *auth;
+ g_autoptr (SoupURI) soup_uri = NULL;
+ g_autofree gchar *display_name = NULL;
+ g_autofree gchar *basename = NULL;
+ ESourceExtension *ext;
+ ESourceWebdav *webdav;
+ ESource *source;
+ const gchar *host;
+ const gchar *path;
+
+ soup_uri = soup_uri_new (data->uri);
+ if (!soup_uri)
+ GCAL_RETURN (NULL);
+
+ host = soup_uri_get_host (soup_uri);
+
+ /* Create the new source and add the needed extensions */
+ source = e_source_new (NULL, NULL, NULL);
+ e_source_set_parent (source, "webcal-stub");
+
+ /* Display name */
+ path = soup_uri_get_path (soup_uri);
+ basename = g_path_get_basename (path);
+ display_name = gcal_utils_format_filename_for_display (basename);
+ e_source_set_display_name (source, display_name);
+
+ ext = e_source_get_extension (source, E_SOURCE_EXTENSION_CALENDAR);
+ e_source_backend_set_backend_name (E_SOURCE_BACKEND (ext), "webcal");
+
+ /* Authentication */
+ auth = e_source_get_extension (source, E_SOURCE_EXTENSION_AUTHENTICATION);
+ e_source_authentication_set_host (auth, host);
+
+ /* Webdav */
+ webdav = e_source_get_extension (source, E_SOURCE_EXTENSION_WEBDAV_BACKEND);
+ e_source_webdav_set_soup_uri (webdav, soup_uri);
+
+ return source;
+}
+
+static ESource*
+create_discovered_source (ESource *source,
+ GSList *user_addresses,
+ EWebDAVDiscoveredSource *discovered_source)
+{
+ g_autoptr (SoupURI) soup_uri = NULL;
+ ESourceSelectable *selectable;
+ ESourceExtension *ext;
+ ESourceWebdav *webdav;
+ ESource *new_source;
+ const gchar *resource_path;
+
+ soup_uri = soup_uri_new (discovered_source->href);
+ resource_path = soup_uri_get_path (soup_uri);
+
+ new_source = e_source_new (NULL, NULL, NULL);
+ e_source_set_parent (new_source, "local");
+
+ ext = e_source_get_extension (new_source, E_SOURCE_EXTENSION_CALENDAR);
+ e_source_backend_set_backend_name (E_SOURCE_BACKEND (ext), "local");
+
+ /* Copy Authentication data */
+ if (e_source_has_extension (source, E_SOURCE_EXTENSION_AUTHENTICATION))
+ {
+ ESourceAuthentication *new_auth, *parent_auth;
+
+ parent_auth = e_source_get_extension (source, E_SOURCE_EXTENSION_AUTHENTICATION);
+ new_auth = e_source_get_extension (new_source, E_SOURCE_EXTENSION_AUTHENTICATION);
+
+ e_source_authentication_set_host (new_auth, e_source_authentication_get_host (parent_auth));
+ e_source_authentication_set_method (new_auth, e_source_authentication_get_method (parent_auth));
+ e_source_authentication_set_port (new_auth, e_source_authentication_get_port (parent_auth));
+ e_source_authentication_set_user (new_auth, e_source_authentication_get_user (parent_auth));
+ e_source_authentication_set_proxy_uid (new_auth, e_source_authentication_get_proxy_uid (parent_auth));
+ }
+
+ /* Copy Webdav data */
+ if (e_source_has_extension (source, E_SOURCE_EXTENSION_WEBDAV_BACKEND))
+ {
+ ESourceWebdav *new_webdav, *parent_webdav;
+
+ parent_webdav = e_source_get_extension (source, E_SOURCE_EXTENSION_WEBDAV_BACKEND);
+ new_webdav = e_source_get_extension (new_source, E_SOURCE_EXTENSION_WEBDAV_BACKEND);
+
+ e_source_webdav_set_display_name (new_webdav, e_source_webdav_get_display_name (parent_webdav));
+ e_source_webdav_set_resource_path (new_webdav, e_source_webdav_get_resource_path (parent_webdav));
+ e_source_webdav_set_resource_query (new_webdav, e_source_webdav_get_resource_query (parent_webdav));
+ e_source_webdav_set_email_address (new_webdav, e_source_webdav_get_email_address (parent_webdav));
+ e_source_webdav_set_ssl_trust (new_webdav, e_source_webdav_get_ssl_trust (parent_webdav));
+
+ e_source_set_parent (new_source, "webcal-stub");
+ e_source_backend_set_backend_name (E_SOURCE_BACKEND (ext), "webcal");
+ }
+
+ /* build up the new source */
+ e_source_set_display_name (new_source, discovered_source->display_name);
+
+ webdav = e_source_get_extension (new_source, E_SOURCE_EXTENSION_WEBDAV_BACKEND);
+ e_source_webdav_set_resource_path (webdav, resource_path);
+ e_source_webdav_set_display_name (webdav, discovered_source->display_name);
+
+ if (user_addresses)
+ e_source_webdav_set_email_address (webdav, user_addresses->data);
+
+ /* Setup the color */
+ selectable = e_source_get_extension (new_source, E_SOURCE_EXTENSION_CALENDAR);
+ e_source_selectable_set_color (selectable, discovered_source->color);
+
+ return new_source;
+}
+
+static gboolean
+is_authentication_error (gint code)
+{
+ switch (code)
+ {
+ case SOUP_STATUS_UNAUTHORIZED:
+ case SOUP_STATUS_FORBIDDEN:
+ case SOUP_STATUS_METHOD_NOT_ALLOWED:
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+/*
+ * Callbacks
+ */
+
+static void
+on_soup_session_authenticate_cb (SoupSession *session,
+ SoupMessage *message,
+ SoupAuth *auth,
+ gboolean retrying,
+ gpointer user_data)
+{
+ DiscovererData *data = user_data;
+
+ if (data->username && data->password)
+ soup_auth_authenticate (auth, data->username, data->password);
+ else
+ soup_message_set_status (message, SOUP_STATUS_UNAUTHORIZED);
+}
+
+typedef GPtrArray* (*DiscoverFunc) (DiscovererData *data,
+ GCancellable *cancellable,
+ GError **error);
+
+static GPtrArray*
+discover_file_in_thread (DiscovererData *data,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_autoptr (GInputStream) input_stream = NULL;
+ g_autoptr (SoupMessage) message = NULL;
+ g_autoptr (SoupSession) session = NULL;
+ g_autoptr (GPtrArray) source = NULL;
+ const gchar *content_type;
+
+ GCAL_ENTRY;
+
+ GCAL_TRACE_MSG ("Creating request for %s", data->uri);
+
+ session = soup_session_new_with_options (SOUP_SESSION_TIMEOUT, 10, NULL);
+ g_signal_connect (session, "authenticate", G_CALLBACK (on_soup_session_authenticate_cb), data);
+
+ message = soup_message_new ("GET", data->uri);
+ input_stream = soup_session_send (session, message, cancellable, error);
+
+ if (!input_stream)
+ GCAL_RETURN (NULL);
+
+ g_input_stream_close (input_stream, cancellable, error);
+
+ content_type = soup_message_headers_get_content_type (message->response_headers, NULL);
+ GCAL_TRACE_MSG ("Message retrieved, content type: %s, status code: %u", content_type,
message->status_code);
+
+ if (is_authentication_error (message->status_code))
+ {
+ g_set_error (error,
+ GCAL_SOURCE_DISCOVERER_ERROR,
+ GCAL_SOURCE_DISCOVERER_ERROR_UNAUTHORIZED,
+ "%s",
+ soup_status_get_phrase (message->status_code));
+
+ GCAL_RETURN (NULL);
+ }
+
+ if (content_type && g_strstr_len (content_type, -1, "text/calendar") != NULL)
+ {
+ source = g_ptr_array_new_full (1, g_object_unref);
+ g_ptr_array_add (source, create_source_for_uri (data));
+ }
+
+ GCAL_RETURN (g_steal_pointer (&source));
+}
+
+static GPtrArray*
+discover_webdav_in_thread (DiscovererData *data,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_autoptr (ENamedParameters) credentials = NULL;
+ g_autoptr (GPtrArray) sources = NULL;
+ g_autoptr (ESource) source = NULL;
+ g_autoptr (GError) local_error = NULL;
+ g_autofree gchar *certificate_pem = NULL;
+ GTlsCertificateFlags flags;
+ GSList *discovered_sources = NULL;
+ GSList *user_addresses = NULL;
+ GSList *l;
+
+ GCAL_ENTRY;
+
+ credentials = e_named_parameters_new ();
+ e_named_parameters_set (credentials, E_SOURCE_CREDENTIAL_USERNAME, data->username);
+ e_named_parameters_set (credentials, E_SOURCE_CREDENTIAL_PASSWORD, data->password);
+
+ source = create_source_for_uri (data);
+
+ e_webdav_discover_sources_sync (source,
+ data->uri,
+ E_WEBDAV_DISCOVER_SUPPORTS_EVENTS,
+ credentials,
+ &certificate_pem,
+ &flags,
+ &discovered_sources,
+ &user_addresses,
+ cancellable,
+ &local_error);
+
+ if (local_error)
+ {
+ if (is_authentication_error (local_error->code))
+ {
+ g_set_error (error,
+ GCAL_SOURCE_DISCOVERER_ERROR,
+ GCAL_SOURCE_DISCOVERER_ERROR_UNAUTHORIZED,
+ "%s",
+ soup_status_get_phrase (local_error->code));
+ }
+ else
+ {
+ g_propagate_error (error, g_steal_pointer (&local_error));
+ }
+
+ GCAL_RETURN (NULL);
+ }
+
+ sources = g_ptr_array_new_full (g_slist_length (discovered_sources), g_object_unref);
+ for (l = discovered_sources; l; l = l->next)
+ {
+ EWebDAVDiscoveredSource *discovered_source;
+ ESource *new_source;
+
+ discovered_source = l->data;
+ new_source = create_discovered_source (source, user_addresses, discovered_source);
+
+ if (!new_source)
+ continue;
+
+ g_ptr_array_add (sources, new_source);
+ }
+
+ g_clear_pointer (&discovered_sources, e_webdav_discover_free_discovered_sources);
+ g_slist_free_full (user_addresses, g_free);
+
+ GCAL_RETURN (g_steal_pointer (&sources));
+}
+
+static void
+discover_sources_in_thread_cb (GTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ g_autoptr (GError) error = NULL;
+ DiscovererData *data = task_data;
+ guint i;
+
+ const DiscoverFunc discover_funcs[] = {
+ discover_file_in_thread,
+ discover_webdav_in_thread,
+ };
+
+ for (i = 0; i < G_N_ELEMENTS (discover_funcs); i++)
+ {
+ g_autoptr (GPtrArray) sources = NULL;
+ g_autoptr (GError) local_error = NULL;
+
+ sources = discover_funcs[i] (data, cancellable, &local_error);
+
+ if (sources)
+ {
+ g_task_return_pointer (task, g_steal_pointer (&sources), NULL);
+ return;
+ }
+ else if (local_error)
+ {
+ g_clear_error (&error);
+ g_propagate_error (&error, g_steal_pointer (&local_error));
+ }
+ }
+
+ if (error)
+ g_task_return_error (task, g_steal_pointer (&error));
+ else
+ g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_UNKNOWN, "Unknown error");
+}
+
+void
+gcal_discover_sources_from_uri (const gchar *uri,
+ const gchar *username,
+ const gchar *password,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr (GTask) task = NULL;
+ DiscovererData *data;
+
+ g_assert (uri != NULL);
+
+ data = g_new0 (DiscovererData, 1);
+ data->uri = g_strdup (uri);
+ data->username = g_strdup (username);
+ data->password = g_strdup (password);
+
+ task = g_task_new (NULL, cancellable, callback, user_data);
+ g_task_set_source_tag (task, gcal_discover_sources_from_uri);
+ g_task_set_task_data (task, data, discoverer_data_free);
+
+ g_task_run_in_thread (task, discover_sources_in_thread_cb);
+}
+
+GPtrArray*
+gcal_discover_sources_from_uri_finish (GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (g_task_is_valid (result, NULL), NULL);
+ g_return_val_if_fail (!error || !*error, NULL);
+
+ return g_task_propagate_pointer (G_TASK (result), error);
+}
diff --git a/src/utils/gcal-source-discoverer.h b/src/utils/gcal-source-discoverer.h
new file mode 100644
index 00000000..6e95bd2b
--- /dev/null
+++ b/src/utils/gcal-source-discoverer.h
@@ -0,0 +1,52 @@
+/* gcal-source-discoverer.h
+ *
+ * Copyright 2019 Georges Basile Stavracas Neto <georges stavracas gmail com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+/**
+ * GcalDiscovererError:
+ * @GCAL_SOURCE_DISCOVERER_ERROR_UNAUTHORIZED: indicated an invalid start date
+ *
+ * Errors that can generate.
+ */
+typedef enum
+{
+ GCAL_SOURCE_DISCOVERER_ERROR_UNAUTHORIZED,
+} GcalSourceDiscovererError;
+
+#define GCAL_SOURCE_DISCOVERER_ERROR (gcal_source_discoverer_error_quark ())
+
+GQuark gcal_source_discoverer_error_quark (void);
+
+void gcal_discover_sources_from_uri (const gchar *uri,
+ const gchar *username,
+ const gchar *password,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+GPtrArray* gcal_discover_sources_from_uri_finish (GAsyncResult *result,
+ GError **error);
+
+G_END_DECLS
diff --git a/tests/gcal-simple-server.c b/tests/gcal-simple-server.c
index 21ad7db8..15b3f010 100644
--- a/tests/gcal-simple-server.c
+++ b/tests/gcal-simple-server.c
@@ -88,7 +88,7 @@ static void
process_caldav (SoupMessage *message,
const gchar *path)
{
- g_message ("Processing CalDAV");
+ g_debug ("Processing CalDAV request");
}
diff --git a/tests/meson.build b/tests/meson.build
index a45a00ef..ec704dfd 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -33,6 +33,7 @@ libgcal_test_dep = declare_dependency(
tests = [
'server',
+ 'discoverer',
'event',
'manager',
]
diff --git a/tests/test-discoverer.c b/tests/test-discoverer.c
new file mode 100644
index 00000000..73ce1016
--- /dev/null
+++ b/tests/test-discoverer.c
@@ -0,0 +1,190 @@
+/* test-discoverer.c
+ *
+ * Copyright 2019 Georges Basile Stavracas Neto <georges stavracas gmail com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+
+#include <glib.h>
+#include <libecal/libecal.h>
+
+#include "gcal-simple-server.h"
+#include "gcal-source-discoverer.h"
+
+static GcalSimpleServer*
+init_server (void)
+{
+ g_autoptr (GcalSimpleServer) server = NULL;
+
+ server = gcal_simple_server_new ();
+ gcal_simple_server_start (server);
+
+ return g_steal_pointer (&server);
+}
+
+/*********************************************************************************************************************/
+
+static void
+discovered_file_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ g_autoptr (GPtrArray) sources = NULL;
+ g_autoptr (GError) error = NULL;
+ GMainLoop *mainloop = user_data;
+
+ sources = gcal_discover_sources_from_uri_finish (result, &error);
+ g_assert_no_error (error);
+ g_assert_cmpuint (sources->len, ==, 1);
+
+ g_main_loop_quit (mainloop);
+}
+
+static void
+discoverer_file (void)
+{
+ g_autoptr (GcalSimpleServer) server = NULL;
+ g_autoptr (GMainLoop) mainloop = NULL;
+ g_autoptr (SoupURI) uri = NULL;
+ g_autofree gchar *uri_str = NULL;
+
+ server = init_server ();
+ uri = gcal_simple_server_get_uri (server);
+ soup_uri_set_path (uri, "/public/calendar");
+
+ uri_str = soup_uri_to_string (uri, FALSE);
+
+ mainloop = g_main_loop_new (NULL, FALSE);
+
+ gcal_discover_sources_from_uri (uri_str,
+ NULL,
+ NULL,
+ NULL,
+ discovered_file_cb,
+ mainloop);
+
+ g_main_loop_run (mainloop);
+}
+
+/*********************************************************************************************************************/
+
+static void
+discovered_webdav_no_auth_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ g_autoptr (GPtrArray) sources = NULL;
+ g_autoptr (GError) error = NULL;
+ GMainLoop *mainloop = user_data;
+
+ sources = gcal_discover_sources_from_uri_finish (result, &error);
+ g_assert_error (error, GCAL_SOURCE_DISCOVERER_ERROR, GCAL_SOURCE_DISCOVERER_ERROR_UNAUTHORIZED);
+
+ g_main_loop_quit (mainloop);
+}
+
+static void
+discoverer_webdav_no_auth (void)
+{
+ g_autoptr (GcalSimpleServer) server = NULL;
+ g_autoptr (GMainLoop) mainloop = NULL;
+ g_autoptr (SoupURI) uri = NULL;
+ g_autofree gchar *uri_str = NULL;
+
+ server = init_server ();
+ uri = gcal_simple_server_get_uri (server);
+ soup_uri_set_path (uri, "/secret-area/calendar");
+
+ uri_str = soup_uri_to_string (uri, FALSE);
+
+ mainloop = g_main_loop_new (NULL, FALSE);
+
+ gcal_discover_sources_from_uri (uri_str,
+ NULL,
+ NULL,
+ NULL,
+ discovered_webdav_no_auth_cb,
+ mainloop);
+
+ g_main_loop_run (mainloop);
+}
+
+/*********************************************************************************************************************/
+
+#if 0
+
+// TODO: Implement raw CalDAV server in GcalSimpleServer
+
+static void
+discoverer_webdav_auth_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ g_autoptr (GPtrArray) sources = NULL;
+ g_autoptr (GError) error = NULL;
+ GMainLoop *mainloop = user_data;
+
+ sources = gcal_discover_sources_from_uri_finish (result, &error);
+ g_assert_no_error (error);
+
+ g_main_loop_quit (mainloop);
+}
+
+static void
+discoverer_webdav_auth (void)
+{
+ g_autoptr (GcalSimpleServer) server = NULL;
+ g_autoptr (GMainLoop) mainloop = NULL;
+ g_autoptr (SoupURI) uri = NULL;
+ g_autofree gchar *uri_str = NULL;
+
+ server = init_server ();
+ uri = gcal_simple_server_get_uri (server);
+ soup_uri_set_path (uri, "/secret-area/dav");
+
+ uri_str = soup_uri_to_string (uri, FALSE);
+
+ mainloop = g_main_loop_new (NULL, FALSE);
+
+ gcal_discover_sources_from_uri (uri_str,
+ "feaneron",
+ "idonotmaintainanything",
+ NULL,
+ discoverer_webdav_auth_cb,
+ mainloop);
+
+ g_main_loop_run (mainloop);
+}
+
+#endif
+
+/*********************************************************************************************************************/
+
+gint
+main (gint argc,
+ gchar *argv[])
+{
+ g_setenv ("TZ", "UTC", TRUE);
+
+ g_test_init (&argc, &argv, NULL);
+
+ g_test_add_func ("/discoverer/file", discoverer_file);
+ g_test_add_func ("/discoverer/webdav/no-auth", discoverer_webdav_no_auth);
+
+ return g_test_run ();
+}
+
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]