Blame src/shell-keyring-prompt.c

Packit d345d1
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
Packit d345d1
/*
Packit d345d1
 * Copyright 2012 Red Hat, Inc.
Packit d345d1
 *           2012 Stef Walter <stefw@gnome.org>
Packit d345d1
 *
Packit d345d1
 * This program is free software; you can redistribute it and/or modify
Packit d345d1
 * it under the terms of the GNU General Public License as published by
Packit d345d1
 * the Free Software Foundation; either version 2 of the License, or
Packit d345d1
 * (at your option) any later version.
Packit d345d1
 *
Packit d345d1
 * This program is distributed in the hope that it will be useful,
Packit d345d1
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit d345d1
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit d345d1
 * GNU General Public License for more details.
Packit d345d1
 *
Packit d345d1
 * You should have received a copy of the GNU General Public License along
Packit d345d1
 * with this program; if not, write to the Free Software Foundation, Inc.,
Packit d345d1
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Packit d345d1
 *
Packit d345d1
 * Author: Stef Walter <stefw@gnome.org>
Packit d345d1
 */
Packit d345d1
Packit d345d1
#include "config.h"
Packit d345d1
Packit d345d1
#include "shell-keyring-prompt.h"
Packit d345d1
#include "shell-secure-text-buffer.h"
Packit d345d1
Packit d345d1
#define GCR_API_SUBJECT_TO_CHANGE
Packit d345d1
#include <gcr/gcr-base.h>
Packit d345d1
Packit d345d1
#include <glib/gi18n.h>
Packit d345d1
Packit d345d1
#include <string.h>
Packit d345d1
Packit d345d1
typedef struct _ShellPasswordPromptPrivate  ShellPasswordPromptPrivate;
Packit d345d1
Packit d345d1
typedef enum
Packit d345d1
{
Packit d345d1
  PROMPTING_NONE,
Packit d345d1
  PROMPTING_FOR_CONFIRM,
Packit d345d1
  PROMPTING_FOR_PASSWORD
Packit d345d1
} PromptingMode;
Packit d345d1
Packit d345d1
struct _ShellKeyringPrompt
Packit d345d1
{
Packit d345d1
  GObject parent;
Packit d345d1
Packit d345d1
  gchar *title;
Packit d345d1
  gchar *message;
Packit d345d1
  gchar *description;
Packit d345d1
  gchar *warning;
Packit d345d1
  gchar *choice_label;
Packit d345d1
  gboolean choice_chosen;
Packit d345d1
  gboolean password_new;
Packit d345d1
  guint password_strength;
Packit d345d1
  gchar *continue_label;
Packit d345d1
  gchar *cancel_label;
Packit d345d1
Packit d345d1
  GTask *task;
Packit d345d1
  ClutterText *password_actor;
Packit d345d1
  ClutterText *confirm_actor;
Packit d345d1
  PromptingMode mode;
Packit d345d1
  gboolean shown;
Packit d345d1
};
Packit d345d1
Packit d345d1
enum {
Packit d345d1
  PROP_0,
Packit d345d1
  PROP_TITLE,
Packit d345d1
  PROP_MESSAGE,
Packit d345d1
  PROP_DESCRIPTION,
Packit d345d1
  PROP_WARNING,
Packit d345d1
  PROP_CHOICE_LABEL,
Packit d345d1
  PROP_CHOICE_CHOSEN,
Packit d345d1
  PROP_PASSWORD_NEW,
Packit d345d1
  PROP_PASSWORD_STRENGTH,
Packit d345d1
  PROP_CALLER_WINDOW,
Packit d345d1
  PROP_CONTINUE_LABEL,
Packit d345d1
  PROP_CANCEL_LABEL,
Packit d345d1
  PROP_PASSWORD_VISIBLE,
Packit d345d1
  PROP_CONFIRM_VISIBLE,
Packit d345d1
  PROP_WARNING_VISIBLE,
Packit d345d1
  PROP_CHOICE_VISIBLE,
Packit d345d1
  PROP_PASSWORD_ACTOR,
Packit d345d1
  PROP_CONFIRM_ACTOR
Packit d345d1
};
Packit d345d1
Packit d345d1
static void    shell_keyring_prompt_iface     (GcrPromptIface *iface);
Packit d345d1
Packit d345d1
G_DEFINE_TYPE_WITH_CODE (ShellKeyringPrompt, shell_keyring_prompt, G_TYPE_OBJECT,
Packit d345d1
                         G_IMPLEMENT_INTERFACE (GCR_TYPE_PROMPT, shell_keyring_prompt_iface);
Packit d345d1
);
Packit d345d1
Packit d345d1
enum {
Packit d345d1
  SIGNAL_SHOW_PASSWORD,
Packit d345d1
  SIGNAL_SHOW_CONFIRM,
Packit d345d1
  SIGNAL_LAST
Packit d345d1
};
Packit d345d1
Packit d345d1
static gint signals[SIGNAL_LAST];
Packit d345d1
Packit d345d1
static void
Packit d345d1
shell_keyring_prompt_init (ShellKeyringPrompt *self)
Packit d345d1
{
Packit d345d1
Packit d345d1
}
Packit d345d1
Packit d345d1
static gchar *
Packit d345d1
remove_mnemonics (const GValue *value)
Packit d345d1
{
Packit d345d1
  const gchar mnemonic = '_';
Packit d345d1
  gchar *stripped_label, *temp;
Packit d345d1
  const gchar *label;
Packit d345d1
Packit d345d1
  g_return_val_if_fail (value != NULL, NULL);
Packit d345d1
  g_return_val_if_fail (G_VALUE_HOLDS_STRING (value), NULL);
Packit d345d1
Packit d345d1
  label = g_value_get_string (value);
Packit d345d1
  g_return_val_if_fail (label != NULL, NULL);
Packit d345d1
Packit d345d1
  /* Stripped label will have the original label lenght at most */
Packit d345d1
  stripped_label = temp = g_new (gchar, strlen(label) + 1);
Packit d345d1
  g_assert (stripped_label != NULL);
Packit d345d1
Packit d345d1
  while (*label != '\0')
Packit d345d1
    {
Packit d345d1
      if (*label == mnemonic)
Packit d345d1
        label++;
Packit d345d1
      *(temp++) = *(label++);
Packit d345d1
    }
Packit d345d1
  *temp = '\0';
Packit d345d1
Packit d345d1
  return stripped_label;
Packit d345d1
}
Packit d345d1
Packit d345d1
static void
Packit d345d1
shell_keyring_prompt_set_property (GObject      *obj,
Packit d345d1
                                   guint         prop_id,
Packit d345d1
                                   const GValue *value,
Packit d345d1
                                   GParamSpec   *pspec)
