Blame src/goabackend/goaowncloudprovider.c

Packit 79f644
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
Packit 79f644
/*
Packit 79f644
 * Copyright © 2012 – 2017 Red Hat, Inc.
Packit 79f644
 *
Packit 79f644
 * This library is free software; you can redistribute it and/or
Packit 79f644
 * modify it under the terms of the GNU Lesser General Public
Packit 79f644
 * License as published by the Free Software Foundation; either
Packit 79f644
 * version 2 of the License, or (at your option) any later version.
Packit 79f644
 *
Packit 79f644
 * This library is distributed in the hope that it will be useful,
Packit 79f644
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 79f644
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 79f644
 * Lesser General Public License for more details.
Packit 79f644
 *
Packit 79f644
 * You should have received a copy of the GNU Lesser General
Packit 79f644
 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
Packit 79f644
 */
Packit 79f644
Packit 79f644
#include "config.h"
Packit 79f644
Packit 79f644
#include <string.h>
Packit 79f644
Packit 79f644
#include <glib/gi18n-lib.h>
Packit 79f644
Packit 79f644
#include <libsoup/soup.h>
Packit 79f644
Packit 79f644
#include "goahttpclient.h"
Packit 79f644
#include "goaprovider.h"
Packit 79f644
#include "goaowncloudprovider.h"
Packit 79f644
#include "goaobjectskeletonutils.h"
Packit 79f644
#include "goautils.h"
Packit 79f644
Packit 79f644
struct _GoaOwncloudProvider
Packit 79f644
{
Packit 79f644
  GoaProvider parent_instance;
Packit 79f644
};
Packit 79f644
Packit 79f644
G_DEFINE_TYPE_WITH_CODE (GoaOwncloudProvider, goa_owncloud_provider, GOA_TYPE_PROVIDER,
Packit 79f644
                         goa_provider_ensure_extension_points_registered ();
Packit 79f644
                         g_io_extension_point_implement (GOA_PROVIDER_EXTENSION_POINT_NAME,
Packit 79f644
							 g_define_type_id,
Packit 79f644
							 GOA_OWNCLOUD_NAME,
Packit 79f644
							 0));
Packit 79f644
Packit 79f644
/* ---------------------------------------------------------------------------------------------------- */
Packit 79f644
Packit 79f644
static const gchar *CALDAV_ENDPOINT = "remote.php/caldav/";
Packit 79f644
static const gchar *CARDDAV_ENDPOINT = "remote.php/carddav/";
Packit 79f644
static const gchar *WEBDAV_ENDPOINT = "remote.php/webdav/";
Packit 79f644
Packit 79f644
static const gchar *
Packit 79f644
get_provider_type (GoaProvider *provider)
Packit 79f644
{
Packit 79f644
  return GOA_OWNCLOUD_NAME;
Packit 79f644
}
Packit 79f644
Packit 79f644
static gchar *
Packit 79f644
get_provider_name (GoaProvider *provider, GoaObject *object)
Packit 79f644
{
Packit 79f644
  return g_strdup(_("Nextcloud"));
Packit 79f644
}
Packit 79f644
Packit 79f644
static GoaProviderGroup
Packit 79f644
get_provider_group (GoaProvider *provider)
Packit 79f644
{
Packit 79f644
  return GOA_PROVIDER_GROUP_BRANDED;
Packit 79f644
}
Packit 79f644
Packit 79f644
static GoaProviderFeatures
Packit 79f644
get_provider_features (GoaProvider *provider)
Packit 79f644
{
Packit 79f644
  return GOA_PROVIDER_FEATURE_BRANDED |
Packit 79f644
         GOA_PROVIDER_FEATURE_CALENDAR |
Packit 79f644
         GOA_PROVIDER_FEATURE_CONTACTS |
Packit 79f644
         GOA_PROVIDER_FEATURE_DOCUMENTS |
Packit 79f644
         GOA_PROVIDER_FEATURE_FILES;
Packit 79f644
}
Packit 79f644
Packit 79f644
/* ---------------------------------------------------------------------------------------------------- */
Packit 79f644
Packit 79f644
static char *
Packit 79f644
uri_to_string_with_path (SoupURI *soup_uri, const gchar *path)
Packit 79f644
{
Packit 79f644
  gchar *uri_string;
Packit 79f644
  gchar *uri_tmp;
Packit 79f644
Packit 79f644
  if (soup_uri == NULL)
Packit 79f644
    return NULL;
Packit 79f644
Packit 79f644
  uri_tmp = soup_uri_to_string (soup_uri, FALSE);
Packit 79f644
  uri_string = g_strconcat (uri_tmp, path, NULL);
Packit 79f644
  g_free (uri_tmp);
Packit 79f644
Packit 79f644
  return uri_string;
Packit 79f644
}
Packit 79f644
Packit 79f644
static char *get_webdav_uri (SoupURI *soup_uri)
Packit 79f644
{
Packit 79f644
  SoupURI *uri_tmp;
Packit 79f644
  gchar *uri_webdav;
Packit 79f644
  const gchar *scheme;
Packit 79f644
  guint port;
Packit 79f644
Packit 79f644
  if (soup_uri == NULL)
Packit 79f644
    return NULL;
Packit 79f644
Packit 79f644
  scheme = soup_uri_get_scheme (soup_uri);
Packit 79f644
  port = soup_uri_get_port (soup_uri);
Packit 79f644
  uri_tmp = soup_uri_copy (soup_uri);
Packit 79f644
Packit 79f644
  if (g_strcmp0 (scheme, SOUP_URI_SCHEME_HTTPS) == 0)
Packit 79f644
    soup_uri_set_scheme (uri_tmp, "davs");
Packit 79f644
  else
Packit 79f644
    soup_uri_set_scheme (uri_tmp, "dav");
Packit 79f644
Packit 79f644
  if (!soup_uri_uses_default_port (soup_uri))
Packit 79f644
    soup_uri_set_port (uri_tmp, port);
Packit 79f644
Packit 79f644
  uri_webdav = uri_to_string_with_path (uri_tmp, WEBDAV_ENDPOINT);
Packit 79f644
  soup_uri_free (uri_tmp);
Packit 79f644
Packit 79f644
  return uri_webdav;
Packit 79f644
}
Packit 79f644
Packit 79f644
static gboolean on_handle_get_password (GoaPasswordBased      *interface,
Packit 79f644
                                        GDBusMethodInvocation *invocation,
Packit 79f644
                                        const gchar           *id,
Packit 79f644
                                        gpointer               user_data);
Packit 79f644
Packit 79f644
static gboolean
Packit 79f644
build_object (GoaProvider         *provider,
Packit 79f644
              GoaObjectSkeleton   *object,
Packit 79f644
              GKeyFile            *key_file,
Packit 79f644
              const gchar         *group,
Packit 79f644
              GDBusConnection     *connection,
Packit 79f644
              gboolean             just_added,
Packit 79f644
              GError             **error)
