[hotssh] Parse ~/.ssh/known_hosts, use for entry completion
- From: Colin Walters <walters src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [hotssh] Parse ~/.ssh/known_hosts, use for entry completion
- Date: Mon, 2 Dec 2013 02:58:32 +0000 (UTC)
commit 31367e50c55efa9eb0b7715a4563f02615aa81b0
Author: Colin Walters <walters verbum org>
Date: Tue Nov 26 17:07:29 2013 -0500
Parse ~/.ssh/known_hosts, use for entry completion
Makefile-src.am | 2 +
src/hotssh-hostdb.c | 202 +++++++++++++++++++++++++++++++++++++++++++++++++++
src/hotssh-hostdb.h | 36 +++++++++
src/hotssh-tab.c | 30 ++++++++
4 files changed, 270 insertions(+), 0 deletions(-)
---
diff --git a/Makefile-src.am b/Makefile-src.am
index ed2cf73..071dbab 100644
--- a/Makefile-src.am
+++ b/Makefile-src.am
@@ -18,6 +18,7 @@ CLEANFILES += hotssh-search-glue.h hotssh-search-glue.c
hotssh_headers = $(addprefix src/, \
hotssh-app.h \
hotssh-search-provider.h \
+ hotssh-hostdb.h \
hotssh-tab.h \
hotssh-password-interaction.h \
hotssh-win.h \
@@ -30,6 +31,7 @@ hotssh_SOURCES = $(hotssh_headers) \
src/main.c \
src/hotssh-app.c \
src/hotssh-search-provider.c \
+ src/hotssh-hostdb.c \
src/hotssh-tab.c \
src/hotssh-password-interaction.c \
src/hotssh-win.c \
diff --git a/src/hotssh-hostdb.c b/src/hotssh-hostdb.c
new file mode 100644
index 0000000..8dbb687
--- /dev/null
+++ b/src/hotssh-hostdb.c
@@ -0,0 +1,202 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2013 Colin Walters <walters verbum org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include "hotssh-hostdb.h"
+#include "hotssh-win.h"
+#include "hotssh-prefs.h"
+
+#include "libgsystem.h"
+
+struct _HotSshHostDB
+{
+ GObject parent;
+};
+
+struct _HotSshHostDBClass
+{
+ GObjectClass parent_class;
+};
+
+typedef struct _HotSshHostDBPrivate HotSshHostDBPrivate;
+
+struct _HotSshHostDBPrivate
+{
+ GtkListStore *model;
+ GFile *openssh_dir;
+ GFile *openssh_knownhosts_path;
+ GFile *hotssh_extra;
+ GFileMonitor *knownhosts_monitor;
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE(HotSshHostDB, hotssh_hostdb, G_TYPE_OBJECT)
+
+static void
+on_knownhosts_changed (GFileMonitor *monitor,
+ GFile *src,
+ GFile *other,
+ GFileMonitorEvent event,
+ gpointer user_data)
+{
+ HotSshHostDB *self = user_data;
+ G_GNUC_UNUSED HotSshHostDBPrivate *priv = hotssh_hostdb_get_instance_private (self);
+ GError *local_error = NULL;
+ gs_free char *contents = NULL;
+ GtkTreeIter modeliter;
+ gsize len;
+ char *iter;
+ char *eol;
+ char *carriage;
+
+ if (!g_file_load_contents (priv->openssh_knownhosts_path, NULL,
+ &contents, &len, NULL,
+ &local_error))
+ goto out;
+
+ gtk_list_store_clear (priv->model);
+
+ iter = contents;
+ while (TRUE)
+ {
+ gs_strfreev char **parts = NULL;
+ char *comma;
+
+ eol = strchr (iter, '\n');
+ if (eol)
+ *eol = '\0';
+
+ carriage = strrchr (iter, '\r');
+ if (carriage)
+ *carriage = '\0';
+
+ if (contents[0] == '#')
+ goto next;
+
+ parts = g_strsplit (iter, " ", -1);
+ if (!parts || g_strv_length (parts) < 3)
+ goto next;
+
+ comma = strchr (parts[0], ',');
+ if (comma)
+ *comma = '\0';
+ gtk_list_store_append (priv->model, &modeliter);
+ gtk_list_store_set (priv->model, &modeliter, 0, parts[0], 1, 0, -1);
+
+ next:
+ if (eol)
+ iter = eol + 1;
+ else
+ break;
+ }
+
+ g_debug ("Read %d known hosts", gtk_tree_model_iter_n_children ((GtkTreeModel*)priv->model, NULL));
+
+ out:
+ if (local_error)
+ {
+ g_debug ("Failed to read '%s': %s", gs_file_get_path_cached (priv->openssh_knownhosts_path),
+ local_error->message);
+ g_clear_error (&local_error);
+ }
+}
+
+static void
+hotssh_hostdb_init (HotSshHostDB *self)
+{
+ HotSshHostDBPrivate *priv = hotssh_hostdb_get_instance_private (self);
+ const char *homedir;
+ GError *local_error = NULL;
+ gs_free char *knownhosts_path = NULL;
+ gs_free char *openssh_path = NULL;
+
+ priv->model = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_UINT64);
+ homedir = g_get_home_dir ();
+ g_assert (homedir);
+
+ openssh_path = g_build_filename (homedir, ".ssh", NULL);
+ knownhosts_path = g_build_filename (openssh_path, "known_hosts", NULL);
+
+ priv->openssh_dir = g_file_new_for_path (openssh_path);
+ priv->openssh_knownhosts_path = g_file_new_for_path (knownhosts_path);
+
+ if (!g_file_query_exists (priv->openssh_dir, NULL))
+ {
+ if (!g_file_make_directory (priv->openssh_dir, NULL, &local_error))
+ {
+ g_error ("Failed to make '%s' directory: %s",
+ gs_file_get_path_cached (priv->openssh_dir),
+ local_error->message);
+ }
+ }
+
+ priv->knownhosts_monitor = g_file_monitor (priv->openssh_knownhosts_path, 0, NULL,
+ &local_error);
+ if (!priv->knownhosts_monitor)
+ {
+ g_error ("Failed to monitor '%s': %s",
+ gs_file_get_path_cached (priv->openssh_knownhosts_path),
+ local_error->message);
+ }
+
+ g_signal_connect (priv->knownhosts_monitor, "changed",
+ G_CALLBACK (on_knownhosts_changed), self);
+ on_knownhosts_changed (priv->knownhosts_monitor, NULL, NULL, 0, self);
+}
+
+static void
+hotssh_hostdb_dispose (GObject *object)
+{
+ HotSshHostDBPrivate *priv = hotssh_hostdb_get_instance_private ((HotSshHostDB*)object);
+
+ g_clear_object (&priv->model);
+
+ G_OBJECT_CLASS (hotssh_hostdb_parent_class)->dispose (object);
+}
+
+static void
+hotssh_hostdb_class_init (HotSshHostDBClass *class)
+{
+ G_OBJECT_CLASS (class)->dispose = hotssh_hostdb_dispose;
+}
+
+HotSshHostDB *
+hotssh_hostdb_get_instance (void)
+{
+ static gsize initialized;
+ static HotSshHostDB *instance = NULL;
+
+ if (g_once_init_enter (&initialized))
+ {
+ instance = g_object_new (HOTSSH_TYPE_HOSTDB, NULL);
+
+ g_once_init_leave (&initialized, 1);
+ }
+ return g_object_ref (instance);
+}
+
+GtkTreeModel *
+hotssh_hostdb_get_model (HotSshHostDB *self)
+{
+ HotSshHostDBPrivate *priv = hotssh_hostdb_get_instance_private (self);
+ return g_object_ref (priv->model);
+}
diff --git a/src/hotssh-hostdb.h b/src/hotssh-hostdb.h
new file mode 100644
index 0000000..cc5cdd3
--- /dev/null
+++ b/src/hotssh-hostdb.h
@@ -0,0 +1,36 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2013 Colin Walters <walters verbum org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+#define HOTSSH_TYPE_HOSTDB (hotssh_hostdb_get_type ())
+#define HOTSSH_HOSTDB(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), HOTSSH_TYPE_HOSTDB, HotSshHostDB))
+
+typedef struct _HotSshHostDB HotSshHostDB;
+typedef struct _HotSshHostDBClass HotSshHostDBClass;
+
+GType hotssh_hostdb_get_type (void);
+HotSshHostDB *hotssh_hostdb_get_instance (void);
+
+GtkTreeModel *hotssh_hostdb_get_model (HotSshHostDB *self);
+
+
diff --git a/src/hotssh-tab.c b/src/hotssh-tab.c
index ce1bccc..a05b6be 100644
--- a/src/hotssh-tab.c
+++ b/src/hotssh-tab.c
@@ -19,6 +19,7 @@
*/
#include "hotssh-tab.h"
+#include "hotssh-hostdb.h"
#include "hotssh-password-interaction.h"
#include "gssh.h"
@@ -92,6 +93,7 @@ struct _HotSshTabPrivate
guint authmechanism_index;
char *hostname;
+ GtkEntryCompletion *host_completion;
GSocketConnectable *address;
GSshConnection *connection;
GSshChannel *channel;
@@ -736,6 +738,20 @@ hotssh_tab_style_updated (GtkWidget *widget)
vte_terminal_set_color_background_rgba ((VteTerminal*)priv->terminal, &bg);
}
+static gboolean
+host_entry_match (GtkEntryCompletion *completion,
+ const char *key,
+ GtkTreeIter *iter,
+ gpointer user_data)
+{
+ gs_free char *host = NULL;
+ GtkTreeModel *model = gtk_entry_completion_get_model (completion);
+
+ gtk_tree_model_get (model, iter, 0, &host, -1);
+
+ return g_str_has_prefix (host, key);
+}
+
static void
hotssh_tab_grab_focus (GtkWidget *widget)
{
@@ -793,15 +809,29 @@ hotssh_tab_init (HotSshTab *self)
gtk_widget_show_all (priv->terminal_box);
g_queue_init (&priv->write_queue);
+
+ {
+ gs_unref_object HotSshHostDB *hostdb = hotssh_hostdb_get_instance ();
+ gs_unref_object GtkTreeModel *hostdb_model = hotssh_hostdb_get_model (hostdb);
+ priv->host_completion = gtk_entry_completion_new ();
+ gtk_entry_completion_set_match_func (priv->host_completion, host_entry_match, self, NULL);
+ gtk_entry_completion_set_model (priv->host_completion, hostdb_model);
+ gtk_entry_completion_set_text_column (priv->host_completion, 0);
+ gtk_entry_completion_set_inline_completion (priv->host_completion, TRUE);
+ gtk_entry_set_completion ((GtkEntry*)priv->host_entry, priv->host_completion);
+ }
}
static void
hotssh_tab_dispose (GObject *object)
{
HotSshTab *self = HOTSSH_TAB (object);
+ HotSshTabPrivate *priv = hotssh_tab_get_instance_private (self);
page_transition (self, HOTSSH_TAB_PAGE_NEW_CONNECTION);
+ g_clear_object (&priv->host_completion);
+
G_OBJECT_CLASS (hotssh_tab_parent_class)->dispose (object);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]