Packit d345d1
{
Packit d345d1
  ShellKeyringPrompt *self = SHELL_KEYRING_PROMPT (obj);
Packit d345d1
Packit d345d1
  switch (prop_id) {
Packit d345d1
  case PROP_TITLE:
Packit d345d1
    g_free (self->title);
Packit d345d1
    self->title = g_value_dup_string (value);
Packit d345d1
    g_object_notify (obj, "title");
Packit d345d1
    break;
Packit d345d1
  case PROP_MESSAGE:
Packit d345d1
    g_free (self->message);
Packit d345d1
    self->message = g_value_dup_string (value);
Packit d345d1
    g_object_notify (obj, "message");
Packit d345d1
    break;
Packit d345d1
  case PROP_DESCRIPTION:
Packit d345d1
    g_free (self->description);
Packit d345d1
    self->description = g_value_dup_string (value);
Packit d345d1
    g_object_notify (obj, "description");
Packit d345d1
    break;
Packit d345d1
  case PROP_WARNING:
Packit d345d1
    g_free (self->warning);
Packit d345d1
    self->warning = g_value_dup_string (value);
Packit d345d1
    if (!self->warning)
Packit d345d1
        self->warning = g_strdup ("");
Packit d345d1
    g_object_notify (obj, "warning");
Packit d345d1
    g_object_notify (obj, "warning-visible");
Packit d345d1
    break;
Packit d345d1
  case PROP_CHOICE_LABEL:
Packit d345d1
    g_free (self->choice_label);
Packit d345d1
    self->choice_label = remove_mnemonics (value);
Packit d345d1
    if (!self->choice_label)
Packit d345d1
        self->choice_label = g_strdup ("");
Packit d345d1
    g_object_notify (obj, "choice-label");
Packit d345d1
    g_object_notify (obj, "choice-visible");
Packit d345d1
    break;
Packit d345d1
  case PROP_CHOICE_CHOSEN:
Packit d345d1
    self->choice_chosen = g_value_get_boolean (value);
Packit d345d1
    g_object_notify (obj, "choice-chosen");
Packit d345d1
    break;
Packit d345d1
  case PROP_PASSWORD_NEW:
Packit d345d1
    self->password_new = g_value_get_boolean (value);
Packit d345d1
    g_object_notify (obj, "password-new");
Packit d345d1
    g_object_notify (obj, "confirm-visible");
Packit d345d1
    break;
Packit d345d1
  case PROP_CALLER_WINDOW:
Packit d345d1
    /* ignored */
Packit d345d1
    break;
Packit d345d1
  case PROP_CONTINUE_LABEL:
Packit d345d1
    g_free (self->continue_label);
Packit d345d1
    self->continue_label = remove_mnemonics (value);
Packit d345d1
    g_object_notify (obj, "continue-label");
Packit d345d1
    break;
Packit d345d1
  case PROP_CANCEL_LABEL:
Packit d345d1
    g_free (self->cancel_label);
Packit d345d1
    self->cancel_label = remove_mnemonics (value);
Packit d345d1
    g_object_notify (obj, "cancel-label");
Packit d345d1
    break;
Packit d345d1
  case PROP_PASSWORD_ACTOR:
Packit d345d1
    shell_keyring_prompt_set_password_actor (self, g_value_get_object (value));
Packit d345d1
    break;
Packit d345d1
  case PROP_CONFIRM_ACTOR:
Packit d345d1
    shell_keyring_prompt_set_confirm_actor (self, g_value_get_object (value));
Packit d345d1
    break;
Packit d345d1
  default:
Packit d345d1
    G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
Packit d345d1
    break;
Packit d345d1
  }
Packit d345d1
}
Packit d345d1
Packit d345d1
static void
Packit d345d1
shell_keyring_prompt_get_property (GObject    *obj,
Packit d345d1
                                   guint       prop_id,
Packit d345d1
                                   GValue     *value,
Packit d345d1
                                   GParamSpec *pspec)