Packit 79f644
{
Packit 79f644
  GoaAccount *account = NULL;
Packit 79f644
  gchar *uri_caldav;
Packit 79f644
  gchar *uri_carddav;
Packit 79f644
  gchar *uri_webdav;
Packit 79f644
  GoaPasswordBased *password_based = NULL;
Packit 79f644
  SoupURI *uri = NULL;
Packit 79f644
  gboolean accept_ssl_errors;
Packit 79f644
  gboolean calendar_enabled;
Packit 79f644
  gboolean contacts_enabled;
Packit 79f644
  gboolean documents_enabled;
Packit 79f644
  gboolean files_enabled;
Packit 79f644
  gboolean ret = FALSE;
Packit 79f644
  const gchar *identity;
Packit 79f644
  gchar *uri_string = NULL;
Packit 79f644
Packit 79f644
  /* Chain up */
Packit 79f644
  if (!GOA_PROVIDER_CLASS (goa_owncloud_provider_parent_class)->build_object (provider,
Packit 79f644
                                                                              object,
Packit 79f644
                                                                              key_file,
Packit 79f644
                                                                              group,
Packit 79f644
                                                                              connection,
Packit 79f644
                                                                              just_added,
Packit 79f644
                                                                              error))
Packit 79f644
    goto out;
Packit 79f644
Packit 79f644
  password_based = goa_object_get_password_based (GOA_OBJECT (object));
Packit 79f644
  if (password_based == NULL)
Packit 79f644
    {
Packit 79f644
      password_based = goa_password_based_skeleton_new ();
Packit 79f644
      /* Ensure D-Bus method invocations run in their own thread */
Packit 79f644
      g_dbus_interface_skeleton_set_flags (G_DBUS_INTERFACE_SKELETON (password_based),
Packit 79f644
                                           G_DBUS_INTERFACE_SKELETON_FLAGS_HANDLE_METHOD_INVOCATIONS_IN_THREAD);
Packit 79f644
      goa_object_skeleton_set_password_based (object, password_based);
Packit 79f644
      g_signal_connect (password_based,
Packit 79f644
                        "handle-get-password",
Packit 79f644
                        G_CALLBACK (on_handle_get_password),
Packit 79f644
                        NULL);
Packit 79f644
    }
Packit 79f644
Packit 79f644
  account = goa_object_get_account (GOA_OBJECT (object));
Packit 79f644
  identity = goa_account_get_identity (account);
Packit 79f644
  uri_string = g_key_file_get_string (key_file, group, "Uri", NULL);
Packit 79f644
  uri = soup_uri_new (uri_string);
Packit 79f644
  if (uri != NULL)
Packit 79f644
    soup_uri_set_user (uri, identity);
Packit 79f644
Packit 79f644
  accept_ssl_errors = g_key_file_get_boolean (key_file, group, "AcceptSslErrors", NULL);
Packit 79f644
Packit 79f644
  /* Calendar */
Packit 79f644
  calendar_enabled = g_key_file_get_boolean (key_file, group, "CalendarEnabled", NULL);
Packit 79f644
  uri_caldav = uri_to_string_with_path (uri, CALDAV_ENDPOINT);
Packit 79f644
  goa_object_skeleton_attach_calendar (object, uri_caldav, calendar_enabled, accept_ssl_errors);
Packit 79f644
  g_free (uri_caldav);
Packit 79f644
Packit 79f644
  /* Contacts */
Packit 79f644
  contacts_enabled = g_key_file_get_boolean (key_file, group, "ContactsEnabled", NULL);
Packit 79f644
  uri_carddav = uri_to_string_with_path (uri, CARDDAV_ENDPOINT);
Packit 79f644
  goa_object_skeleton_attach_contacts (object, uri_carddav, contacts_enabled, accept_ssl_errors);
Packit 79f644
  g_free (uri_carddav);
Packit 79f644
Packit 79f644
  /* Documents */
Packit 79f644
  documents_enabled = g_key_file_get_boolean (key_file, group, "DocumentsEnabled", NULL);
Packit 79f644
  goa_object_skeleton_attach_documents (object, documents_enabled);
Packit 79f644
Packit 79f644
  /* Files */
Packit 79f644
  files_enabled = g_key_file_get_boolean (key_file, group, "FilesEnabled", NULL);
Packit 79f644
  uri_webdav = get_webdav_uri (uri);
Packit 79f644
  goa_object_skeleton_attach_files (object, uri_webdav, files_enabled, accept_ssl_errors);
Packit 79f644
  g_free (uri_webdav);
Packit 79f644
Packit 79f644
  if (just_added)
Packit 79f644
    {
Packit 79f644
      goa_account_set_calendar_disabled (account, !calendar_enabled);
Packit 79f644
      goa_account_set_contacts_disabled (account, !contacts_enabled);
Packit 79f644
      goa_account_set_documents_disabled (account, !documents_enabled);
Packit 79f644
      goa_account_set_files_disabled (account, !files_enabled);
Packit 79f644
Packit 79f644
      g_signal_connect (account,
Packit 79f644
                        "notify::calendar-disabled",
Packit 79f644
                        G_CALLBACK (goa_util_account_notify_property_cb),
Packit 79f644
                        (gpointer) "CalendarEnabled");
Packit 79f644
      g_signal_connect (account,
Packit 79f644
                        "notify::contacts-disabled",
Packit 79f644
                        G_CALLBACK (goa_util_account_notify_property_cb),
Packit 79f644
                        (gpointer) "ContactsEnabled");
Packit 79f644
      g_signal_connect (account,
Packit 79f644
                        "notify::documents-disabled",
Packit 79f644
                        G_CALLBACK (goa_util_account_notify_property_cb),
Packit 79f644
                        (gpointer) "DocumentsEnabled");
Packit 79f644
      g_signal_connect (account,
Packit 79f644
                        "notify::files-disabled",
Packit 79f644
                        G_CALLBACK (goa_util_account_notify_property_cb),
Packit 79f644
                        (gpointer) "FilesEnabled");
Packit 79f644
    }
Packit 79f644
Packit 79f644
  ret = TRUE;
Packit 79f644
Packit 79f644
 out:
Packit 79f644
  g_clear_object (&password_based);
Packit 79f644
  g_clear_pointer (&uri, (GDestroyNotify *) soup_uri_free);
Packit 79f644
  g_free (uri_string);
Packit 79f644
  return ret;
Packit 79f644
}
Packit 79f644
Packit 79f644
/* ---------------------------------------------------------------------------------------------------- */
Packit 79f644
Packit 79f644
static gboolean
Packit 79f644
ensure_credentials_sync (GoaProvider         *provider,
Packit 79f644
                         GoaObject           *object,
Packit 79f644
                         gint                *out_expires_in,
Packit 79f644
                         GCancellable        *cancellable,
Packit 79f644
                         GError             **error)
