(root)/
glib-2.79.0/
gio/
tests/
gtlsconsoleinteraction.c
       1  /* GIO - GLib Input, Output and Streaming Library
       2   *
       3   * Copyright (C) 2011 Collabora, Ltd.
       4   *
       5   * SPDX-License-Identifier: LGPL-2.1-or-later
       6   *
       7   * This library is free software; you can redistribute it and/or
       8   * modify it under the terms of the GNU Lesser General Public
       9   * License as published by the Free Software Foundation; either
      10   * version 2.1 of the License, or (at your option) any later version.
      11   *
      12   * This library is distributed in the hope that it will be useful,
      13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15   * Lesser General Public License for more details.
      16   *
      17   * You should have received a copy of the GNU Lesser General
      18   * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
      19   *
      20   * Author: Stef Walter <stefw@collabora.co.uk>
      21   */
      22  
      23  #include "config.h"
      24  
      25  #include <glib.h>
      26  #include <glib/gprintf.h>
      27  #include <string.h>
      28  
      29  #ifdef G_OS_WIN32
      30  #include <conio.h>
      31  #endif
      32  
      33  #include "gtlsconsoleinteraction.h"
      34  
      35  /*
      36   * WARNING: This is not the example you're looking for [slow hand wave]. This
      37   * is not industrial strength, it's just for testing. It uses embarrassing
      38   * functions like getpass() and does lazy things with threads.
      39   */
      40  
      41  G_DEFINE_TYPE (GTlsConsoleInteraction, g_tls_console_interaction, G_TYPE_TLS_INTERACTION)
      42  
      43  #if defined(G_OS_WIN32) || defined(__BIONIC__)
      44  /* win32 doesn't have getpass() */
      45  #include <stdio.h>
      46  #ifndef BUFSIZ
      47  #define BUFSIZ 8192
      48  #endif
      49  static gchar *
      50  static_getpass (const gchar *prompt)
      51  {
      52    static gchar buf[BUFSIZ];
      53    gint i;
      54  
      55    g_printf ("%s", prompt);
      56    fflush (stdout);
      57  
      58    for (i = 0; i < BUFSIZ - 1; ++i)
      59      {
      60  #ifdef __BIONIC__
      61        buf[i] = getc (stdin);
      62  #else
      63        buf[i] = _getch ();
      64  #endif
      65        if (buf[i] == '\r')
      66          break;
      67      }
      68    buf[i] = '\0';
      69  
      70    g_printf ("\n");
      71  
      72    return &buf[0];
      73  }
      74  #undef getpass
      75  #define getpass static_getpass /* avoid overloading a potential
      76                                    build environment defintion of getpass */
      77  #endif
      78  
      79  static GTlsInteractionResult
      80  g_tls_console_interaction_ask_password (GTlsInteraction    *interaction,
      81                                          GTlsPassword       *password,
      82                                          GCancellable       *cancellable,
      83                                          GError            **error)
      84  {
      85    const gchar *value;
      86    gchar *prompt;
      87  
      88    prompt = g_strdup_printf ("Password \"%s\"': ", g_tls_password_get_description (password));
      89    value = getpass (prompt);
      90    g_free (prompt);
      91  
      92    if (g_cancellable_set_error_if_cancelled (cancellable, error))
      93      return G_TLS_INTERACTION_FAILED;
      94  
      95    g_tls_password_set_value (password, (guchar *)value, -1);
      96    return G_TLS_INTERACTION_HANDLED;
      97  }
      98  
      99  static void
     100  ask_password_with_getpass (GTask        *task,
     101                             gpointer      object,
     102                             gpointer      task_data,
     103                             GCancellable *cancellable)
     104  {
     105    GTlsPassword *password = task_data;
     106    GError *error = NULL;
     107  
     108    g_tls_console_interaction_ask_password (G_TLS_INTERACTION (object), password,
     109                                            cancellable, &error);
     110    if (error != NULL)
     111      g_task_return_error (task, error);
     112    else
     113      g_task_return_int (task, G_TLS_INTERACTION_HANDLED);
     114  }
     115  
     116  static void
     117  g_tls_console_interaction_ask_password_async (GTlsInteraction    *interaction,
     118                                                GTlsPassword       *password,
     119                                                GCancellable       *cancellable,
     120                                                GAsyncReadyCallback callback,
     121                                                gpointer            user_data)
     122  {
     123    GTask *task;
     124  
     125    task = g_task_new (interaction, cancellable, callback, user_data);
     126    g_task_set_task_data (task, g_object_ref (password), g_object_unref);
     127    g_task_run_in_thread (task, ask_password_with_getpass);
     128    g_object_unref (task);
     129  }
     130  
     131  static GTlsInteractionResult
     132  g_tls_console_interaction_ask_password_finish (GTlsInteraction    *interaction,
     133                                                 GAsyncResult       *result,
     134                                                 GError            **error)
     135  {
     136    GTlsInteractionResult ret;
     137  
     138    g_return_val_if_fail (g_task_is_valid (result, interaction),
     139                          G_TLS_INTERACTION_FAILED);
     140  
     141    ret = g_task_propagate_int (G_TASK (result), error);
     142    if (ret == (GTlsInteractionResult)-1)
     143      return G_TLS_INTERACTION_FAILED;
     144    else
     145      return ret;
     146  }
     147  
     148  static void
     149  g_tls_console_interaction_init (GTlsConsoleInteraction *interaction)
     150  {
     151  
     152  }
     153  
     154  static void
     155  g_tls_console_interaction_class_init (GTlsConsoleInteractionClass *klass)
     156  {
     157    GTlsInteractionClass *interaction_class = G_TLS_INTERACTION_CLASS (klass);
     158    interaction_class->ask_password = g_tls_console_interaction_ask_password;
     159    interaction_class->ask_password_async = g_tls_console_interaction_ask_password_async;
     160    interaction_class->ask_password_finish = g_tls_console_interaction_ask_password_finish;
     161  }
     162  
     163  GTlsInteraction *
     164  g_tls_console_interaction_new (void)
     165  {
     166    return g_object_new (G_TYPE_TLS_CONSOLE_INTERACTION, NULL);
     167  }