Packit d345d1
{
Packit d345d1
  ShellKeyringPrompt *self = SHELL_KEYRING_PROMPT (obj);
Packit d345d1
Packit d345d1
  switch (prop_id) {
Packit d345d1
  case PROP_TITLE:
Packit d345d1
    g_value_set_string (value, self->title ? self->title : "");
Packit d345d1
    break;
Packit d345d1
  case PROP_MESSAGE:
Packit d345d1
    g_value_set_string (value, self->message ? self->message : "");
Packit d345d1
    break;
Packit d345d1
  case PROP_DESCRIPTION:
Packit d345d1
    g_value_set_string (value, self->description ? self->description : "");
Packit d345d1
    break;
Packit d345d1
  case PROP_WARNING:
Packit d345d1
    g_value_set_string (value, self->warning ? self->warning : "");
Packit d345d1
    break;
Packit d345d1
  case PROP_CHOICE_LABEL:
Packit d345d1
    g_value_set_string (value, self->choice_label ? self->choice_label : "");
Packit d345d1
    break;
Packit d345d1
  case PROP_CHOICE_CHOSEN:
Packit d345d1
    g_value_set_boolean (value, self->choice_chosen);
Packit d345d1
    break;
Packit d345d1
  case PROP_PASSWORD_NEW:
Packit d345d1
    g_value_set_boolean (value, self->password_new);
Packit d345d1
    break;
Packit d345d1
  case PROP_PASSWORD_STRENGTH:
Packit d345d1
    g_value_set_int (value, self->password_strength);
Packit d345d1
    break;
Packit d345d1
  case PROP_CALLER_WINDOW:
Packit d345d1
    g_value_set_string (value, "");
Packit d345d1
    break;
Packit d345d1
  case PROP_CONTINUE_LABEL:
Packit d345d1
    g_value_set_string (value, self->continue_label);
Packit d345d1
    break;
Packit d345d1
  case PROP_CANCEL_LABEL:
Packit d345d1
    g_value_set_string (value, self->cancel_label);
Packit d345d1
    break;
Packit d345d1
  case PROP_PASSWORD_VISIBLE:
Packit d345d1
    g_value_set_boolean (value, self->mode == PROMPTING_FOR_PASSWORD);
Packit d345d1
    break;
Packit d345d1
  case PROP_CONFIRM_VISIBLE:
Packit d345d1
    g_value_set_boolean (value, self->password_new &&
Packit d345d1
                                self->mode == PROMPTING_FOR_PASSWORD);
Packit d345d1
    break;
Packit d345d1
  case PROP_WARNING_VISIBLE:
Packit d345d1
    g_value_set_boolean (value, self->warning && self->warning[0]);
Packit d345d1
    break;
Packit d345d1
  case PROP_CHOICE_VISIBLE:
Packit d345d1
    g_value_set_boolean (value, self->choice_label && self->choice_label[0]);
Packit d345d1
    break;
Packit d345d1
  case PROP_PASSWORD_ACTOR:
Packit d345d1
    g_value_set_object (value, shell_keyring_prompt_get_password_actor (self));
Packit d345d1
    break;
Packit d345d1
  case PROP_CONFIRM_ACTOR:
Packit d345d1
    g_value_set_object (value, shell_keyring_prompt_get_confirm_actor (self));
Packit d345d1
    break;
Packit d345d1
  default:
Packit d345d1
    G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
Packit d345d1
    break;
Packit d345d1
  }
Packit d345d1
}
Packit d345d1
Packit d345d1
static void
Packit d345d1
shell_keyring_prompt_dispose (GObject *obj)
Packit d345d1
{
Packit d345d1
  ShellKeyringPrompt *self = SHELL_KEYRING_PROMPT (obj);
Packit d345d1
Packit d345d1
  if (self->shown)
Packit d345d1
    gcr_prompt_close (GCR_PROMPT (self));
Packit d345d1
Packit d345d1
  if (self->task)
Packit d345d1
    shell_keyring_prompt_cancel (self);
Packit d345d1
  g_assert (self->task == NULL);
Packit d345d1
Packit d345d1
  shell_keyring_prompt_set_password_actor (self, NULL);
Packit d345d1
  shell_keyring_prompt_set_confirm_actor (self, NULL);
Packit d345d1
Packit d345d1
  G_OBJECT_CLASS (shell_keyring_prompt_parent_class)->dispose (obj);
Packit d345d1
}
Packit d345d1
Packit d345d1
static void
Packit d345d1
shell_keyring_prompt_finalize (GObject *obj)
Packit d345d1
{
Packit d345d1
  ShellKeyringPrompt *self = SHELL_KEYRING_PROMPT (obj);
Packit d345d1
Packit d345d1
  g_free (self->title);
Packit d345d1
  g_free (self->message);
Packit d345d1
  g_free (self->description);
Packit d345d1
  g_free (self->warning);
Packit d345d1
  g_free (self->choice_label);
Packit d345d1
  g_free (self->continue_label);
Packit d345d1
  g_free (self->cancel_label);
Packit d345d1
Packit d345d1
  G_OBJECT_CLASS (shell_keyring_prompt_parent_class)->finalize (obj);
Packit d345d1
}
Packit d345d1
Packit d345d1
static void
Packit d345d1
shell_keyring_prompt_class_init (ShellKeyringPromptClass *klass)
Packit d345d1
{
Packit d345d1
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
Packit d345d1
Packit d345d1
  gobject_class->get_property = shell_keyring_prompt_get_property;
Packit d345d1
  gobject_class->set_property = shell_keyring_prompt_set_property;
Packit d345d1
  gobject_class->dispose = shell_keyring_prompt_dispose;
Packit d345d1
  gobject_class->finalize = shell_keyring_prompt_finalize;
Packit d345d1
Packit d345d1
  g_object_class_override_property (gobject_class, PROP_TITLE, "title");
Packit d345d1
Packit d345d1
  g_object_class_override_property (gobject_class, PROP_MESSAGE, "message");
Packit d345d1
Packit d345d1
  g_object_class_override_property (gobject_class, PROP_DESCRIPTION, "description");
Packit d345d1
Packit d345d1
  g_object_class_override_property (gobject_class, PROP_WARNING, "warning");
Packit d345d1
Packit d345d1
  g_object_class_override_property (gobject_class, PROP_PASSWORD_NEW, "password-new");
Packit d345d1
Packit d345d1
  g_object_class_override_property (gobject_class, PROP_PASSWORD_STRENGTH, "password-strength");
Packit d345d1
Packit d345d1
  g_object_class_override_property (gobject_class, PROP_CHOICE_LABEL, "choice-label");
Packit d345d1
Packit d345d1
  g_object_class_override_property (gobject_class, PROP_CHOICE_CHOSEN, "choice-chosen");
Packit d345d1
Packit d345d1
  g_object_class_override_property (gobject_class, PROP_CALLER_WINDOW, "caller-window");
Packit d345d1
Packit d345d1
  g_object_class_override_property (gobject_class, PROP_CONTINUE_LABEL, "continue-label");
Packit d345d1
Packit d345d1
  g_object_class_override_property (gobject_class, PROP_CANCEL_LABEL, "cancel-label");
Packit d345d1
Packit d345d1
  /**
Packit d345d1
   * ShellKeyringPrompt:password-visible:
Packit d345d1
   *
Packit d345d1
   * Whether the password entry is visible or not.
Packit d345d1
   */
Packit d345d1
  g_object_class_install_property (gobject_class, PROP_PASSWORD_VISIBLE,
Packit d345d1
             g_param_spec_boolean ("password-visible", "Password visible", "Password field is visible",
Packit d345d1
                                   FALSE, G_PARAM_READABLE));
Packit d345d1
Packit d345d1
  /**
Packit d345d1
    * ShellKeyringPrompt:confirm-visible:
Packit d345d1
    *
Packit d345d1
    * Whether the password confirm entry is visible or not.
Packit d345d1
    */
Packit d345d1
  g_object_class_install_property (gobject_class, PROP_CONFIRM_VISIBLE,
Packit d345d1
             g_param_spec_boolean ("confirm-visible", "Confirm visible", "Confirm field is visible",
Packit d345d1
                                   FALSE, G_PARAM_READABLE));
Packit d345d1
Packit d345d1
  /**
Packit d345d1
   * ShellKeyringPrompt:warning-visible:
Packit d345d1
   *
Packit d345d1
   * Whether the warning label is visible or not.
Packit d345d1
   */
Packit d345d1
  g_object_class_install_property (gobject_class, PROP_WARNING_VISIBLE,
Packit d345d1
             g_param_spec_boolean ("warning-visible", "Warning visible", "Warning is visible",
Packit d345d1
                                   FALSE, G_PARAM_READABLE));
Packit d345d1
Packit d345d1
  /**
Packit d345d1
   * ShellKeyringPrompt:choice-visible:
Packit d345d1
   *
Packit d345d1
   * Whether the choice check box is visible or not.
Packit d345d1
   */
Packit d345d1
  g_object_class_install_property (gobject_class, PROP_CHOICE_VISIBLE,
Packit d345d1
             g_param_spec_boolean ("choice-visible", "Choice visible", "Choice is visible",
Packit d345d1
                                   FALSE, G_PARAM_READABLE));
Packit d345d1
Packit d345d1
  /**
Packit d345d1
   * ShellKeyringPrompt:password-actor:
Packit d345d1
   *
Packit d345d1
   * Text field for password
Packit d345d1
   */
Packit d345d1
  g_object_class_install_property (gobject_class, PROP_PASSWORD_ACTOR,
Packit d345d1
              g_param_spec_object ("password-actor", "Password actor", "Text field for password",
Packit d345d1
                                   CLUTTER_TYPE_TEXT, G_PARAM_READWRITE));
Packit d345d1
Packit d345d1
  /**
Packit d345d1
   * ShellKeyringPrompt:confirm-actor:
Packit d345d1
   *
Packit d345d1
   * Text field for confirmation password
Packit d345d1
   */
Packit d345d1
  g_object_class_install_property (gobject_class, PROP_CONFIRM_ACTOR,
Packit d345d1
              g_param_spec_object ("confirm-actor", "Confirm actor", "Text field for confirming password",
Packit d345d1
                                   CLUTTER_TYPE_TEXT, G_PARAM_READWRITE));
Packit d345d1
Packit d345d1
  signals[SIGNAL_SHOW_PASSWORD] = g_signal_new ("show-password", G_TYPE_FROM_CLASS (klass),
Packit d345d1
                                                0, 0, NULL, NULL,
Packit d345d1
                                                g_cclosure_marshal_VOID__VOID,
Packit d345d1
                                                G_TYPE_NONE, 0);
Packit d345d1
Packit d345d1
  signals[SIGNAL_SHOW_CONFIRM] =  g_signal_new ("show-confirm", G_TYPE_FROM_CLASS (klass),
Packit d345d1
                                                0, 0, NULL, NULL,
Packit d345d1
                                                g_cclosure_marshal_VOID__VOID,
Packit d345d1
                                                G_TYPE_NONE, 0);
Packit d345d1
}
Packit d345d1
Packit d345d1
static void
Packit d345d1
shell_keyring_prompt_password_async (GcrPrompt          *prompt,
Packit d345d1
                                     GCancellable       *cancellable,
Packit d345d1
                                     GAsyncReadyCallback callback,
Packit d345d1
                                     gpointer            user_data)