Packit 79f644
{
Packit 79f644
  GoaHttpClient *http_client = NULL;
Packit 79f644
  gboolean accept_ssl_errors;
Packit 79f644
  gboolean ret = FALSE;
Packit 79f644
  gchar *username = NULL;
Packit 79f644
  gchar *password = NULL;
Packit 79f644
  gchar *uri = NULL;
Packit 79f644
  gchar *uri_webdav = NULL;
Packit 79f644
Packit 79f644
  if (!goa_utils_get_credentials (provider, object, "password", &username, &password, cancellable, error))
Packit 79f644
    {
Packit 79f644
      if (error != NULL)
Packit 79f644
        {
Packit 79f644
          (*error)->domain = GOA_ERROR;
Packit 79f644
          (*error)->code = GOA_ERROR_NOT_AUTHORIZED;
Packit 79f644
        }
Packit 79f644
      goto out;
Packit 79f644
    }
Packit 79f644
Packit 79f644
  accept_ssl_errors = goa_util_lookup_keyfile_boolean (object, "AcceptSslErrors");
Packit 79f644
  uri = goa_util_lookup_keyfile_string (object, "Uri");
Packit 79f644
  uri_webdav = g_strconcat (uri, WEBDAV_ENDPOINT, NULL);
Packit 79f644
Packit 79f644
  http_client = goa_http_client_new ();
Packit 79f644
  ret = goa_http_client_check_sync (http_client,
Packit 79f644
                                    uri_webdav,
Packit 79f644
                                    username,
Packit 79f644
                                    password,
Packit 79f644
                                    accept_ssl_errors,
Packit 79f644
                                    cancellable,
Packit 79f644
                                    error);
Packit 79f644
  if (!ret)
Packit 79f644
    {
Packit 79f644
      if (error != NULL)
Packit 79f644
        {
Packit 79f644
          g_prefix_error (error,
Packit 79f644
                          /* Translators: the first %s is the username
Packit 79f644
                           * (eg., debarshi.ray@gmail.com or rishi), and the
Packit 79f644
                           * (%s, %d) is the error domain and code.
Packit 79f644
                           */
Packit 79f644
                          _("Invalid password with username “%s” (%s, %d): "),
Packit 79f644
                          username,
Packit 79f644
                          g_quark_to_string ((*error)->domain),
Packit 79f644
                          (*error)->code);
Packit 79f644
          (*error)->domain = GOA_ERROR;
Packit 79f644
          (*error)->code = GOA_ERROR_NOT_AUTHORIZED;
Packit 79f644
        }
Packit 79f644
      goto out;
Packit 79f644
    }
Packit 79f644
Packit 79f644
  if (out_expires_in != NULL)
Packit 79f644
    *out_expires_in = 0;
Packit 79f644
Packit 79f644
 out:
Packit 79f644
  g_clear_object (&http_client);
Packit 79f644
  g_free (username);
Packit 79f644
  g_free (password);
Packit 79f644
  g_free (uri);
Packit 79f644
  g_free (uri_webdav);
Packit 79f644
  return ret;
Packit 79f644
}
Packit 79f644
Packit 79f644
/* ---------------------------------------------------------------------------------------------------- */
Packit 79f644
Packit 79f644
static void
Packit 79f644
add_entry (GtkWidget     *grid,
Packit 79f644
           gint           row,
Packit 79f644
           const gchar   *text,
Packit 79f644
           GtkWidget    **out_entry)
Packit 79f644
{
Packit 79f644
  GtkStyleContext *context;
Packit 79f644
  GtkWidget *label;
Packit 79f644
  GtkWidget *entry;
Packit 79f644
Packit 79f644
  label = gtk_label_new_with_mnemonic (text);
Packit 79f644
  context = gtk_widget_get_style_context (label);
Packit 79f644
  gtk_style_context_add_class (context, GTK_STYLE_CLASS_DIM_LABEL);
Packit 79f644
  gtk_widget_set_halign (label, GTK_ALIGN_END);
Packit 79f644
  gtk_widget_set_hexpand (label, TRUE);
Packit 79f644
  gtk_grid_attach (GTK_GRID (grid), label, 0, row, 1, 1);
Packit 79f644
Packit 79f644
  entry = gtk_entry_new ();
Packit 79f644
  gtk_widget_set_hexpand (entry, TRUE);
Packit 79f644
  gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE);
Packit 79f644
  gtk_grid_attach (GTK_GRID (grid), entry, 1, row, 3, 1);
Packit 79f644
Packit 79f644
  gtk_label_set_mnemonic_widget (GTK_LABEL (label), entry);
Packit 79f644
  if (out_entry != NULL)
Packit 79f644
    *out_entry = entry;
