gchar *display_name;
gchar *email_address;
gchar *resource_path;
+ gchar *resource_query;
gboolean avoid_ifmatch;
gboolean calendar_auto_schedule;
gboolean ignore_invalid_cert;
- SoupURI *uri;
+ SoupURI *soup_uri;
};
enum {
PROP_EMAIL_ADDRESS,
PROP_IGNORE_INVALID_CERT,
PROP_RESOURCE_PATH,
+ PROP_RESOURCE_QUERY,
PROP_SOUP_URI
};
e_source_webdav,
E_TYPE_SOURCE_EXTENSION)
-static gboolean
-source_webdav_host_to_soup_uri (GBinding *binding,
- const GValue *source_value,
- GValue *target_value,
- gpointer user_data)
+static void
+source_webdav_notify_cb (GObject *object,
+ GParamSpec *pspec,
+ ESourceWebdav *extension)
{
- GObject *target;
- SoupURI *soup_uri;
- const gchar *host;
-
- host = g_value_get_string (source_value);
-
- target = g_binding_get_target (binding);
- g_return_val_if_fail (E_IS_SOURCE_WEBDAV (target), FALSE);
-
- soup_uri = e_source_webdav_dup_soup_uri (E_SOURCE_WEBDAV (target));
- soup_uri_set_host (soup_uri, host);
- g_value_take_boxed (target_value, soup_uri);
-
- return TRUE;
+ g_object_notify (G_OBJECT (extension), "soup-uri");
}
static gboolean
-source_webdav_soup_uri_to_host (GBinding *binding,
- const GValue *source_value,
- GValue *target_value,
- gpointer user_data)
+source_webdav_user_to_method (GBinding *binding,
+ const GValue *source_value,
+ GValue *target_value,
+ gpointer user_data)
{
- SoupURI *soup_uri;
+ const gchar *user;
- soup_uri = g_value_get_boxed (source_value);
- g_value_set_string (target_value, soup_uri->host);
+ user = g_value_get_string (source_value);
+ if (user == NULL || *user == '\0')
+ g_value_set_string (target_value, "none");
+ else
+ g_value_set_string (target_value, "plain/password");
return TRUE;
}
-static gboolean
-source_webdav_path_to_soup_uri (GBinding *binding,
- const GValue *source_value,
- GValue *target_value,
- gpointer user_data)
+static void
+source_webdav_update_properties_from_soup_uri (ESourceWebdav *webdav_extension)
{
- GObject *target;
+ ESource *source;
+ ESourceExtension *extension;
SoupURI *soup_uri;
- const gchar *path;
+ const gchar *extension_name;
- path = g_value_get_string (source_value);
+ /* Do not use e_source_webdav_dup_soup_uri() here. That
+ * builds the URI from properties we haven't yet updated. */
+ g_mutex_lock (webdav_extension->priv->property_lock);
+ soup_uri = soup_uri_copy (webdav_extension->priv->soup_uri);
+ g_mutex_unlock (webdav_extension->priv->property_lock);
- /* soup_uri_set_path() warns on NULL. */
- if (path == NULL)
- path = "";
+ extension = E_SOURCE_EXTENSION (webdav_extension);
+ source = e_source_extension_get_source (extension);
- target = g_binding_get_target (binding);
- g_return_val_if_fail (E_IS_SOURCE_WEBDAV (target), FALSE);
+ g_object_set (
+ extension,
+ "resource-path", soup_uri->path,
+ "resource-query", soup_uri->query,
+ NULL);
- soup_uri = e_source_webdav_dup_soup_uri (E_SOURCE_WEBDAV (target));
- soup_uri_set_path (soup_uri, path);
- g_value_take_boxed (target_value, soup_uri);
+ extension_name = E_SOURCE_EXTENSION_AUTHENTICATION;
+ extension = e_source_get_extension (source, extension_name);
- return TRUE;
-}
+ g_object_set (
+ extension,
+ "host", soup_uri->host,
+ "port", soup_uri->port,
+ "user", soup_uri->user,
+ NULL);
-static gboolean
-source_webdav_soup_uri_to_path (GBinding *binding,
- const GValue *source_value,
- GValue *target_value,
- gpointer user_data)
-{
- SoupURI *soup_uri;
+ extension_name = E_SOURCE_EXTENSION_SECURITY;
+ extension = e_source_get_extension (source, extension_name);
- soup_uri = g_value_get_boxed (source_value);
- g_value_set_string (target_value, soup_uri->path);
+ g_object_set (
+ extension,
+ "secure", (soup_uri->scheme == SOUP_URI_SCHEME_HTTPS),
+ NULL);
- return TRUE;
+ soup_uri_free (soup_uri);
}
-static gboolean
-source_webdav_port_to_soup_uri (GBinding *binding,
- const GValue *source_value,
- GValue *target_value,
- gpointer user_data)
+static void
+source_webdav_update_soup_uri_from_properties (ESourceWebdav *webdav_extension)
{
- GObject *target;
+ ESource *source;
+ ESourceExtension *extension;
SoupURI *soup_uri;
+ const gchar *extension_name;
+ gchar *user;
+ gchar *host;
+ gchar *path;
+ gchar *query;
guint port;
+ gboolean secure;
- port = g_value_get_uint (source_value);
-
- target = g_binding_get_target (binding);
- g_return_val_if_fail (E_IS_SOURCE_WEBDAV (target), FALSE);
-
- soup_uri = e_source_webdav_dup_soup_uri (E_SOURCE_WEBDAV (target));
- soup_uri_set_port (soup_uri, port);
- g_value_take_boxed (target_value, soup_uri);
+ extension = E_SOURCE_EXTENSION (webdav_extension);
+ source = e_source_extension_get_source (extension);
- return TRUE;
-}
+ g_object_get (
+ extension,
+ "resource-path", &path,
+ "resource-query", &query,
+ NULL);
-static gboolean
-source_webdav_soup_uri_to_port (GBinding *binding,
- const GValue *source_value,
- GValue *target_value,
- gpointer user_data)
-{
- SoupURI *soup_uri;
+ extension_name = E_SOURCE_EXTENSION_AUTHENTICATION;
+ extension = e_source_get_extension (source, extension_name);
- soup_uri = g_value_get_boxed (source_value);
- g_value_set_uint (target_value, soup_uri->port);
+ g_object_get (
+ extension,
+ "user", &user,
+ "host", &host,
+ "port", &port,
+ NULL);
- return TRUE;
-}
+ extension_name = E_SOURCE_EXTENSION_SECURITY;
+ extension = e_source_get_extension (source, extension_name);
-static gboolean
-source_webdav_secure_to_soup_uri (GBinding *binding,
- const GValue *source_value,
- GValue *target_value,
- gpointer user_data)
-{
- GObject *target;
- SoupURI *soup_uri;
- gboolean secure;
+ g_object_get (
+ extension,
+ "secure", &secure,
+ NULL);
- secure = g_value_get_boolean (source_value);
+ g_mutex_lock (webdav_extension->priv->property_lock);
- target = g_binding_get_target (binding);
- g_return_val_if_fail (E_IS_SOURCE_WEBDAV (target), FALSE);
+ soup_uri = webdav_extension->priv->soup_uri;
- soup_uri = e_source_webdav_dup_soup_uri (E_SOURCE_WEBDAV (target));
- if (secure)
+ /* Try not to disturb the scheme, in case it's "webcal" or some
+ * other non-standard value. But if we have to change it, do it. */
+ if (secure && soup_uri->scheme != SOUP_URI_SCHEME_HTTPS)
soup_uri_set_scheme (soup_uri, SOUP_URI_SCHEME_HTTPS);
- else
+ if (!secure && soup_uri->scheme == SOUP_URI_SCHEME_HTTPS)
soup_uri_set_scheme (soup_uri, SOUP_URI_SCHEME_HTTP);
- g_value_take_boxed (target_value, soup_uri);
-
- return TRUE;
-}
-
-static gboolean
-source_webdav_soup_uri_to_secure (GBinding *binding,
- const GValue *source_value,
- GValue *target_value,
- gpointer user_data)
-{
- SoupURI *soup_uri;
- gboolean secure;
- soup_uri = g_value_get_boxed (source_value);
- secure = (soup_uri->scheme == SOUP_URI_SCHEME_HTTPS);
- g_value_set_boolean (target_value, secure);
-
- return TRUE;
-}
-
-static gboolean
-source_webdav_user_to_soup_uri (GBinding *binding,
- const GValue *source_value,
- GValue *target_value,
- gpointer user_data)
-{
- GObject *target;
- SoupURI *soup_uri;
- const gchar *user;
-
- user = g_value_get_string (source_value);
-
- target = g_binding_get_target (binding);
- g_return_val_if_fail (E_IS_SOURCE_WEBDAV (target), FALSE);
-
- soup_uri = e_source_webdav_dup_soup_uri (E_SOURCE_WEBDAV (target));
soup_uri_set_user (soup_uri, user);
- g_value_take_boxed (target_value, soup_uri);
-
- return TRUE;
-}
+ soup_uri_set_host (soup_uri, host);
+ soup_uri_set_port (soup_uri, port);
-static gboolean
-source_webdav_soup_uri_to_user (GBinding *binding,
- const GValue *source_value,
- GValue *target_value,
- gpointer user_data)
-{
- SoupURI *soup_uri;
+ /* SoupURI doesn't like NULL paths. */
+ soup_uri_set_path (soup_uri, (path != NULL) ? path : "");
- soup_uri = g_value_get_boxed (source_value);
- g_value_set_string (target_value, soup_uri->user);
+ soup_uri_set_query (soup_uri, query);
- return TRUE;
-}
+ g_mutex_unlock (webdav_extension->priv->property_lock);
-static gboolean
-source_webdav_user_to_method (GBinding *binding,
- const GValue *source_value,
- GValue *target_value,
- gpointer user_data)
-{
- const gchar *user;
-
- user = g_value_get_string (source_value);
- if (user == NULL || *user == '\0')
- g_value_set_string (target_value, "none");
- else
- g_value_set_string (target_value, "plain/password");
-
- return TRUE;
+ g_free (user);
+ g_free (host);
+ g_free (path);
+ g_free (query);
}
static void
g_value_get_string (value));
return;
+ case PROP_RESOURCE_QUERY:
+ e_source_webdav_set_resource_query (
+ E_SOURCE_WEBDAV (object),
+ g_value_get_string (value));
+ return;
+
case PROP_SOUP_URI:
e_source_webdav_set_soup_uri (
E_SOURCE_WEBDAV (object),
E_SOURCE_WEBDAV (object)));
return;
+ case PROP_RESOURCE_QUERY:
+ g_value_take_string (
+ value,
+ e_source_webdav_dup_resource_query (
+ E_SOURCE_WEBDAV (object)));
+ return;
+
case PROP_SOUP_URI:
g_value_take_boxed (
value,
g_free (priv->display_name);
g_free (priv->email_address);
g_free (priv->resource_path);
+ g_free (priv->resource_query);
- soup_uri_free (priv->uri);
+ soup_uri_free (priv->soup_uri);
/* Chain up to parent's finalize() method. */
G_OBJECT_CLASS (e_source_webdav_parent_class)->finalize (object);
source_webdav_constructed (GObject *object)
{
ESource *source;
- ESourceExtension *this_extension;
- ESourceExtension *other_extension;
+ ESourceExtension *extension;
const gchar *extension_name;
/* Chain up to parent's constructed() method. */
G_OBJECT_CLASS (e_source_webdav_parent_class)->constructed (object);
- this_extension = E_SOURCE_EXTENSION (object);
- source = e_source_extension_get_source (this_extension);
+ /* XXX I *think* we don't need to worry about disconnecting the
+ * signals. ESourceExtensions are only added, never removed,
+ * and they all finalize with their ESource. At least that's
+ * how it's supposed to work if everyone follows the rules. */
- g_object_bind_property_full (
- this_extension, "resource-path",
- this_extension, "soup-uri",
- G_BINDING_BIDIRECTIONAL |
- G_BINDING_SYNC_CREATE,
- source_webdav_path_to_soup_uri,
- source_webdav_soup_uri_to_path,
- NULL, (GDestroyNotify) NULL);
+ extension = E_SOURCE_EXTENSION (object);
+ source = e_source_extension_get_source (extension);
+
+ g_signal_connect (
+ extension, "notify::resource-path",
+ G_CALLBACK (source_webdav_notify_cb), object);
- /* Bind to properties of other extensions for convenience. */
+ g_signal_connect (
+ extension, "notify::resource-query",
+ G_CALLBACK (source_webdav_notify_cb), object);
extension_name = E_SOURCE_EXTENSION_AUTHENTICATION;
- other_extension = e_source_get_extension (source, extension_name);
+ extension = e_source_get_extension (source, extension_name);
- g_object_bind_property_full (
- other_extension, "host",
- this_extension, "soup-uri",
- G_BINDING_BIDIRECTIONAL |
- G_BINDING_SYNC_CREATE,
- source_webdav_host_to_soup_uri,
- source_webdav_soup_uri_to_host,
- NULL, (GDestroyNotify) NULL);
+ g_signal_connect (
+ extension, "notify::host",
+ G_CALLBACK (source_webdav_notify_cb), object);
- g_object_bind_property_full (
- other_extension, "port",
- this_extension, "soup-uri",
- G_BINDING_BIDIRECTIONAL |
- G_BINDING_SYNC_CREATE,
- source_webdav_port_to_soup_uri,
- source_webdav_soup_uri_to_port,
- NULL, (GDestroyNotify) NULL);
+ g_signal_connect (
+ extension, "notify::port",
+ G_CALLBACK (source_webdav_notify_cb), object);
- g_object_bind_property_full (
- other_extension, "user",
- this_extension, "soup-uri",
- G_BINDING_BIDIRECTIONAL |
- G_BINDING_SYNC_CREATE,
- source_webdav_user_to_soup_uri,
- source_webdav_soup_uri_to_user,
- NULL, (GDestroyNotify) NULL);
+ g_signal_connect (
+ extension, "notify::user",
+ G_CALLBACK (source_webdav_notify_cb), object);
+ /* This updates the authentication method
+ * based on whether a user name was given. */
g_object_bind_property_full (
- other_extension, "user",
- other_extension, "method",
+ extension, "user",
+ extension, "method",
G_BINDING_SYNC_CREATE,
source_webdav_user_to_method,
NULL,
NULL, (GDestroyNotify) NULL);
extension_name = E_SOURCE_EXTENSION_SECURITY;
- other_extension = e_source_get_extension (source, extension_name);
+ extension = e_source_get_extension (source, extension_name);
- g_object_bind_property_full (
- other_extension, "secure",
- this_extension, "soup-uri",
- G_BINDING_BIDIRECTIONAL |
- G_BINDING_SYNC_CREATE,
- source_webdav_secure_to_soup_uri,
- source_webdav_soup_uri_to_secure,
- NULL, (GDestroyNotify) NULL);
+ g_signal_connect (
+ extension, "notify::secure",
+ G_CALLBACK (source_webdav_notify_cb), object);
}
static void
g_object_class_install_property (
object_class,
+ PROP_RESOURCE_QUERY,
+ g_param_spec_string (
+ "resource-query",
+ "Resource Query",
+ "Query to access a WebDAV resource",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ E_SOURCE_PARAM_SETTING));
+
+ g_object_class_install_property (
+ object_class,
PROP_SOUP_URI,
g_param_spec_boxed (
"soup-uri",
extension->priv->property_lock = g_mutex_new ();
/* Initialize this enough for SOUP_URI_IS_VALID() to pass. */
- extension->priv->uri = soup_uri_new (NULL);
- extension->priv->uri->scheme = SOUP_URI_SCHEME_HTTP;
- extension->priv->uri->path = g_strdup ("");
+ extension->priv->soup_uri = soup_uri_new (NULL);
+ extension->priv->soup_uri->scheme = SOUP_URI_SCHEME_HTTP;
+ extension->priv->soup_uri->path = g_strdup ("");
}
/**
}
/**
+ * e_source_webdav_get_resource_query:
+ * @extension: an #ESourceWebdav
+ *
+ * Returns the URI query required to access a resource on a WebDAV server.
+ *
+ * This is typically used when the #ESourceWebdav:resource-path points not
+ * to the resource itself but to a web program that generates the resource
+ * content on-the-fly. The #ESourceWebdav:resource-query holds the input
+ * values for the program.
+ *
+ * Returns: the query to access a WebDAV resource
+ *
+ * Since: 3.6
+ **/
+const gchar *
+e_source_webdav_get_resource_query (ESourceWebdav *extension)
+{
+ g_return_val_if_fail (E_IS_SOURCE_WEBDAV (extension), NULL);
+
+ return extension->priv->resource_query;
+}
+
+/**
+ * e_source_webdav_dup_resource_query:
+ * @extension: an #ESourceWebdav
+ *
+ * Thread-safe variation of e_source_webdav_get_resource_query().
+ * Use this function when accessing @extension from multiple threads.
+ *
+ * The returned string should be freed with g_free() when no longer needed.
+ *
+ * Returns: the newly-allocated copy of #ESourceWebdav:resource-query
+ *
+ * Since: 3.6
+ **/
+gchar *
+e_source_webdav_dup_resource_query (ESourceWebdav *extension)
+{
+ const gchar *protected;
+ gchar *duplicate;
+
+ g_return_val_if_fail (E_IS_SOURCE_WEBDAV (extension), NULL);
+
+ g_mutex_lock (extension->priv->property_lock);
+
+ protected = e_source_webdav_get_resource_query (extension);
+ duplicate = g_strdup (protected);
+
+ g_mutex_unlock (extension->priv->property_lock);
+
+ return duplicate;
+}
+
+/**
+ * e_source_webdav_set_resource_query:
+ * @extension: an #ESourceWebdav
+ * @resource_query: (allow-none): the query to access a WebDAV resource,
+ * or %NULL
+ *
+ * Sets the URI query required to access a resource on a WebDAV server.
+ *
+ * This is typically used when the #ESourceWebdav:resource-path points not
+ * to the resource itself but to a web program that generates the resource
+ * content on-the-fly. The #ESourceWebdav:resource-query holds the input
+ * values for the program.
+ *
+ * The internal copy of @resource_query is automatically stripped of leading
+ * and trailing whitespace. If the resulting string is empty, %NULL is set
+ * instead.
+ *
+ * Since: 3.6
+ **/
+void
+e_source_webdav_set_resource_query (ESourceWebdav *extension,
+ const gchar *resource_query)
+{
+ g_return_if_fail (E_IS_SOURCE_WEBDAV (extension));
+
+ g_mutex_lock (extension->priv->property_lock);
+
+ if (g_strcmp0 (extension->priv->resource_query, resource_query) == 0) {
+ g_mutex_unlock (extension->priv->property_lock);
+ return;
+ }
+
+ g_free (extension->priv->resource_query);
+ extension->priv->resource_query = e_util_strdup_strip (resource_query);
+
+ g_mutex_unlock (extension->priv->property_lock);
+
+ g_object_notify (G_OBJECT (extension), "resource-query");
+}
+
+/**
* e_source_webdav_dup_soup_uri:
* @extension: an #ESourceWebdav
*
g_return_val_if_fail (E_IS_SOURCE_WEBDAV (extension), NULL);
+ /* Keep this outside of the property lock. */
+ source_webdav_update_soup_uri_from_properties (extension);
+
g_mutex_lock (extension->priv->property_lock);
- duplicate = soup_uri_copy (extension->priv->uri);
+ duplicate = soup_uri_copy (extension->priv->soup_uri);
g_mutex_unlock (extension->priv->property_lock);
/**
* e_source_webdav_set_soup_uri:
* @extension: an #ESourceWebdav
- * @uri: a #SoupURI
+ * @soup_uri: a #SoupURI
*
* This is a convenience function which propagates the components of
* @uri to the #ESourceAuthentication extension, the #ESourceSecurity
- * extension, and @extension itself. (The "query" and "fragment"
- * components of @uri are ignored.)
+ * extension, and @extension itself. (The "fragment" component of
+ * @uri is ignored.)
*
* Since: 3.6
**/
void
e_source_webdav_set_soup_uri (ESourceWebdav *extension,
- SoupURI *uri)
+ SoupURI *soup_uri)
{
g_return_if_fail (E_IS_SOURCE_WEBDAV (extension));
- g_return_if_fail (SOUP_URI_IS_VALID (uri));
+ g_return_if_fail (SOUP_URI_IS_VALID (soup_uri));
g_mutex_lock (extension->priv->property_lock);
- if (extension->priv->uri && soup_uri_equal (extension->priv->uri, uri)) {
- g_mutex_unlock (extension->priv->property_lock);
- return;
- }
+ /* Do not test for URI equality because our
+ * internal SoupURI might not be up-to-date. */
- soup_uri_free (extension->priv->uri);
- extension->priv->uri = soup_uri_copy (uri);
+ soup_uri_free (extension->priv->soup_uri);
+ extension->priv->soup_uri = soup_uri_copy (soup_uri);
g_mutex_unlock (extension->priv->property_lock);
+ g_object_freeze_notify (G_OBJECT (extension));
+ source_webdav_update_properties_from_soup_uri (extension);
g_object_notify (G_OBJECT (extension), "soup-uri");
+ g_object_thaw_notify (G_OBJECT (extension));
}