Packit d345d1
{
Packit d345d1
  ShellKeyringPrompt *self = SHELL_KEYRING_PROMPT (prompt);
Packit d345d1
  GObject *obj;
Packit d345d1
Packit d345d1
  if (self->task != NULL) {
Packit d345d1
      g_warning ("this prompt can only show one prompt at a time");
Packit d345d1
      return;
Packit d345d1
  }
Packit d345d1
Packit d345d1
  self->mode = PROMPTING_FOR_PASSWORD;
Packit d345d1
  self->task = g_task_new (self, NULL, callback, user_data);
Packit d345d1
  g_task_set_source_tag (self->task, shell_keyring_prompt_password_async);
Packit d345d1
Packit d345d1
  obj = G_OBJECT (self);
Packit d345d1
  g_object_notify (obj, "password-visible");
Packit d345d1
  g_object_notify (obj, "confirm-visible");
Packit d345d1
  g_object_notify (obj, "warning-visible");
Packit d345d1
  g_object_notify (obj, "choice-visible");
Packit d345d1
Packit d345d1
  self->shown = TRUE;
Packit d345d1
  g_signal_emit (self, signals[SIGNAL_SHOW_PASSWORD], 0);
Packit d345d1
}
Packit d345d1
Packit d345d1
static const gchar *
Packit d345d1
shell_keyring_prompt_password_finish (GcrPrompt    *prompt,
Packit d345d1
                                      GAsyncResult *result,
Packit d345d1
                                      GError      **error)