Packit 79f644
}
Packit 79f644
Packit 79f644
/* ---------------------------------------------------------------------------------------------------- */
Packit 79f644
Packit 79f644
typedef struct
Packit 79f644
{
Packit 79f644
  GCancellable *cancellable;
Packit 79f644
Packit 79f644
  GtkDialog *dialog;
Packit 79f644
  GMainLoop *loop;
Packit 79f644
Packit 79f644
  GtkWidget *cluebar;
Packit 79f644
  GtkWidget *cluebar_label;
Packit 79f644
  GtkWidget *connect_button;
Packit 79f644
  GtkWidget *progress_grid;
Packit 79f644
Packit 79f644
  GtkWidget *uri;
Packit 79f644
  GtkWidget *username;
Packit 79f644
  GtkWidget *password;
Packit 79f644
Packit 79f644
  gchar *account_object_path;
Packit 79f644
Packit 79f644
  GError *error;
Packit 79f644
} AddAccountData;
Packit 79f644
Packit 79f644
/* ---------------------------------------------------------------------------------------------------- */
Packit 79f644
Packit 79f644
static gchar *
Packit 79f644
normalize_uri (const gchar *address, gchar **server)
Packit 79f644
{
Packit 79f644
  SoupURI *uri = NULL;
Packit 79f644
  const gchar *path;
Packit 79f644
  gchar *ret = NULL;
Packit 79f644
  gchar *scheme = NULL;
Packit 79f644
  gchar *uri_string = NULL;
Packit 79f644
  guint std_port = 0;
Packit 79f644
Packit 79f644
  scheme = g_uri_parse_scheme (address);
Packit 79f644
Packit 79f644
  if (g_strcmp0 (scheme, "http") == 0
Packit 79f644
      || g_strcmp0 (scheme, "dav") == 0)   /* dav(s) is used by DNS-SD
Packit 79f644
                                              and gvfs */
Packit 79f644
    {
Packit 79f644
      uri_string = g_strdup (address);
Packit 79f644
      std_port = 80;
Packit 79f644
    }
Packit 79f644
  else if (g_strcmp0 (scheme, "https") == 0
Packit 79f644
           || g_strcmp0 (scheme, "davs") == 0)
Packit 79f644
    {
Packit 79f644
      uri_string = g_strdup (address);
Packit 79f644
      std_port = 443;
Packit 79f644
    }
Packit 79f644
  else if (scheme == NULL)
Packit 79f644
    {
Packit 79f644
      uri_string = g_strconcat ("https://", address, NULL);
Packit 79f644
      std_port = 443;
Packit 79f644
    }
Packit 79f644
  else
Packit 79f644
    goto out;
Packit 79f644
Packit 79f644
  uri = soup_uri_new (uri_string);
Packit 79f644
  if (uri == NULL)
Packit 79f644
    goto out;
Packit 79f644
Packit 79f644
  if (g_strcmp0 (scheme, "dav") == 0)
Packit 79f644
    soup_uri_set_scheme (uri, SOUP_URI_SCHEME_HTTP);
Packit 79f644
  else if (g_strcmp0 (scheme, "davs") == 0)
Packit 79f644
    soup_uri_set_scheme (uri, SOUP_URI_SCHEME_HTTPS);
Packit 79f644
Packit 79f644
  path = soup_uri_get_path (uri);
Packit 79f644
  if (!g_str_has_suffix (path, "/"))
Packit 79f644
    {
Packit 79f644
      gchar *new_path;
Packit 79f644
Packit 79f644
      new_path = g_strconcat (path, "/", NULL);
Packit 79f644
      soup_uri_set_path (uri, new_path);
Packit 79f644
      path = soup_uri_get_path (uri);
Packit 79f644
      g_free (new_path);
Packit 79f644
    }
Packit 79f644
Packit 79f644
  if (server != NULL)
Packit 79f644
    {
Packit 79f644
      gchar *port_string;
Packit 79f644
      gchar *pretty_path;
Packit 79f644
      guint port;
Packit 79f644
Packit 79f644
      port = soup_uri_get_port (uri);
Packit 79f644
      port_string = g_strdup_printf (":%u", port);
Packit 79f644
Packit 79f644
      pretty_path = g_strdup (path);
Packit 79f644
      pretty_path[strlen(pretty_path) - 1] = '\0';
Packit 79f644
Packit 79f644
      *server = g_strconcat (soup_uri_get_host (uri), (port == std_port) ? "" : port_string, pretty_path, NULL);
Packit 79f644
Packit 79f644
      g_free (port_string);
Packit 79f644
      g_free (pretty_path);
Packit 79f644
    }
Packit 79f644
Packit 79f644
  ret = soup_uri_to_string (uri, FALSE);
Packit 79f644
Packit 79f644
 out:
Packit 79f644
  g_clear_pointer (&uri, (GDestroyNotify *) soup_uri_free);
Packit 79f644
  g_free (scheme);
Packit 79f644
  g_free (uri_string);
Packit 79f644
  return ret;
Packit 79f644
}
Packit 79f644
Packit 79f644
static void
Packit 79f644
on_uri_username_or_password_changed (GtkEditable *editable, gpointer user_data)
Packit 79f644
{
Packit 79f644
  AddAccountData *data = user_data;
Packit 79f644
  gboolean can_add = FALSE;
Packit 79f644
  const gchar *address;
Packit 79f644
  gchar *uri = NULL;
Packit 79f644
Packit 79f644
  address = gtk_entry_get_text (GTK_ENTRY (data->uri));
Packit 79f644
  uri = normalize_uri (address, NULL);
Packit 79f644
  if (uri == NULL)
Packit 79f644
    goto out;
Packit 79f644
Packit 79f644
  can_add = gtk_entry_get_text_length (GTK_ENTRY (data->username)) != 0
Packit 79f644
            && gtk_entry_get_text_length (GTK_ENTRY (data->password)) != 0;
Packit 79f644
Packit 79f644
 out:
Packit 79f644
  gtk_dialog_set_response_sensitive (data->dialog, GTK_RESPONSE_OK, can_add);
Packit 79f644
  g_free (uri);
Packit 79f644
}
Packit 79f644
Packit 79f644
static void
Packit 79f644
show_progress_ui (GtkContainer *container, gboolean progress)
Packit 79f644
{
Packit 79f644
  GList *children;
Packit 79f644
  GList *l;
Packit 79f644
Packit 79f644
  children = gtk_container_get_children (container);
Packit 79f644
  for (l = children; l != NULL; l = l->next)
Packit 79f644
    {
Packit 79f644
      GtkWidget *widget = GTK_WIDGET (l->data);
Packit 79f644
      gdouble opacity;
Packit 79f644
Packit 79f644
      opacity = progress ? 1.0 : 0.0;
Packit 79f644
      gtk_widget_set_opacity (widget, opacity);
Packit 79f644
    }
Packit 79f644
Packit 79f644
  g_list_free (children);
Packit 79f644
}
Packit 79f644
Packit 79f644
static void
Packit 79f644
create_account_details_ui (GoaProvider    *provider,
Packit 79f644
                           GtkDialog      *dialog,
Packit 79f644
                           GtkBox         *vbox,
Packit 79f644
                           gboolean        new_account,
Packit 79f644
                           gboolean        is_template,
Packit 79f644
                           AddAccountData *data)
