[hotssh/wip/hostdb-rework] wip
- From: Colin Walters <walters src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [hotssh/wip/hostdb-rework] wip
- Date: Mon, 30 Dec 2013 17:46:51 +0000 (UTC)
commit 9f890261606a7bcd54eef7bed53835d78a055682
Author: Colin Walters <walters verbum org>
Date: Mon Dec 30 11:03:31 2013 -0500
wip
src/hotssh-hostdb.c | 455 +++++++++++++++++++++++++++------------------------
src/hotssh-hostdb.h | 27 +++-
2 files changed, 266 insertions(+), 216 deletions(-)
---
diff --git a/src/hotssh-hostdb.c b/src/hotssh-hostdb.c
index 560fc8a..9580f21 100644
--- a/src/hotssh-hostdb.c
+++ b/src/hotssh-hostdb.c
@@ -28,13 +28,6 @@
#include "libgsystem.h"
-enum {
- HOTSSH_HOSTDB_COLUMN_HOSTNAME,
- HOTSSH_HOSTDB_COLUMN_LAST_USED,
- HOTSSH_HOSTDB_COLUMN_IS_KNOWN,
- HOTSSH_HOSTDB_COLUMN_USERNAME
-};
-
struct _HotSshHostDB
{
GObject parent;
@@ -50,145 +43,79 @@ typedef struct _HotSshHostDBPrivate HotSshHostDBPrivate;
struct _HotSshHostDBPrivate
{
GtkListStore *model;
- GKeyFile *extradb;
+ GHashTable *openssh_knownhosts; /* str -> str */
+ GKeyFile *hostdb;
GFile *openssh_dir;
GFile *openssh_knownhosts_path;
- GFile *hotssh_extradb;
+ GFile *hotssh_hostdb_path;
GFileMonitor *knownhosts_monitor;
- GFileMonitor *hotssh_extradb_monitor;
- guint idle_save_extradb_id;
- char *new_extradb_contents;
+ guint idle_save_hostdb_id;
+ char *new_hostdb_contents;
};
G_DEFINE_TYPE_WITH_PRIVATE(HotSshHostDB, hotssh_hostdb, G_TYPE_OBJECT)
static char *
-host_group_key_to_host (const char *group)
+address_to_string (GNetworkAddress *address)
{
- char *hostname = NULL;
- const char *host_group_prefix = "host \"";
- const char *lastquote;
- const char *hoststart;
-
- if (!g_str_has_prefix (group, host_group_prefix))
- return NULL;
-
- hoststart = group + strlen (host_group_prefix);
- lastquote = strchr (hoststart, '"');
- if (!lastquote)
- return NULL;
-
- hostname = g_strndup (hoststart, lastquote - hoststart);
- if (!(hostname && hostname[0]))
- {
- g_free (hostname);
- return NULL;
- }
-
- return hostname;
+ const char *hostname = g_network_address_get_hostname (address);
+ guint port = g_network_address_get_port (address);
+ if (port == 22)
+ return g_strdup (g_network_address_get_hostname (address));
+ return g_strdup_printf ("[%s]:%u", hostname, port);
}
-static gboolean
-sync_extradb_to_model (HotSshHostDB *self,
- const char *groupname,
- const char *hostname,
- GtkTreeIter *iter)
+static void
+mark_all_entries_unknown (HotSshHostDB *self)
{
- G_GNUC_UNUSED HotSshHostDBPrivate *priv = hotssh_hostdb_get_instance_private (self);
- guint64 last_used;
- gs_free char *username = NULL;
- GError *temp_error = NULL;
+ GtkTreeIter iter;
- last_used = g_key_file_get_uint64 (priv->extradb, groupname, "last-used", &temp_error);
- if (temp_error)
- {
- g_clear_error (&temp_error);
- return FALSE;
- }
- else
+ if (!gtk_tree_model_get_iter_first ((GtkTreeModel*)priv->model, &iter))
+ return;
+ while (TRUE)
{
- gtk_list_store_set (priv->model, iter,
- HOTSSH_HOSTDB_COLUMN_LAST_USED, last_used,
+ gtk_list_store_set (priv->model, &iter,
+ HOTSSH_HOSTDB_COLUMN_IS_KNOWN, FALSE,
-1);
- }
- username = g_key_file_get_string (priv->extradb, groupname, "username", NULL);
- if (username && username[0])
- {
- gtk_list_store_set (priv->model, iter,
- HOTSSH_HOSTDB_COLUMN_USERNAME, username,
- -1);
+ if (!gtk_tree_model_iter_next ((GtkTreeModel*)priv->model, iter))
+ break;
}
- return TRUE;
}
static void
-merge_databases (HotSshHostDB *self)
+mark_all_entries_known_by_address (HotSshHostDB *self,
+ const char *hostname,
+ guint port)
{
- G_GNUC_UNUSED HotSshHostDBPrivate *priv = hotssh_hostdb_get_instance_private (self);
- gs_strfreev char **extradb_groups = NULL;
- gs_unref_hashtable GHashTable *known_hosts
- = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
- char **strviter;
GtkTreeIter iter;
-
+
if (!gtk_tree_model_get_iter_first ((GtkTreeModel*)priv->model, &iter))
return;
while (TRUE)
{
- gs_free char *hostname = NULL;
- gs_free char *section = NULL;
- gs_free char *username = NULL;
+ gs_free char *model_hostname = NULL;
+ guint model_port;
gboolean is_known = FALSE;
- gboolean remove = FALSE;
gtk_tree_model_get ((GtkTreeModel*)priv->model, &iter,
- HOTSSH_HOSTDB_COLUMN_HOSTNAME, &hostname,
+ HOTSSH_HOSTDB_COLUMN_HOSTNAME, &model_hostname,
+ HOTSSH_HOSTDB_COLUMN_PORT, &model_port,
HOTSSH_HOSTDB_COLUMN_IS_KNOWN, &is_known,
-1);
- if (is_known)
- g_hash_table_add (known_hosts, g_strdup (hostname));
-
- section = g_strdup_printf ("host \"%s\"", hostname);
- if (!sync_extradb_to_model (self, section, hostname, &iter))
- {
- if (!is_known)
- remove = TRUE;
- }
-
- if (remove)
- {
- if (!gtk_list_store_remove (priv->model, &iter))
- break;
- }
- else
- {
- if (!gtk_tree_model_iter_next ((GtkTreeModel*)priv->model, &iter))
- break;
- }
- }
-
- extradb_groups = g_key_file_get_groups (priv->extradb, NULL);
- for (strviter = extradb_groups; strviter && *strviter; strviter++)
- {
- const char *group = *strviter;
- gs_free char *hostname = NULL;
-
- hostname = host_group_key_to_host (group);
- if (!hostname)
- continue;
-
- if (!g_hash_table_contains (known_hosts, hostname))
+ if (!is_known &&
+ g_ascii_strcasecmp (hostname, model_hostname) == 0 &&
+ port == model_port)
{
- gtk_list_store_append (priv->model, &iter);
gtk_list_store_set (priv->model, &iter,
- HOTSSH_HOSTDB_COLUMN_HOSTNAME, hostname,
- HOTSSH_HOSTDB_COLUMN_IS_KNOWN, FALSE,
+ HOTSSH_HOSTDB_COLUMN_IS_KNOWN, TRUE,
-1);
- (void) sync_extradb_to_model (self, group, hostname, &iter);
}
+
+ if (!gtk_tree_model_iter_next ((GtkTreeModel*)priv->model, iter))
+ break;
}
}
@@ -214,12 +141,16 @@ on_knownhosts_changed (GFileMonitor *monitor,
&local_error))
goto out;
- gtk_list_store_clear (priv->model);
-
+ mark_all_entries_unknown (self);
+
+ g_hash_table_remove_all (priv->openssh_knownhosts);
+
iter = contents;
while (TRUE)
{
gs_strfreev char **parts = NULL;
+ GNetworkAddress *address_obj = NULL;
+ gs_free char *address_str = NULL;
char *comma;
eol = strchr (iter, '\n');
@@ -240,12 +171,17 @@ on_knownhosts_changed (GFileMonitor *monitor,
comma = strchr (parts[0], ',');
if (comma)
*comma = '\0';
- gtk_list_store_append (priv->model, &modeliter);
- gtk_list_store_set (priv->model, &modeliter,
- HOTSSH_HOSTDB_COLUMN_HOSTNAME, parts[0],
- HOTSSH_HOSTDB_COLUMN_LAST_USED, 0,
- HOTSSH_HOSTDB_COLUMN_IS_KNOWN, TRUE,
- -1);
+
+ address_obj = g_network_address_parse (parts[0], 22, NULL);
+ if (!address_obj)
+ goto next;
+ address_str = address_to_string (address_obj);
+
+ mark_all_entries_known_by_address (self, host, port);
+
+ g_hash_table_insert (priv->openssh_knownhosts, address_str, parts);
+ address_str = NULL;
+ parts = NULL;
next:
if (eol)
@@ -256,7 +192,7 @@ on_knownhosts_changed (GFileMonitor *monitor,
g_debug ("Read %d known hosts", gtk_tree_model_iter_n_children ((GtkTreeModel*)priv->model, NULL));
- if (priv->extradb)
+ if (priv->hostdb)
merge_databases (self);
out:
@@ -268,21 +204,65 @@ on_knownhosts_changed (GFileMonitor *monitor,
}
}
+static gboolean
+set_row_from_group (HotSshHostDB *self,
+ const char *groupname,
+ GtkTreeIter *iter)
+{
+ G_GNUC_UNUSED HotSshHostDBPrivate *priv = hotssh_hostdb_get_instance_private (self);
+ gs_free char *address = NULL;
+ gs_free char *username = NULL;
+ gs_free char *port_str = NULL;
+ gint64 last_used;
+ int port;
+ gboolean is_known;
+ GError *temp_error = NULL;
+
+ last_used = g_key_file_get_uint64 (priv->hostdb, groupname, "last-used", &temp_error);
+ if (temp_error)
+ {
+ g_clear_error (&temp_error);
+ return FALSE;
+ }
+
+ gtk_list_store_set (priv->model, iter,
+ HOTSSH_HOSTDB_COLUMN_LAST_USED, last_used,
+ -1);
+
+ username = g_key_file_get_string (priv->hostdb, groupname, "username", NULL);
+ if (!(username && username[0]))
+ return FALSE;
+
+ address = g_key_file_get_string (priv->hostdb, groupname, "address", NULL);
+ if (!(address && address[0]))
+ return FALSE;
+
+ port = g_key_file_get_integer (priv->hostdb, groupname, "port", NULL);
+ if (port <= 0 || port > G_MAXUINT16)
+ port = 22;
+
+ is_known = g_hash_table_contains (priv->openssh_knownhosts, address);
+
+ gtk_list_store_set (priv->model, &iter,
+ HOTSSH_HOSTDB_COLUMN_ID, groupname,
+ HOTSSH_HOSTDB_COLUMN_USERNAME, username,
+ HOTSSH_HOSTDB_COLUMN_ADDRESS, address,
+ HOTSSH_HOSTDB_COLUMN_PORT, (guint)port,
+ HOTSSH_HOSTDB_COLUMN_IS_KNOWN, is_known,
+ -1);
+}
+
static void
-on_extradb_changed (GFileMonitor *monitor,
- GFile *src,
- GFile *other,
- GFileMonitorEvent event,
- gpointer user_data)
+load_hostdb (HotSshHostDB *self)
{
- HotSshHostDB *self = user_data;
G_GNUC_UNUSED HotSshHostDBPrivate *priv = hotssh_hostdb_get_instance_private (self);
+ gs_strfreev char **hostdb_groups = NULL;
GError *local_error = NULL;
- g_clear_pointer (&priv->extradb, g_key_file_unref);
- priv->extradb = g_key_file_new ();
+ g_clear_pointer (&priv->hostdb, g_key_file_unref);
+ priv->hostdb = g_key_file_new ();
- if (!g_key_file_load_from_file (priv->extradb, gs_file_get_path_cached (priv->hotssh_extradb), 0,
&local_error))
+ if (!g_key_file_load_from_file (priv->hostdb, gs_file_get_path_cached (priv->hotssh_hostdb_path), 0,
&local_error))
{
if (g_error_matches (local_error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
g_clear_error (&local_error);
@@ -290,8 +270,20 @@ on_extradb_changed (GFileMonitor *monitor,
goto out;
}
- if (priv->extradb)
- merge_databases (self);
+ hostdb_groups = g_key_file_get_groups (priv->hostdb, NULL);
+ for (strviter = hostdb_groups; strviter && *strviter; strviter++)
+ {
+ const char *group = *strviter;
+
+ if (!g_str_has_prefix (group, "entry "))
+ continue;
+
+ gtk_list_store_append (priv->model, &iter);
+ if (!set_row_from_group (self, group, &iter))
+ {
+ gtk_list_store_remove (priv->model, &iter);
+ }
+ }
out:
if (local_error)
@@ -302,53 +294,8 @@ on_extradb_changed (GFileMonitor *monitor,
}
}
-static gboolean
-hostname_to_iter (HotSshHostDB *self,
- const char *hostname,
- GtkTreeIter *iter)
-{
- G_GNUC_UNUSED HotSshHostDBPrivate *priv = hotssh_hostdb_get_instance_private (self);
-
- if (!gtk_tree_model_get_iter_first ((GtkTreeModel*)priv->model, iter))
- return FALSE;
-
- while (TRUE)
- {
- gs_free char *model_hostname = NULL;
-
- gtk_tree_model_get ((GtkTreeModel*)priv->model, iter,
- HOTSSH_HOSTDB_COLUMN_HOSTNAME, &model_hostname,
- -1);
-
- if (g_ascii_strcasecmp (hostname, model_hostname) == 0)
- return TRUE;
-
- if (!gtk_tree_model_iter_next ((GtkTreeModel*)priv->model, iter))
- break;
- }
-
- return FALSE;
-}
-
static void
-get_or_create_host_in_db (HotSshHostDB *self,
- const char *hostname,
- GtkTreeIter *iter)
-{
- G_GNUC_UNUSED HotSshHostDBPrivate *priv = hotssh_hostdb_get_instance_private (self);
-
- if (hostname_to_iter (self, hostname, iter))
- return;
-
- gtk_list_store_append (priv->model, iter);
- gtk_list_store_set (priv->model, iter,
- HOTSSH_HOSTDB_COLUMN_HOSTNAME, hostname,
- HOTSSH_HOSTDB_COLUMN_IS_KNOWN, FALSE,
- -1);
-}
-
-static void
-on_replace_extradb_contents_complete (GObject *src,
+on_replace_hostdb_contents_complete (GObject *src,
GAsyncResult *result,
gpointer user_data)
{
@@ -356,75 +303,152 @@ on_replace_extradb_contents_complete (GObject *src,
G_GNUC_UNUSED HotSshHostDBPrivate *priv = hotssh_hostdb_get_instance_private (self);
GError *local_error = NULL;
- priv->idle_save_extradb_id = 0;
+ priv->idle_save_hostdb_id = 0;
if (!g_file_replace_contents_finish ((GFile*)src, result, NULL, &local_error))
goto out;
out:
- g_clear_pointer (&priv->new_extradb_contents, g_free);
+ g_clear_pointer (&priv->new_hostdb_contents, g_free);
if (local_error)
{
g_warning ("Failed to save '%s': %s",
- gs_file_get_path_cached (priv->hotssh_extradb),
+ gs_file_get_path_cached (priv->hotssh_hostdb_path),
local_error->message);
g_clear_error (&local_error);
}
}
static gboolean
-idle_save_extradb (gpointer user_data)
+idle_save_hostdb (gpointer user_data)
{
HotSshHostDB *self = user_data;
G_GNUC_UNUSED HotSshHostDBPrivate *priv = hotssh_hostdb_get_instance_private (self);
gsize len;
- priv->new_extradb_contents = g_key_file_to_data (priv->extradb, &len, NULL);
- g_assert (priv->new_extradb_contents);
+ priv->new_hostdb_contents = g_key_file_to_data (priv->hostdb, &len, NULL);
+ g_assert (priv->new_hostdb_contents);
- g_file_replace_contents_async (priv->hotssh_extradb, priv->new_extradb_contents, len, NULL,
+ g_file_replace_contents_async (priv->hotssh_hostdb_path, priv->new_hostdb_contents, len, NULL,
FALSE, 0, NULL,
- on_replace_extradb_contents_complete, self);
+ on_replace_hostdb_contents_complete, self);
return FALSE;
}
static void
-queue_save_extradb (HotSshHostDB *self)
+queue_save_hostdb (HotSshHostDB *self)
{
G_GNUC_UNUSED HotSshHostDBPrivate *priv = hotssh_hostdb_get_instance_private (self);
- if (priv->idle_save_extradb_id > 0)
+ if (priv->idle_save_hostdb_id > 0)
return;
- priv->idle_save_extradb_id = g_timeout_add_seconds (5, idle_save_extradb, self);
+ priv->idle_save_hostdb_id = g_timeout_add_seconds (5, idle_save_hostdb, self);
+}
+
+static void
+parse_uri (SoupURI *uri,
+ const char **out_host,
+ const char **out_user,
+ guint *out_port)
+{
+ g_assert_cmpstr ("ssh", ==, soup_uri_get_scheme (uri));
+ *out_host = soup_uri_get_host (uri);
+ *out_user = soup_uri_get_user (uri);
+ if (!*out_user)
+ *out_user = g_get_user_name ();
+ *out_port = soup_uri_get_port (uri);
+}
+
+static void
+append_randword (GString *buf)
+{
+ guint i;
+ for (i = 0; i < 4; i++)
+ g_string_append_printf (buf, "%X", (guint8) g_random_int_range (0, 256));
+}
+
+static char *
+allocate_groupname (HotSshHostDB *self)
+{
+ GString *buf = g_string_new ("entry ");
+ char *ret;
+ guint i;
+
+ for (i = 0; i < 2; i++)
+ append_randword (buf);
+ g_string_append_c (buf, '-');
+ for (i = 0; i < 3; i++)
+ {
+ append_randword (buf);
+ g_string_append_c (buf, '-');
+ }
+ for (i = 0; i < 3; i++)
+ append_randword (buf);
+
+ return g_string_free (buf, FALSE);
+}
+
+static void
+set_group_values (HotSshHostDB *self,
+ const char *groupname,
+ const char *username,
+ GNetworkAddress *address)
+{
+ guint port = g_network_address_get_port (address);
+ g_key_file_set_string (self->hostdb, groupname, "username",
+ username ? username : g_get_user_name ());
+ g_key_file_set_string (self->hostdb, groupname, "hostname",
+ g_network_address_get_hostname (address));
+ if (port != 22)
+ g_key_file_set_integer (self->hostdb, groupname, "port", port);
}
void
-hotssh_hostdb_host_used (HotSshHostDB *self,
- const char *hostname)
+hotssh_hostdb_add_entry (HotSshHostDB *self,
+ const char *username,
+ GNetworkAddress *address,
+ GtkTreeIter *out_iter)
{
G_GNUC_UNUSED HotSshHostDBPrivate *priv = hotssh_hostdb_get_instance_private (self);
GtkTreeIter iter;
- gs_free char *groupname = g_strdup_printf ("host \"%s\"", hostname);
+ gs_free char *groupname = allocate_groupname (self);
- get_or_create_host_in_db (self, hostname, &iter);
+ set_group_values (self, groupname, username, address);
- g_key_file_set_uint64 (priv->extradb, groupname, "last-used", g_get_real_time () / G_USEC_PER_SEC);
- queue_save_extradb (self);
+ gtk_list_store_append (priv->model, &iter);
+ (void) set_row_from_group (self, groupname, &iter);
+ queue_save_hostdb (self);
}
void
-hotssh_hostdb_set_username (HotSshHostDB *self,
- const char *hostname,
- const char *username)
+hotssh_hostdb_set_entry_basic (HotSshHostDB *self,
+ GtkTreeIter *iter,
+ const char *username,
+ GNetworkAddress *address)
{
- G_GNUC_UNUSED HotSshHostDBPrivate *priv = hotssh_hostdb_get_instance_private (self);
- GtkTreeIter iter;
- gs_free char *groupname = g_strdup_printf ("host \"%s\"", hostname);
+ gs_free char *groupname = NULL;
+ gtk_tree_model_get ((GtkTreeModel*)priv->model, iter,
+ HOTSSH_HOSTDB_COLUMN_ID, &groupname,
+ -1);
+ set_group_values (self, groupname, username, address);
+ (void) set_row_from_group (self, groupname, &iter);
+ queue_save_hostdb (self);
+}
- get_or_create_host_in_db (self, hostname, &iter);
+void
+hotssh_hostdb_set_entry_known (HotSshHostDB *self,
+ GtkTreeIter *iter,
+ gboolean known)
+{
+ gs_free char *groupname = NULL;
+ gboolean is_known;
- g_key_file_set_string (priv->extradb, groupname, "username", username);
+ gtk_tree_model_get ((GtkTreeModel*)priv->model, iter,
+ HOTSSH_HOSTDB_COLUMN_ID, &groupname,
+ HOTSSH_HOSTDB_COLUMN_IS_KNOWN, &is_known,
+ -1);
- queue_save_extradb (self);
+ if (is_known == known)
+ return;
}
static GFileMonitor *
@@ -458,13 +482,22 @@ hotssh_hostdb_init (HotSshHostDB *self)
gs_free char *knownhosts_path = NULL;
gs_free char *openssh_path = NULL;
gs_free char *hotssh_config_dir = NULL;
- gs_free char *hotssh_extradb_path = NULL;
-
- priv->model = gtk_list_store_new (4, G_TYPE_STRING, G_TYPE_UINT64, G_TYPE_BOOLEAN,
- G_TYPE_STRING);
+ gs_free char *hotssh_hostdb_path = NULL;
+
+ priv->model = gtk_list_store_new (HOTSSH_HOSTDB_N_COLUMNS,
+ G_TYPE_STRING, /* id */
+ G_TYPE_STRING, /* hostname */
+ G_TYPE_UINT32, /* port */
+ G_TYPE_STRING, /* username */
+ G_TYPE_UINT64, /* last-used */
+ G_TYPE_BOOLEAN /* is-known */
+ );
homedir = g_get_home_dir ();
g_assert (homedir);
+ priv->openssh_knownhosts = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, (GDestroyNotify)g_strfreev);
+
openssh_path = g_build_filename (homedir, ".ssh", NULL);
knownhosts_path = g_build_filename (openssh_path, "known_hosts", NULL);
@@ -473,8 +506,8 @@ hotssh_hostdb_init (HotSshHostDB *self)
hotssh_config_dir = g_build_filename (g_get_user_config_dir (), "hotssh", NULL);
(void) g_mkdir_with_parents (hotssh_config_dir, 0700);
- hotssh_extradb_path = g_build_filename (hotssh_config_dir, "hostdb.ini", NULL);
- priv->hotssh_extradb = g_file_new_for_path (hotssh_extradb_path);
+ hotssh_hostdb_path = g_build_filename (hotssh_config_dir, "hostdb.ini", NULL);
+ priv->hotssh_hostdb_path = g_file_new_for_path (hotssh_hostdb_path);
if (!g_file_query_exists (priv->openssh_dir, NULL))
{
@@ -486,11 +519,10 @@ hotssh_hostdb_init (HotSshHostDB *self)
}
}
+ load_hostdb (self);
+
priv->knownhosts_monitor = monitor_file_bind_noerror (self, priv->openssh_knownhosts_path,
on_knownhosts_changed);
-
- priv->hotssh_extradb_monitor = monitor_file_bind_noerror (self, priv->hotssh_extradb,
- on_extradb_changed);
}
static void
@@ -498,7 +530,8 @@ hotssh_hostdb_dispose (GObject *object)
{
HotSshHostDBPrivate *priv = hotssh_hostdb_get_instance_private ((HotSshHostDB*)object);
- g_clear_pointer (&priv->extradb, g_key_file_unref);
+ g_clear_pointer (&priv->hostdb, g_key_file_unref);
+ g_clear_pointer (&priv->openssh_knownhosts_path, g_hash_table_unref);
g_clear_object (&priv->model);
G_OBJECT_CLASS (hotssh_hostdb_parent_class)->dispose (object);
diff --git a/src/hotssh-hostdb.h b/src/hotssh-hostdb.h
index 217834d..60d7fdf 100644
--- a/src/hotssh-hostdb.h
+++ b/src/hotssh-hostdb.h
@@ -28,14 +28,31 @@
typedef struct _HotSshHostDB HotSshHostDB;
typedef struct _HotSshHostDBClass HotSshHostDBClass;
+enum {
+ HOTSSH_HOSTDB_COLUMN_ID,
+ HOTSSH_HOSTDB_COLUMN_HOSTNAME,
+ HOTSSH_HOSTDB_COLUMN_PORT,
+ HOTSSH_HOSTDB_COLUMN_USERNAME,
+ HOTSSH_HOSTDB_COLUMN_LAST_USED,
+ HOTSSH_HOSTDB_COLUMN_IS_KNOWN
+};
+#define HOTSSH_HOSTDB_N_COLUMNS (HOTSSH_HOSTDB_COLUMN_IS_KNOWN+1)
+
GType hotssh_hostdb_get_type (void);
HotSshHostDB *hotssh_hostdb_get_instance (void);
GtkTreeModel *hotssh_hostdb_get_model (HotSshHostDB *self);
-void hotssh_hostdb_host_used (HotSshHostDB *self,
- const char *hostname);
-void hotssh_hostdb_set_username (HotSshHostDB *self,
- const char *hostname,
- const char *username);
+void hotssh_hostdb_add_entry (HotSshHostDB *self,
+ const char *username,
+ GNetworkAddress *address,
+ GtkTreeIter *out_iter);
+
+void hotssh_hostdb_set_entry_basic (HotSshHostDB *self,
+ GtkTreeIter *iter,
+ const char *username,
+ GNetworkAddress *address);
+void hotssh_hostdb_set_entry_known (HotSshHostDB *self,
+ GtkTreeIter *iter,
+ gboolean known);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]