Packit d345d1
{
Packit d345d1
  g_return_val_if_fail (g_task_get_source_object (G_TASK (result)) == prompt, NULL);
Packit d345d1
  g_return_val_if_fail (g_async_result_is_tagged (result,
Packit d345d1
                        shell_keyring_prompt_password_async), NULL);
Packit d345d1
Packit d345d1
  return g_task_propagate_pointer (G_TASK (result), error);
Packit d345d1
}
Packit d345d1
Packit d345d1
static void
Packit d345d1
shell_keyring_prompt_confirm_async (GcrPrompt          *prompt,
Packit d345d1
                                    GCancellable       *cancellable,
Packit d345d1
                                    GAsyncReadyCallback callback,
Packit d345d1
                                    gpointer            user_data)
Packit d345d1
{
Packit d345d1
  ShellKeyringPrompt *self = SHELL_KEYRING_PROMPT (prompt);
Packit d345d1
  GObject *obj;
Packit d345d1
Packit d345d1
  if (self->task != NULL) {
Packit d345d1
      g_warning ("this prompt is already prompting");
Packit d345d1
      return;
Packit d345d1
  }
Packit d345d1
Packit d345d1
  self->mode = PROMPTING_FOR_CONFIRM;
Packit d345d1
  self->task = g_task_new (self, NULL, callback, user_data);
Packit d345d1
  g_task_set_source_tag (self->task, shell_keyring_prompt_confirm_async);
Packit d345d1
Packit d345d1
  obj = G_OBJECT (self);
Packit d345d1
  g_object_notify (obj, "password-visible");
Packit d345d1
  g_object_notify (obj, "confirm-visible");
Packit d345d1
  g_object_notify (obj, "warning-visible");
Packit d345d1
  g_object_notify (obj, "choice-visible");
Packit d345d1
Packit d345d1
  self->shown = TRUE;
Packit d345d1
  g_signal_emit (self, signals[SIGNAL_SHOW_CONFIRM], 0);
Packit d345d1
}
Packit d345d1
Packit d345d1
static GcrPromptReply
Packit d345d1
shell_keyring_prompt_confirm_finish (GcrPrompt    *prompt,
Packit d345d1
                                     GAsyncResult *result,
Packit d345d1
                                     GError      **error)