Packit 79f644
{
Packit 79f644
  GtkWidget *grid0;
Packit 79f644
  GtkWidget *grid1;
Packit 79f644
  GtkWidget *label;
Packit 79f644
  GtkWidget *spinner;
Packit 79f644
  gint row;
Packit 79f644
  gint width;
Packit 79f644
Packit 79f644
  goa_utils_set_dialog_title (provider, dialog, new_account);
Packit 79f644
Packit 79f644
  grid0 = gtk_grid_new ();
Packit 79f644
  gtk_container_set_border_width (GTK_CONTAINER (grid0), 5);
Packit 79f644
  gtk_widget_set_margin_bottom (grid0, 6);
Packit 79f644
  gtk_orientable_set_orientation (GTK_ORIENTABLE (grid0), GTK_ORIENTATION_VERTICAL);
Packit 79f644
  gtk_grid_set_row_spacing (GTK_GRID (grid0), 12);
Packit 79f644
  gtk_container_add (GTK_CONTAINER (vbox), grid0);
Packit 79f644
Packit 79f644
  data->cluebar = gtk_info_bar_new ();
Packit 79f644
  gtk_info_bar_set_message_type (GTK_INFO_BAR (data->cluebar), GTK_MESSAGE_ERROR);
Packit 79f644
  gtk_widget_set_hexpand (data->cluebar, TRUE);
Packit 79f644
  gtk_widget_set_no_show_all (data->cluebar, TRUE);
Packit 79f644
  gtk_container_add (GTK_CONTAINER (grid0), data->cluebar);
Packit 79f644
Packit 79f644
  data->cluebar_label = gtk_label_new ("");
Packit 79f644
  gtk_label_set_line_wrap (GTK_LABEL (data->cluebar_label), TRUE);
Packit 79f644
  gtk_container_add (GTK_CONTAINER (gtk_info_bar_get_content_area (GTK_INFO_BAR (data->cluebar))),
Packit 79f644
                     data->cluebar_label);
Packit 79f644
Packit 79f644
  grid1 = gtk_grid_new ();
Packit 79f644
  gtk_grid_set_column_spacing (GTK_GRID (grid1), 12);
Packit 79f644
  gtk_grid_set_row_spacing (GTK_GRID (grid1), 12);
Packit 79f644
  gtk_container_add (GTK_CONTAINER (grid0), grid1);
Packit 79f644
Packit 79f644
  row = 0;
Packit 79f644
  add_entry (grid1, row++, _("_Server"), &data->uri);
Packit 79f644
  add_entry (grid1, row++, _("User_name"), &data->username);
Packit 79f644
  add_entry (grid1, row++, _("_Password"), &data->password);
Packit 79f644
  gtk_entry_set_visibility (GTK_ENTRY (data->password), FALSE);
Packit 79f644
Packit 79f644
  if (new_account)
Packit 79f644
    gtk_widget_grab_focus (data->uri);
Packit 79f644
  else if (is_template)
Packit 79f644
    gtk_widget_grab_focus (data->username);
Packit 79f644
  else
Packit 79f644
    gtk_widget_grab_focus (data->password);
Packit 79f644
Packit 79f644
  g_signal_connect (data->uri, "changed", G_CALLBACK (on_uri_username_or_password_changed), data);
Packit 79f644
  g_signal_connect (data->username, "changed", G_CALLBACK (on_uri_username_or_password_changed), data);
Packit 79f644
  g_signal_connect (data->password, "changed", G_CALLBACK (on_uri_username_or_password_changed), data);
Packit 79f644
Packit 79f644
  gtk_dialog_add_button (data->dialog, _("_Cancel"), GTK_RESPONSE_CANCEL);
Packit 79f644
  data->connect_button = gtk_dialog_add_button (data->dialog, _("C_onnect"), GTK_RESPONSE_OK);
Packit 79f644
  gtk_dialog_set_default_response (data->dialog, GTK_RESPONSE_OK);
Packit 79f644
  gtk_dialog_set_response_sensitive (data->dialog, GTK_RESPONSE_OK, FALSE);
Packit 79f644
Packit 79f644
  data->progress_grid = gtk_grid_new ();
Packit 79f644
  gtk_orientable_set_orientation (GTK_ORIENTABLE (data->progress_grid), GTK_ORIENTATION_HORIZONTAL);
Packit 79f644
  gtk_grid_set_column_spacing (GTK_GRID (data->progress_grid), 3);
Packit 79f644
  gtk_container_add (GTK_CONTAINER (grid0), data->progress_grid);
Packit 79f644
Packit 79f644
  spinner = gtk_spinner_new ();
Packit 79f644
  gtk_widget_set_opacity (spinner, 0.0);
Packit 79f644
  gtk_widget_set_size_request (spinner, 20, 20);
Packit 79f644
  gtk_spinner_start (GTK_SPINNER (spinner));
Packit 79f644
  gtk_container_add (GTK_CONTAINER (data->progress_grid), spinner);
Packit 79f644
Packit 79f644
  label = gtk_label_new (_("Connecting…"));
Packit 79f644
  gtk_widget_set_opacity (label, 0.0);
Packit 79f644
  gtk_container_add (GTK_CONTAINER (data->progress_grid), label);
Packit 79f644
Packit 79f644
  if (new_account)
Packit 79f644
    {
Packit 79f644
      gtk_window_get_size (GTK_WINDOW (data->dialog), &width, NULL);
Packit 79f644
      gtk_window_set_default_size (GTK_WINDOW (data->dialog), width, -1);
Packit 79f644
    }
Packit 79f644
  else
Packit 79f644
    {
Packit 79f644
      GtkWindow *parent;
Packit 79f644
Packit 79f644
      /* Keep in sync with GoaPanelAddAccountDialog in
Packit 79f644
       * gnome-control-center.
Packit 79f644
       */
Packit 79f644
      parent = gtk_window_get_transient_for (GTK_WINDOW (data->dialog));
Packit 79f644
      if (parent != NULL)
Packit 79f644
        {
Packit 79f644
          gtk_window_get_size (parent, &width, NULL);
Packit 79f644
          gtk_window_set_default_size (GTK_WINDOW (data->dialog), (gint) (0.5 * width), -1);
Packit 79f644
        }
Packit 79f644
    }
Packit 79f644
}
Packit 79f644
Packit 79f644
/* ---------------------------------------------------------------------------------------------------- */
Packit 79f644
Packit 79f644
static void
Packit 79f644
add_account_cb (GoaManager *manager, GAsyncResult *res, gpointer user_data)
Packit 79f644
{
Packit 79f644
  AddAccountData *data = user_data;
Packit 79f644
  goa_manager_call_add_account_finish (manager,
Packit 79f644
                                       &data->account_object_path,
Packit 79f644
                                       res,
Packit 79f644
                                       &data->error);
Packit 79f644
  g_main_loop_quit (data->loop);
Packit 79f644
}
Packit 79f644
Packit 79f644
static void
Packit 79f644
check_cb (GObject *source_object, GAsyncResult *res, gpointer user_data)
Packit 79f644
{
Packit 79f644
  GoaHttpClient *client = GOA_HTTP_CLIENT (source_object);
Packit 79f644
  AddAccountData *data = user_data;
Packit 79f644
Packit 79f644
  goa_http_client_check_finish (client, res, &data->error);
Packit 79f644
  g_main_loop_quit (data->loop);
Packit 79f644
  gtk_widget_set_sensitive (data->connect_button, TRUE);
Packit 79f644
  show_progress_ui (GTK_CONTAINER (data->progress_grid), FALSE);
Packit 79f644
}
Packit 79f644
Packit 79f644
static void
Packit 79f644
dialog_response_cb (GtkDialog *dialog, gint response_id, gpointer user_data)
Packit 79f644
{
Packit 79f644
  AddAccountData *data = user_data;
Packit 79f644
Packit 79f644
  if (response_id == GTK_RESPONSE_CANCEL || response_id == GTK_RESPONSE_DELETE_EVENT)
Packit 79f644
    g_cancellable_cancel (data->cancellable);
Packit 79f644
}
Packit 79f644
Packit 79f644
/* ---------------------------------------------------------------------------------------------------- */
Packit 79f644
Packit 79f644
static GoaObject *
Packit 79f644
add_account (GoaProvider    *provider,
Packit 79f644
             GoaClient      *client,
Packit 79f644
             GtkDialog      *dialog,
Packit 79f644
             GtkBox         *vbox,
Packit 79f644
             GError        **error)