Packit d345d1
{
Packit d345d1
  GTask *task = G_TASK (result);
Packit d345d1
  gssize res;
Packit d345d1
Packit d345d1
  g_return_val_if_fail (g_task_get_source_object (task) == prompt,
Packit d345d1
                        GCR_PROMPT_REPLY_CANCEL);
Packit d345d1
  g_return_val_if_fail (g_async_result_is_tagged (result,
Packit d345d1
                        shell_keyring_prompt_confirm_async), GCR_PROMPT_REPLY_CANCEL);
Packit d345d1
Packit d345d1
  res = g_task_propagate_int (task, error);
Packit d345d1
  return res == -1 ? GCR_PROMPT_REPLY_CANCEL : (GcrPromptReply)res;
Packit d345d1
}
Packit d345d1
Packit d345d1
static void
Packit d345d1
shell_keyring_prompt_close (GcrPrompt *prompt)
Packit d345d1
{
Packit d345d1
  ShellKeyringPrompt *self = SHELL_KEYRING_PROMPT (prompt);
Packit d345d1
Packit d345d1
  /*
Packit d345d1
   * We expect keyring.js to connect to this signal and do the
Packit d345d1
   * actual work of closing the prompt.
Packit d345d1
   */
Packit d345d1
Packit d345d1
  self->shown = FALSE;
Packit d345d1
}
Packit d345d1
Packit d345d1
static void
Packit d345d1
shell_keyring_prompt_iface (GcrPromptIface *iface)
Packit d345d1
{
Packit d345d1
  iface->prompt_password_async = shell_keyring_prompt_password_async;
Packit d345d1
  iface->prompt_password_finish = shell_keyring_prompt_password_finish;
Packit d345d1
  iface->prompt_confirm_async = shell_keyring_prompt_confirm_async;
Packit d345d1
  iface->prompt_confirm_finish = shell_keyring_prompt_confirm_finish;
Packit d345d1
  iface->prompt_close = shell_keyring_prompt_close;
Packit d345d1
}
Packit d345d1
Packit d345d1
/**
Packit d345d1
 * shell_keyring_prompt_new:
Packit d345d1
 *
Packit d345d1
 * Create new internal prompt base
Packit d345d1
 *
Packit d345d1
 * Returns: (transfer full): new internal prompt
Packit d345d1
 */
Packit d345d1
ShellKeyringPrompt *
Packit d345d1
shell_keyring_prompt_new (void)
Packit d345d1
{
Packit d345d1
	return g_object_new (SHELL_TYPE_KEYRING_PROMPT, NULL);
Packit d345d1
}
Packit d345d1
Packit d345d1
/**
Packit d345d1
 * shell_keyring_prompt_get_password_actor:
Packit d345d1
 * @self: the internal prompt
Packit d345d1
 *
Packit d345d1
 * Get the prompt password text actor
Packit d345d1
 *
Packit d345d1
 * Returns: (transfer none) (nullable): the password actor
Packit d345d1
 */
Packit d345d1
ClutterText *
Packit d345d1
shell_keyring_prompt_get_password_actor (ShellKeyringPrompt *self)
Packit d345d1
{
Packit d345d1
  g_return_val_if_fail (SHELL_IS_KEYRING_PROMPT (self), NULL);
Packit d345d1
  return self->password_actor;
Packit d345d1
}
Packit d345d1
Packit d345d1
/**
Packit d345d1
 * shell_keyring_prompt_get_confirm_actor:
Packit d345d1
 * @self: the internal prompt
Packit d345d1
 *
Packit d345d1
 * Get the prompt password text actor
Packit d345d1
 *
Packit d345d1
 * Returns: (transfer none) (nullable): the password actor
Packit d345d1
 */
Packit d345d1
ClutterText *
Packit d345d1
shell_keyring_prompt_get_confirm_actor (ShellKeyringPrompt *self)
Packit d345d1
{
Packit d345d1
  g_return_val_if_fail (SHELL_IS_KEYRING_PROMPT (self), NULL);
Packit d345d1
  return self->confirm_actor;
Packit d345d1
}
Packit d345d1
Packit d345d1
static guint
Packit d345d1
calculate_password_strength (const gchar *password)
Packit d345d1
{
Packit d345d1
  int upper, lower, digit, misc;
Packit d345d1
  gdouble pwstrength;
Packit d345d1
  int length, i;
Packit d345d1
Packit d345d1
  /*
Packit d345d1
   * This code is based on the Master Password dialog in Firefox
Packit d345d1
   * (pref-masterpass.js)
Packit d345d1
   * Original code triple-licensed under the MPL, GPL, and LGPL
Packit d345d1
   * so is license-compatible with this file
Packit d345d1
   */
Packit d345d1
Packit d345d1
  length = strlen (password);
Packit d345d1
Packit d345d1
  /* Always return 0 for empty passwords */
Packit d345d1
  if (length == 0)
Packit d345d1
    return 0;
Packit d345d1
Packit d345d1
  upper = 0;
Packit d345d1
  lower = 0;
Packit d345d1
  digit = 0;
Packit d345d1
  misc = 0;
Packit d345d1
Packit d345d1
  for (i = 0; i < length ; i++)
Packit d345d1
    {
Packit d345d1
      if (g_ascii_isdigit (password[i]))
Packit d345d1
        digit++;
Packit d345d1
      else if (g_ascii_islower (password[i]))
Packit d345d1
        lower++;
Packit d345d1
      else if (g_ascii_isupper (password[i]))
Packit d345d1
        upper++;
Packit d345d1
      else
Packit d345d1
        misc++;
Packit d345d1
    }
Packit d345d1
Packit d345d1
  if (length > 5)
Packit d345d1
    length = 5;
Packit d345d1
  if (digit > 3)
Packit d345d1
    digit = 3;
Packit d345d1
  if (upper > 3)
Packit d345d1
    upper = 3;
Packit d345d1
  if (misc > 3)
Packit d345d1
    misc = 3;
Packit d345d1
Packit d345d1
  pwstrength = ((length * 1) - 2) +
Packit d345d1
      (digit * 1) +
Packit d345d1
      (misc * 1.5) +
Packit d345d1
      (upper * 1);
Packit d345d1
Packit d345d1
  /* Always return 1+ for non-empty passwords */
Packit d345d1
  if (pwstrength < 1.0)
Packit d345d1
    pwstrength = 1.0;
Packit d345d1
  if (pwstrength > 10.0)
Packit d345d1
    pwstrength = 10.0;
Packit d345d1
Packit d345d1
  return (guint)pwstrength;
Packit d345d1
}
Packit d345d1
Packit d345d1
static void
Packit d345d1
on_password_changed (ClutterText *text,
Packit d345d1
                     gpointer user_data)
Packit d345d1
{
Packit d345d1
  ShellKeyringPrompt *self = SHELL_KEYRING_PROMPT (user_data);
Packit d345d1
  const gchar *password;
Packit d345d1
Packit d345d1
  password = clutter_text_get_text (self->password_actor);
Packit d345d1
Packit d345d1
  self->password_strength = calculate_password_strength (password);
Packit d345d1
  g_object_notify (G_OBJECT (self), "password-strength");
Packit d345d1
}
Packit d345d1
Packit d345d1
/**
Packit d345d1
 * shell_keyring_prompt_set_password_actor:
Packit d345d1
 * @self: the internal prompt
Packit d345d1
 * @password_actor: (nullable): the password actor
Packit d345d1
 *
Packit d345d1
 * Set the prompt password text actor
Packit d345d1
 */
Packit d345d1
void
Packit d345d1
shell_keyring_prompt_set_password_actor (ShellKeyringPrompt *self,
Packit d345d1
                                         ClutterText *password_actor)
Packit d345d1
{
Packit d345d1
  ClutterTextBuffer *buffer;
Packit d345d1
Packit d345d1
  g_return_if_fail (SHELL_IS_KEYRING_PROMPT (self));
Packit d345d1
  g_return_if_fail (password_actor == NULL || CLUTTER_IS_TEXT (password_actor));
Packit d345d1
Packit d345d1
  if (password_actor)
Packit d345d1
    {
Packit d345d1
      buffer = shell_secure_text_buffer_new ();
Packit d345d1
      clutter_text_set_buffer (password_actor, buffer);
Packit d345d1
      g_object_unref (buffer);
Packit d345d1
Packit d345d1
      g_signal_connect (password_actor, "text-changed", G_CALLBACK (on_password_changed), self);
Packit d345d1
      g_object_ref (password_actor);
Packit d345d1
    }
Packit d345d1
  if (self->password_actor)
Packit d345d1
    {
Packit d345d1
      g_signal_handlers_disconnect_by_func (self->password_actor, on_password_changed, self);
Packit d345d1
      g_object_unref (self->password_actor);
Packit d345d1
    }
Packit d345d1
Packit d345d1
  self->password_actor = password_actor;
Packit d345d1
  g_object_notify (G_OBJECT (self), "password-actor");
Packit d345d1
}
Packit d345d1
Packit d345d1
/**
Packit d345d1
 * shell_keyring_prompt_set_confirm_actor:
Packit d345d1
 * @self: the internal prompt
Packit d345d1
 * @confirm_actor: (nullable): the confirm password actor
Packit d345d1
 *
Packit d345d1
 * Set the prompt password confirmation text actor
Packit d345d1
 */
Packit d345d1
void
Packit d345d1
shell_keyring_prompt_set_confirm_actor (ShellKeyringPrompt *self,
Packit d345d1
                                        ClutterText *confirm_actor)
Packit d345d1
{
Packit d345d1
  ClutterTextBuffer *buffer;
Packit d345d1
Packit d345d1
  g_return_if_fail (SHELL_IS_KEYRING_PROMPT (self));
Packit d345d1
  g_return_if_fail (confirm_actor == NULL || CLUTTER_IS_TEXT (confirm_actor));
Packit d345d1
Packit d345d1
  if (confirm_actor)
Packit d345d1
    {
Packit d345d1
      buffer = shell_secure_text_buffer_new ();
Packit d345d1
      clutter_text_set_buffer (confirm_actor, buffer);
Packit d345d1
      g_object_unref (buffer);
Packit d345d1
Packit d345d1
      g_object_ref (confirm_actor);
Packit d345d1
    }
Packit d345d1
  if (self->confirm_actor)
Packit d345d1
    g_object_unref (self->confirm_actor);
Packit d345d1
  self->confirm_actor = confirm_actor;
Packit d345d1
  g_object_notify (G_OBJECT (self), "confirm-actor");
Packit d345d1
}
Packit d345d1
Packit d345d1
/**
Packit d345d1
 * shell_keyring_prompt_complete:
Packit d345d1
 * @self: the internal prompt
Packit d345d1
 *
Packit d345d1
 * Called by the implementation when the prompt completes. There are various
Packit d345d1
 * checks done. %TRUE is returned if the prompt actually should complete.
Packit d345d1
 *
Packit d345d1
 * Returns: whether the prompt completed
Packit d345d1
 */