Packit 79f644
{
Packit 79f644
  AddAccountData data;
Packit 79f644
  GVariantBuilder credentials;
Packit 79f644
  GVariantBuilder details;
Packit 79f644
  GoaHttpClient *http_client = NULL;
Packit 79f644
  GoaObject *ret = NULL;
Packit 79f644
  gboolean accept_ssl_errors = FALSE;
Packit 79f644
  const gchar *uri_text;
Packit 79f644
  const gchar *password;
Packit 79f644
  const gchar *username;
Packit 79f644
  const gchar *provider_type;
Packit 79f644
  gchar *presentation_identity = NULL;
Packit 79f644
  gchar *server = NULL;
Packit 79f644
  gchar *uri = NULL;
Packit 79f644
  gchar *uri_webdav;
Packit 79f644
  gint response;
Packit 79f644
Packit 79f644
  memset (&data, 0, sizeof (AddAccountData));
Packit 79f644
  data.cancellable = g_cancellable_new ();
Packit 79f644
  data.loop = g_main_loop_new (NULL, FALSE);
Packit 79f644
  data.dialog = dialog;
Packit 79f644
  data.error = NULL;
Packit 79f644
Packit 79f644
  create_account_details_ui (provider, dialog, vbox, TRUE, FALSE, &data);
Packit 79f644
  gtk_widget_show_all (GTK_WIDGET (vbox));
Packit 79f644
  g_signal_connect (dialog, "response", G_CALLBACK (dialog_response_cb), &data);
Packit 79f644
Packit 79f644
  http_client = goa_http_client_new ();
Packit 79f644
Packit 79f644
 http_again:
Packit 79f644
  response = gtk_dialog_run (dialog);
Packit 79f644
  if (response != GTK_RESPONSE_OK)
Packit 79f644
    {
Packit 79f644
      g_set_error (&data.error,
Packit 79f644
                   GOA_ERROR,
Packit 79f644
                   GOA_ERROR_DIALOG_DISMISSED,
Packit 79f644
                   _("Dialog was dismissed"));
Packit 79f644
      goto out;
Packit 79f644
    }
Packit 79f644
Packit 79f644
  uri_text = gtk_entry_get_text (GTK_ENTRY (data.uri));
Packit 79f644
  username = gtk_entry_get_text (GTK_ENTRY (data.username));
Packit 79f644
  password = gtk_entry_get_text (GTK_ENTRY (data.password));
Packit 79f644
Packit 79f644
  uri = normalize_uri (uri_text, &server);
Packit 79f644
  presentation_identity = g_strconcat (username, "@", server, NULL);
Packit 79f644
Packit 79f644
  /* See if there's already an account of this type with the
Packit 79f644
   * given identity
Packit 79f644
   */
Packit 79f644
  provider_type = goa_provider_get_provider_type (provider);
Packit 79f644
  if (!goa_utils_check_duplicate (client,
Packit 79f644
                                  username,
Packit 79f644
                                  presentation_identity,
Packit 79f644
                                  provider_type,
Packit 79f644
                                  (GoaPeekInterfaceFunc) goa_object_peek_password_based,
Packit 79f644
                                  &data.error))
Packit 79f644
    goto out;
Packit 79f644
Packit 79f644
  uri_webdav = g_strconcat (uri, WEBDAV_ENDPOINT, NULL);
Packit 79f644
Packit 79f644
  g_clear_object (&data.cancellable);
Packit 79f644
  data.cancellable = g_cancellable_new ();
Packit 79f644
Packit 79f644
  goa_http_client_check (http_client,
Packit 79f644
                         uri_webdav,
Packit 79f644
                         username,
Packit 79f644
                         password,
Packit 79f644
                         accept_ssl_errors,
Packit 79f644
                         data.cancellable,
Packit 79f644
                         check_cb,
Packit 79f644
                         &data);
Packit 79f644
  g_free (uri_webdav);
Packit 79f644
Packit 79f644
  gtk_widget_set_sensitive (data.connect_button, FALSE);
Packit 79f644
  show_progress_ui (GTK_CONTAINER (data.progress_grid), TRUE);
Packit 79f644
  g_main_loop_run (data.loop);
Packit 79f644
Packit 79f644
  if (g_cancellable_is_cancelled (data.cancellable))
Packit 79f644
    {
Packit 79f644
      g_prefix_error (&data.error,
Packit 79f644
                      _("Dialog was dismissed (%s, %d): "),
Packit 79f644
                      g_quark_to_string (data.error->domain),
Packit 79f644
                      data.error->code);
Packit 79f644
      data.error->domain = GOA_ERROR;
Packit 79f644
      data.error->code = GOA_ERROR_DIALOG_DISMISSED;
Packit 79f644
      goto out;
Packit 79f644
    }
Packit 79f644
  else if (data.error != NULL)
Packit 79f644
    {
Packit 79f644
      gchar *markup;
Packit 79f644
Packit 79f644
      if (data.error->code == GOA_ERROR_SSL)
Packit 79f644
        {
Packit 79f644
          gtk_button_set_label (GTK_BUTTON (data.connect_button), _("_Ignore"));
Packit 79f644
          accept_ssl_errors = TRUE;
Packit 79f644
        }
Packit 79f644
      else
Packit 79f644
        {
Packit 79f644
          gtk_button_set_label (GTK_BUTTON (data.connect_button), _("_Try Again"));
Packit 79f644
          accept_ssl_errors = FALSE;
Packit 79f644
        }
Packit 79f644
Packit 79f644
      markup = g_strdup_printf ("%s:\n%s",
Packit 79f644
                                _("Error connecting to ownCloud server"),
Packit 79f644
                                data.error->message);
Packit 79f644
      g_clear_error (&data.error);
Packit 79f644
Packit 79f644
      gtk_label_set_markup (GTK_LABEL (data.cluebar_label), markup);
Packit 79f644
      g_free (markup);
Packit 79f644
Packit 79f644
      gtk_widget_set_no_show_all (data.cluebar, FALSE);
Packit 79f644
      gtk_widget_show_all (data.cluebar);
Packit 79f644
Packit 79f644
      g_clear_pointer (&presentation_identity, g_free);
Packit 79f644
      g_clear_pointer (&server, g_free);
Packit 79f644
      g_clear_pointer (&uri, g_free);
Packit 79f644
      goto http_again;
Packit 79f644
    }
Packit 79f644
Packit 79f644
  gtk_widget_hide (GTK_WIDGET (dialog));
Packit 79f644
Packit 79f644
  g_variant_builder_init (&credentials, G_VARIANT_TYPE_VARDICT);
Packit 79f644
  g_variant_builder_add (&credentials, "{sv}", "password", g_variant_new_string (password));
Packit 79f644
Packit 79f644
  g_variant_builder_init (&details, G_VARIANT_TYPE ("a{ss}"));
Packit 79f644
  g_variant_builder_add (&details, "{ss}", "CalendarEnabled", "true");
Packit 79f644
  g_variant_builder_add (&details, "{ss}", "ContactsEnabled", "true");
Packit 79f644
  g_variant_builder_add (&details, "{ss}", "DocumentsEnabled", "true");
Packit 79f644
  g_variant_builder_add (&details, "{ss}", "FilesEnabled", "true");
Packit 79f644
  g_variant_builder_add (&details, "{ss}", "Uri", uri);
Packit 79f644
  g_variant_builder_add (&details, "{ss}", "AcceptSslErrors", (accept_ssl_errors) ? "true" : "false");
Packit 79f644
Packit 79f644
  /* OK, everything is dandy, add the account */
Packit 79f644
  /* we want the GoaClient to update before this method returns (so it
Packit 79f644
   * can create a proxy for the new object) so run the mainloop while
Packit 79f644
   * waiting for this to complete
Packit 79f644
   */
Packit 79f644
  goa_manager_call_add_account (goa_client_get_manager (client),
Packit 79f644
                                goa_provider_get_provider_type (provider),
Packit 79f644
                                username,
Packit 79f644
                                presentation_identity,
Packit 79f644
                                g_variant_builder_end (&credentials),
Packit 79f644
                                g_variant_builder_end (&details),
Packit 79f644
                                NULL, /* GCancellable* */
Packit 79f644
                                (GAsyncReadyCallback) add_account_cb,
Packit 79f644
                                &data);
Packit 79f644
  g_main_loop_run (data.loop);
Packit 79f644
  if (data.error != NULL)
Packit 79f644
    goto out;
Packit 79f644
Packit 79f644
  ret = GOA_OBJECT (g_dbus_object_manager_get_object (goa_client_get_object_manager (client),
Packit 79f644
                                                      data.account_object_path));
Packit 79f644
Packit 79f644
 out:
Packit 79f644
  /* We might have an object even when data.error is set.
Packit 79f644
   * eg., if we failed to store the credentials in the keyring.
Packit 79f644
   */
Packit 79f644
  if (data.error != NULL)
Packit 79f644
    g_propagate_error (error, data.error);
Packit 79f644
  else
Packit 79f644
    g_assert (ret != NULL);
Packit 79f644
Packit 79f644
  g_signal_handlers_disconnect_by_func (dialog, dialog_response_cb, &data);
Packit 79f644
Packit 79f644
  g_free (presentation_identity);
Packit 79f644
  g_free (server);
Packit 79f644
  g_free (uri);
Packit 79f644
  g_free (data.account_object_path);
Packit 79f644
  g_clear_pointer (&data.loop, (GDestroyNotify) g_main_loop_unref);
Packit 79f644
  g_clear_object (&data.cancellable);
Packit 79f644
  g_clear_object (&http_client);
Packit 79f644
  return ret;
Packit 79f644
}
Packit 79f644
Packit 79f644
/* ---------------------------------------------------------------------------------------------------- */
Packit 79f644
Packit 79f644
static gboolean
Packit 79f644
refresh_account (GoaProvider    *provider,
Packit 79f644
                 GoaClient      *client,
Packit 79f644
                 GoaObject      *object,
Packit 79f644
                 GtkWindow      *parent,
Packit 79f644
                 GError        **error)
Packit 79f644
{
Packit 79f644
  AddAccountData data;
Packit 79f644
  GVariantBuilder credentials;
Packit 79f644
  GoaAccount *account;
Packit 79f644
  GoaHttpClient *http_client = NULL;
Packit 79f644
  GtkWidget *dialog;
Packit 79f644
  GtkWidget *vbox;
Packit 79f644
  gboolean accept_ssl_errors;
Packit 79f644
  gboolean is_template = FALSE;
Packit 79f644
  gboolean ret = FALSE;
Packit 79f644
  const gchar *password;
Packit 79f644
  const gchar *username;
Packit 79f644
  gchar *uri = NULL;
Packit 79f644
  gchar *uri_webdav = NULL;
Packit 79f644
  gint response;
Packit 79f644
Packit 79f644
  g_return_val_if_fail (GOA_IS_OWNCLOUD_PROVIDER (provider), FALSE);
Packit 79f644
  g_return_val_if_fail (GOA_IS_CLIENT (client), FALSE);
Packit 79f644
  g_return_val_if_fail (GOA_IS_OBJECT (object), FALSE);
Packit 79f644
  g_return_val_if_fail (parent == NULL || GTK_IS_WINDOW (parent), FALSE);
Packit 79f644
  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
Packit 79f644
Packit 79f644
  dialog = gtk_dialog_new_with_buttons (NULL,
Packit 79f644
                                        parent,
Packit 79f644
                                        GTK_DIALOG_MODAL
Packit 79f644
                                        | GTK_DIALOG_DESTROY_WITH_PARENT
Packit 79f644
                                        | GTK_DIALOG_USE_HEADER_BAR,
Packit 79f644
                                        NULL,
Packit 79f644
                                        NULL);
Packit 79f644
  gtk_container_set_border_width (GTK_CONTAINER (dialog), 12);
Packit 79f644
  gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
Packit 79f644
  gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
Packit 79f644
Packit 79f644
  vbox = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
Packit 79f644
  gtk_box_set_spacing (GTK_BOX (vbox), 12);
Packit 79f644
Packit 79f644
  memset (&data, 0, sizeof (AddAccountData));
Packit 79f644
  data.cancellable = g_cancellable_new ();
Packit 79f644
  data.loop = g_main_loop_new (NULL, FALSE);
Packit 79f644
  data.dialog = GTK_DIALOG (dialog);
Packit 79f644
  data.error = NULL;
Packit 79f644
Packit 79f644
  account = goa_object_peek_account (object);
Packit 79f644
  username = goa_account_get_identity (account);
Packit 79f644
  if (username == NULL || username[0] == '\0')
Packit 79f644
    is_template = TRUE;
Packit 79f644
Packit 79f644
  create_account_details_ui (provider, GTK_DIALOG (dialog), GTK_BOX (vbox), FALSE, is_template, &data);
Packit 79f644
Packit 79f644
  accept_ssl_errors = goa_util_lookup_keyfile_boolean (object, "AcceptSslErrors");
Packit 79f644
  uri = goa_util_lookup_keyfile_string (object, "Uri");
Packit 79f644
  gtk_entry_set_text (GTK_ENTRY (data.uri), uri);
Packit 79f644
  gtk_editable_set_editable (GTK_EDITABLE (data.uri), FALSE);
Packit 79f644
Packit 79f644
  if (!is_template)
Packit 79f644
    {
Packit 79f644
      gtk_entry_set_text (GTK_ENTRY (data.username), username);
Packit 79f644
      gtk_editable_set_editable (GTK_EDITABLE (data.username), FALSE);
Packit 79f644
    }
Packit 79f644
Packit 79f644
  gtk_widget_show_all (dialog);
Packit 79f644
  g_signal_connect (dialog, "response", G_CALLBACK (dialog_response_cb), &data);
Packit 79f644
Packit 79f644
  http_client = goa_http_client_new ();
Packit 79f644
  uri_webdav = g_strconcat (uri, WEBDAV_ENDPOINT, NULL);
Packit 79f644
Packit 79f644
 http_again:
Packit 79f644
  response = gtk_dialog_run (GTK_DIALOG (dialog));
Packit 79f644
  if (response != GTK_RESPONSE_OK)
Packit 79f644
    {
Packit 79f644
      g_set_error (&data.error,
Packit 79f644
                   GOA_ERROR,
Packit 79f644
                   GOA_ERROR_DIALOG_DISMISSED,
Packit 79f644
                   _("Dialog was dismissed"));
Packit 79f644
      goto out;
Packit 79f644
    }
Packit 79f644
Packit 79f644
  if (is_template)
Packit 79f644
    username = gtk_entry_get_text (GTK_ENTRY (data.username));
Packit 79f644
Packit 79f644
  password = gtk_entry_get_text (GTK_ENTRY (data.password));
Packit 79f644
Packit 79f644
  g_clear_object (&data.cancellable);
Packit 79f644
  data.cancellable = g_cancellable_new ();
Packit 79f644
Packit 79f644
  goa_http_client_check (http_client,
Packit 79f644
                         uri_webdav,
Packit 79f644
                         username,
Packit 79f644
                         password,
Packit 79f644
                         accept_ssl_errors,
Packit 79f644
                         data.cancellable,
Packit 79f644
                         check_cb,
Packit 79f644
                         &data);
Packit 79f644
  gtk_widget_set_sensitive (data.connect_button, FALSE);
Packit 79f644
  show_progress_ui (GTK_CONTAINER (data.progress_grid), TRUE);
Packit 79f644
  g_main_loop_run (data.loop);
Packit 79f644
Packit 79f644
  if (g_cancellable_is_cancelled (data.cancellable))
Packit 79f644
    {
Packit 79f644
      g_prefix_error (&data.error,
Packit 79f644
                      _("Dialog was dismissed (%s, %d): "),
Packit 79f644
                      g_quark_to_string (data.error->domain),
Packit 79f644
                      data.error->code);
Packit 79f644
      data.error->domain = GOA_ERROR;
Packit 79f644
      data.error->code = GOA_ERROR_DIALOG_DISMISSED;
Packit 79f644
      goto out;
Packit 79f644
    }
Packit 79f644
  else if (data.error != NULL)
Packit 79f644
    {
Packit 79f644
      gchar *markup;
Packit 79f644
Packit 79f644
      markup = g_strdup_printf ("%s:\n%s",
Packit 79f644
                                _("Error connecting to ownCloud server"),
Packit 79f644
                                data.error->message);
Packit 79f644
      g_clear_error (&data.error);
Packit 79f644
Packit 79f644
      gtk_label_set_markup (GTK_LABEL (data.cluebar_label), markup);
Packit 79f644
      g_free (markup);
Packit 79f644
Packit 79f644
      gtk_button_set_label (GTK_BUTTON (data.connect_button), _("_Try Again"));
Packit 79f644
      gtk_widget_set_no_show_all (data.cluebar, FALSE);
Packit 79f644
      gtk_widget_show_all (data.cluebar);
Packit 79f644
      goto http_again;
Packit 79f644
    }
Packit 79f644
Packit 79f644
  /* TODO: run in worker thread */
Packit 79f644
  g_variant_builder_init (&credentials, G_VARIANT_TYPE_VARDICT);
Packit 79f644
  g_variant_builder_add (&credentials, "{sv}", "password", g_variant_new_string (password));
Packit 79f644
Packit 79f644
  if (is_template)
Packit 79f644
    {
Packit 79f644
      GVariantBuilder details;
Packit 79f644
      GoaManager *manager;
Packit 79f644
      const gchar *id;
Packit 79f644
      const gchar *provider_type;
Packit 79f644
      gchar *dummy = NULL;
Packit 79f644
      gchar *presentation_identity = NULL;
Packit 79f644
      gchar *server = NULL;
Packit 79f644
Packit 79f644
      manager = goa_client_get_manager (client);
Packit 79f644
      id = goa_account_get_id (account);
Packit 79f644
      provider_type = goa_provider_get_provider_type (provider);
Packit 79f644
Packit 79f644
      dummy = normalize_uri (uri, &server);
Packit 79f644
      presentation_identity = g_strconcat (username, "@", server, NULL);
Packit 79f644
      g_free (dummy);
Packit 79f644
      g_free (server);
Packit 79f644
Packit 79f644
      g_variant_builder_init (&details, G_VARIANT_TYPE ("a{ss}"));
Packit 79f644
      g_variant_builder_add (&details, "{ss}", "Id", id);
Packit 79f644
Packit 79f644
      goa_manager_call_add_account (manager,
Packit 79f644
                                    provider_type,
Packit 79f644
                                    username,
Packit 79f644
                                    presentation_identity,
Packit 79f644
                                    g_variant_builder_end (&credentials),
Packit 79f644
                                    g_variant_builder_end (&details),
Packit 79f644
                                    NULL, /* GCancellable* */
Packit 79f644
                                    (GAsyncReadyCallback) add_account_cb,
Packit 79f644
                                    &data);
Packit 79f644
      g_free (presentation_identity);
Packit 79f644
Packit 79f644
      g_main_loop_run (data.loop);
Packit 79f644
      if (data.error != NULL)
Packit 79f644
        goto out;
Packit 79f644
    }
Packit 79f644
  else
Packit 79f644
    {
Packit 79f644
      if (!goa_utils_store_credentials_for_object_sync (provider,
Packit 79f644
                                                        object,
Packit 79f644
                                                        g_variant_builder_end (&credentials),
Packit 79f644
                                                        NULL, /* GCancellable */
Packit 79f644
                                                        &data.error))
Packit 79f644
        goto out;
Packit 79f644
    }
Packit 79f644
Packit 79f644
  goa_account_call_ensure_credentials (account,
Packit 79f644
                                       NULL, /* GCancellable */
Packit 79f644
                                       NULL, NULL); /* callback, user_data */
Packit 79f644
Packit 79f644
  ret = TRUE;
Packit 79f644
Packit 79f644
 out:
Packit 79f644
  if (data.error != NULL)
Packit 79f644
    g_propagate_error (error, data.error);
Packit 79f644
Packit 79f644
  gtk_widget_destroy (dialog);
Packit 79f644
  g_free (uri);
Packit 79f644
  g_free (uri_webdav);
Packit 79f644
  g_free (data.account_object_path);
Packit 79f644
  g_clear_pointer (&data.loop, (GDestroyNotify) g_main_loop_unref);
Packit 79f644
  g_clear_object (&data.cancellable);
Packit 79f644
  g_clear_object (&http_client);
Packit 79f644
  return ret;
Packit 79f644
}
Packit 79f644
Packit 79f644
/* ---------------------------------------------------------------------------------------------------- */
Packit 79f644
Packit 79f644
static void
Packit 79f644
goa_owncloud_provider_init (GoaOwncloudProvider *self)
Packit 79f644
{
Packit 79f644
}
Packit 79f644
Packit 79f644
static void
Packit 79f644
goa_owncloud_provider_class_init (GoaOwncloudProviderClass *klass)
Packit 79f644
{
Packit 79f644
  GoaProviderClass *provider_class;
Packit 79f644
Packit 79f644
  provider_class = GOA_PROVIDER_CLASS (klass);
Packit 79f644
  provider_class->get_provider_type          = get_provider_type;
Packit 79f644
  provider_class->get_provider_name          = get_provider_name;
Packit 79f644
  provider_class->get_provider_group         = get_provider_group;
Packit 79f644
  provider_class->get_provider_features      = get_provider_features;
Packit 79f644
  provider_class->add_account                = add_account;
Packit 79f644
  provider_class->refresh_account            = refresh_account;
Packit 79f644
  provider_class->build_object               = build_object;
Packit 79f644
  provider_class->ensure_credentials_sync    = ensure_credentials_sync;
Packit 79f644
}
Packit 79f644
Packit 79f644
/* ---------------------------------------------------------------------------------------------------- */
Packit 79f644
Packit 79f644
static gboolean
Packit 79f644
on_handle_get_password (GoaPasswordBased      *interface,
Packit 79f644
                        GDBusMethodInvocation *invocation,
Packit 79f644
                        const gchar           *id, /* unused */
Packit 79f644
                        gpointer               user_data)