Packit d345d1
gboolean
Packit d345d1
shell_keyring_prompt_complete (ShellKeyringPrompt *self)
Packit d345d1
{
Packit d345d1
  GTask *res;
Packit d345d1
  PromptingMode mode;
Packit d345d1
  const gchar *password;
Packit d345d1
  const gchar *confirm;
Packit d345d1
  const gchar *env;
Packit d345d1
Packit d345d1
  g_return_val_if_fail (SHELL_IS_KEYRING_PROMPT (self), FALSE);
Packit d345d1
  g_return_val_if_fail (self->mode != PROMPTING_NONE, FALSE);
Packit d345d1
  g_return_val_if_fail (self->task != NULL, FALSE);
Packit d345d1
Packit d345d1
  password = clutter_text_get_text (self->password_actor);
Packit d345d1
Packit d345d1
  if (self->mode == PROMPTING_FOR_PASSWORD)
Packit d345d1
    {
Packit d345d1
      /* Is it a new password? */
Packit d345d1
      if (self->password_new)
Packit d345d1
        {
Packit d345d1
          confirm = clutter_text_get_text (self->confirm_actor);
Packit d345d1
Packit d345d1
          /* Do the passwords match? */
Packit d345d1
          if (!g_str_equal (password, confirm))
Packit d345d1
            {
Packit d345d1
              gcr_prompt_set_warning (GCR_PROMPT (self), _("Passwords do not match."));
Packit d345d1
              return FALSE;
Packit d345d1
          }
Packit d345d1
Packit d345d1
          /* Don't allow blank passwords if in paranoid mode */
Packit d345d1
          env = g_getenv ("GNOME_KEYRING_PARANOID");
Packit d345d1
          if (env && *env)
Packit d345d1
            {
Packit d345d1
              gcr_prompt_set_warning (GCR_PROMPT (self), _("Password cannot be blank"));
Packit d345d1
              return FALSE;
Packit d345d1
            }
Packit d345d1
        }
Packit d345d1
Packit d345d1
      self->password_strength = calculate_password_strength (password);
Packit d345d1
      g_object_notify (G_OBJECT (self), "password-strength");
Packit d345d1
    }
Packit d345d1
Packit d345d1
  res = self->task;
Packit d345d1
  mode = self->mode;
Packit d345d1
  self->task = NULL;
Packit d345d1
  self->mode = PROMPTING_NONE;
Packit d345d1
Packit d345d1
  if (mode == PROMPTING_FOR_CONFIRM)
Packit d345d1
    g_task_return_int (res, (gssize)GCR_PROMPT_REPLY_CONTINUE);
Packit d345d1
  else
Packit d345d1
    g_task_return_pointer (res, (gpointer)password, NULL);
Packit d345d1
  g_object_unref (res);
Packit d345d1
Packit d345d1
  return TRUE;
Packit d345d1
}
Packit d345d1
Packit d345d1
/**
Packit d345d1
 * shell_keyring_prompt_cancel:
Packit d345d1
 * @self: the internal prompt
Packit d345d1
 *
Packit d345d1
 * Called by implementation when the prompt is cancelled.
Packit d345d1
 */
Packit d345d1
void
Packit d345d1
shell_keyring_prompt_cancel (ShellKeyringPrompt *self)
Packit d345d1
{
Packit d345d1
  GTask *res;
Packit d345d1
  PromptingMode mode;
Packit d345d1
Packit d345d1
  g_return_if_fail (SHELL_IS_KEYRING_PROMPT (self));
Packit d345d1
Packit d345d1
  /*
Packit d345d1
   * If cancelled while not prompting, we should just close the prompt,
Packit d345d1
   * the user wants it to go away.
Packit d345d1
   */
Packit d345d1
  if (self->mode == PROMPTING_NONE)
Packit d345d1
    {
Packit d345d1
      if (self->shown)
Packit d345d1
        gcr_prompt_close (GCR_PROMPT (self));
Packit d345d1
      return;
Packit d345d1
    }
Packit d345d1
Packit d345d1
  g_return_if_fail (self->task != NULL);
Packit d345d1
Packit d345d1
  res = self->task;
Packit d345d1
  mode = self->mode;
Packit d345d1
  self->task = NULL;
Packit d345d1
  self->mode = PROMPTING_NONE;
Packit d345d1
Packit d345d1
  if (mode == PROMPTING_FOR_CONFIRM)
Packit d345d1
    g_task_return_int (res, (gssize) GCR_PROMPT_REPLY_CANCEL);
Packit d345d1
  else
Packit d345d1
    g_task_return_pointer (res, NULL, NULL);
Packit d345d1
  g_object_unref (res);
Packit d345d1
}