Packit 79f644
{
Packit 79f644
  GoaObject *object;
Packit 79f644
  GoaAccount *account;
Packit 79f644
  GoaProvider *provider;
Packit 79f644
  GError *error;
Packit 79f644
  const gchar *account_id;
Packit 79f644
  const gchar *method_name;
Packit 79f644
  const gchar *provider_type;
Packit 79f644
  gchar *password = NULL;
Packit 79f644
Packit 79f644
  /* TODO: maybe log what app is requesting access */
Packit 79f644
Packit 79f644
  object = GOA_OBJECT (g_dbus_interface_get_object (G_DBUS_INTERFACE (interface)));
Packit 79f644
  account = goa_object_peek_account (object);
Packit 79f644
  account_id = goa_account_get_id (account);
Packit 79f644
  provider_type = goa_account_get_provider_type (account);
Packit 79f644
  method_name = g_dbus_method_invocation_get_method_name (invocation);
Packit 79f644
  g_debug ("Handling %s for account (%s, %s)", method_name, provider_type, account_id);
Packit 79f644
Packit 79f644
  provider = goa_provider_get_for_provider_type (provider_type);
Packit 79f644
Packit 79f644
  error = NULL;
Packit 79f644
  if (!goa_utils_get_credentials (provider, object, "password", NULL, &password, NULL, &error))
Packit 79f644
    {
Packit 79f644
      g_dbus_method_invocation_take_error (invocation, error);
Packit 79f644
      goto out;
Packit 79f644
    }
Packit 79f644
Packit 79f644
  goa_password_based_complete_get_password (interface, invocation, password);
Packit 79f644
Packit 79f644
 out:
Packit 79f644
  g_free (password);
Packit 79f644
  g_object_unref (provider);
Packit 79f644
  return TRUE; /* invocation was handled */
Packit 79f644
}