/* This file is part of GNUnet (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNUnet 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 General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file src/setup/gnunet-setup-gns.c * @author Christian Grothoff * @brief everything releated to the main GNS zone tree view */ #include "gnunet_gtk.h" #include "gnunet-gns-gtk.h" /** * Columns in the gns model. */ enum GNSTreestoreColumn { /** * A gchararray */ GNS_TREESTORE_COL_NAME = 0, /** * A gboolean */ GNS_TREESTORE_COL_IS_PUBLIC, /** * A guint */ GNS_TREESTORE_COL_RECORD_TYPE, /** * A gchararray */ GNS_TREESTORE_COL_RECORD_TYPE_AS_STR, /** * A guint64 */ GNS_TREESTORE_COL_EXP_TIME, /** * A gboolean */ GNS_TREESTORE_COL_EXP_TIME_IS_REL, /** * A gchararray */ GNS_TREESTORE_COL_EXP_TIME_AS_STR, /** * A gchararray */ GNS_TREESTORE_COL_VAL_AS_STR, /** * A gchararray */ GNS_TREESTORE_COL_VAL_COLOR, /** * A gboolean */ GNS_TREESTORE_COL_NAME_IS_VISIBLE, /** * A gboolean */ GNS_TREESTORE_COL_IS_RECORD_ROW, /** * A gboolean */ GNS_TREESTORE_COL_NOT_DUMMY_ROW, /** * A gchararray */ GNS_TREESTORE_COL_EXP_TIME_COLOR, /** * A gchararray */ GNS_TREESTORE_COL_NAME_COLOR }; /** * Columns in the gns type model. */ enum LIST_COLUMNS { /** * A guint */ GNS_TYPE_TO_NAME_LISTSTORE_COLUMN_TYPE = 0, /** * A gchararray */ GNS_TYPE_TO_NAME_LISTSTORE_COLUMN_TYPENAME }; /** * */ struct UpdateContext { /** * */ struct GNUNET_GNS_Context *gns; /** * */ struct GNUNET_NAMESTORE_RecordData *rd; /** * */ char * name; /** * */ unsigned int rd_count; }; /** * Name of our zone as a string. */ static char *zone_as_string; /** * Default directory of zone files as a string. */ static char *zonekey_directory; struct GNUNET_GNS_Context { /** * Handle to the namestore. */ struct GNUNET_NAMESTORE_Handle *ns; GtkCheckMenuItem *shorten_menu; GtkTreeStore *ts; GtkListStore *ls; GtkTreeModel *tm; GtkTreeView *tv; struct GNUNET_CRYPTO_RsaPrivateKey *pkey; struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pubkey; struct GNUNET_CRYPTO_ShortHashCode zone; int iteration; }; static void check_name_validity_and_commit_remove_proc (void *cls, int32_t success, const char *emsg) { struct UpdateContext * uc = cls; unsigned int c; if ((GNUNET_OK == success) || (GNUNET_NO == success)) { for (c = 0; c < uc->rd_count; c++) { GNUNET_NAMESTORE_record_create(uc->gns->ns, uc->gns->pkey, uc->name, &uc->rd[c],NULL, NULL); GNUNET_free ((void *) uc->rd[c].data); } GNUNET_free (uc->rd); GNUNET_free (uc->name); GNUNET_free (uc); } else if (GNUNET_SYSERR == success) { for (c = 0; c < uc->rd_count; c++) GNUNET_free ((void *) uc->rd[c].data); GNUNET_free (uc->rd); GNUNET_free (uc->name); GNUNET_free (uc); } else { GNUNET_break (0); GNUNET_free (uc); } } static void check_name_validity_and_commit (struct GNUNET_GNS_Context *gns, gchar *path, char * oldname) { GtkTreeIter it; GtkTreeIter parent; int records; int children; int append_pseu; int c; int valid = GNUNET_YES; char * name; void * data; size_t data_size; const gchar * pseu; char *n_name; int n_type; gboolean n_public; char *n_exp_color; guint64 n_exp_time; char *n_exp_str; gboolean n_is_relative; char *n_value; char *n_value_color; gtk_tree_model_get_iter_from_string(gns->tm, &it, path); if (FALSE == gtk_tree_model_iter_parent (gns->tm, &parent, &it)) parent = it; children = gtk_tree_model_iter_n_children (gns->tm, &parent); if (children < 1) { return; } gtk_tree_model_get(gns->tm, &parent, GNS_TREESTORE_COL_NAME, &name, -1); if (0 == strcmp (name, ROOT_STR)) { /* We have to append PSEU RECORD */ append_pseu = GNUNET_YES; records = children + 1; } else { append_pseu = GNUNET_NO; records = children; } struct GNUNET_NAMESTORE_RecordData *rd = GNUNET_malloc (records * sizeof (struct GNUNET_NAMESTORE_RecordData)); if (FALSE == gtk_tree_model_iter_children (gns->tm, &it, &parent)) return; for (c = 0; c < children; c++) { gtk_tree_model_get(gns->tm, &it, GNS_TREESTORE_COL_NAME, &n_name, GNS_TREESTORE_COL_RECORD_TYPE, &n_type, GNS_TREESTORE_COL_IS_PUBLIC, &n_public, GNS_TREESTORE_COL_EXP_TIME_COLOR, &n_exp_color, GNS_TREESTORE_COL_EXP_TIME, &n_exp_time, GNS_TREESTORE_COL_EXP_TIME_IS_REL, &n_is_relative, GNS_TREESTORE_COL_EXP_TIME_AS_STR, &n_exp_str, GNS_TREESTORE_COL_VAL_AS_STR, &n_value, GNS_TREESTORE_COL_VAL_COLOR, &n_value_color, -1); /* valid name */ if (NULL == n_name) valid = GNUNET_NO; else { if (GNUNET_SYSERR == GNUNET_NAMESTORE_check_name (n_name)) valid = GNUNET_NO; } /* valid record type */ if (0 == n_type) valid = GNUNET_NO; /* valid expiration */ if ((n_exp_color != NULL) || (NULL == n_exp_str) || (0 == n_exp_time)) valid = GNUNET_NO; /* valid value */ if ((n_value_color != NULL) || (NULL == n_value)) valid = GNUNET_NO; if (NULL != n_value) { if (GNUNET_OK != GNUNET_NAMESTORE_string_to_value(n_type, n_value, &data, &data_size)) valid = GNUNET_NO; } if (GNUNET_YES == valid) { if (FALSE == n_public) rd[c].flags = GNUNET_NAMESTORE_RF_AUTHORITY | GNUNET_NAMESTORE_RF_PRIVATE; else rd[c].flags = GNUNET_NAMESTORE_RF_AUTHORITY | GNUNET_NAMESTORE_RF_NONE; rd[c].record_type = n_type; rd[c].expiration_time = n_exp_time; rd[c].data_size = data_size; rd[c].data = GNUNET_malloc(data_size); memcpy ((void *) rd[c].data, data, data_size); } g_free (n_name); g_free (n_exp_color); g_free (n_exp_str); g_free (n_value); g_free (n_value_color); if (FALSE == gtk_tree_model_iter_next (gns->tm, &it)) break; } if (GNUNET_NO == valid) { for (c = 0; c < children; c++) GNUNET_free_non_null ((void *) rd[c].data); GNUNET_free_non_null (rd); } else { if (GNUNET_YES == append_pseu) { GNUNET_assert (children == (records -1)); /* Append PSEU record */ GtkEntry * entry = GTK_ENTRY (gtk_builder_get_object (gns->builder, "GNUNET_GNS_GTK_pseu_entry")); pseu = gtk_entry_get_text (GTK_ENTRY(entry)); if ((NULL != pseu) && (0 != strcmp (PSEU_EMPTY_STR, pseu)) && (0 != strcmp ("", pseu))) { if (GNUNET_OK != GNUNET_NAMESTORE_string_to_value(GNUNET_NAMESTORE_TYPE_PSEU, pseu, (void **) &rd[records - 1].data, &rd[records - 1].data_size)) { GNUNET_break (0); for (c = 0; c < records; c++) GNUNET_free_non_null ((void *) rd[c].data); GNUNET_free_non_null (rd); } rd[records - 1].record_type = GNUNET_NAMESTORE_TYPE_PSEU; rd[records - 1].expiration_time = UINT64_MAX; rd[records - 1].flags = GNUNET_NAMESTORE_RF_AUTHORITY | GNUNET_NAMESTORE_RF_NONE; } else { GNUNET_break (0); } } /* Remove old entries */ struct UpdateContext * uc = GNUNET_malloc (sizeof (struct UpdateContext)); uc->gns = gns; uc->rd = rd; uc->rd_count = records; uc->name = strdup (name); if (oldname != NULL) GNUNET_NAMESTORE_record_remove(gns->ns, gns->pkey, oldname, NULL, &check_name_validity_and_commit_remove_proc, uc); else GNUNET_NAMESTORE_record_remove(gns->ns, gns->pkey, name, NULL, &check_name_validity_and_commit_remove_proc, uc); g_free (name); } } /** * */ struct Remove_Context { /** * */ struct GNUNET_GNS_Context *gns; /** * */ char *path; }; static void check_name_validity_and_remove_proc (void *cls, int32_t success, const char *emsg) { struct Remove_Context *rcc = cls; GtkDialog *dialog; GtkTreeIter it; if (GNUNET_SYSERR == success) { char * message = _("Record could not be deleted:"); dialog = GTK_DIALOG(gtk_message_dialog_new (GTK_WINDOW (rcc->gns->main_window), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, _("%s\n%s\n"), message, emsg)); g_signal_connect (dialog, "response", G_CALLBACK (gtk_widget_destroy), rcc->gns); gtk_widget_show_all (GTK_WIDGET(dialog)); } else { gtk_tree_model_get_iter_from_string(rcc->gns->tm, &it, rcc->path); gtk_tree_store_remove (rcc->gns->ts, &it); } GNUNET_free (rcc->path); GNUNET_free (rcc); } static void check_name_validity_and_remove (struct GNUNET_GNS_Context *gns, gchar *path) { GtkTreeIter it; GtkTreeIter parent; char *name; int valid = GNUNET_YES; struct GNUNET_NAMESTORE_RecordData rd; struct Remove_Context *rcc; char *n_name; int n_type; gboolean n_public; char *n_exp_color; guint64 n_exp_time; char *n_exp_str; gboolean n_is_relative; char *n_value; char *n_value_color; gtk_tree_model_get_iter_from_string(gns->tm, &it, path); gtk_tree_model_get(gns->tm, &it, GNS_TREESTORE_COL_NAME, &name, -1); if (TRUE == gtk_tree_model_iter_parent (gns->tm, &parent, &it)) { /* Removing a single record */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing single record for name `%s'\n", name); gtk_tree_model_get(gns->tm, &it, GNS_TREESTORE_COL_NAME, &n_name, GNS_TREESTORE_COL_RECORD_TYPE, &n_type, GNS_TREESTORE_COL_IS_PUBLIC, &n_public, GNS_TREESTORE_COL_EXP_TIME_COLOR, &n_exp_color, GNS_TREESTORE_COL_EXP_TIME, &n_exp_time, GNS_TREESTORE_COL_EXP_TIME_IS_REL, &n_is_relative, GNS_TREESTORE_COL_EXP_TIME_AS_STR, &n_exp_str, GNS_TREESTORE_COL_VAL_AS_STR, &n_value, GNS_TREESTORE_COL_VAL_COLOR, &n_value_color, -1); /* valid name */ if (NULL == n_name) valid = GNUNET_NO; /* valid record type */ if (0 == n_type) valid = GNUNET_NO; /* valid expiration */ if ((n_exp_color != NULL) || (NULL == n_exp_str) || (0 == n_exp_time)) valid = GNUNET_NO; /* valid value */ if ((n_value_color != NULL) || (NULL == n_value)) valid = GNUNET_NO; if (GNUNET_YES == valid) { if (FALSE == n_public) rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY | GNUNET_NAMESTORE_RF_PRIVATE; else rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY | GNUNET_NAMESTORE_RF_NONE; rd.record_type = n_type; rd.expiration_time = n_exp_time; rd.data_size = strlen (n_value) + 1; rd.data = GNUNET_malloc(rd.data_size); memcpy ((void *) rd.data, n_value, rd.data_size); rcc = GNUNET_malloc(sizeof (struct Remove_Context)); rcc->gns = gns; rcc->path = strdup (path); GNUNET_NAMESTORE_record_remove(gns->ns, gns->pkey, name, &rd, &check_name_validity_and_remove_proc, rcc); GNUNET_free ((void *) rd.data); } else { gtk_tree_model_get_iter_from_string(gns->tm, &it, path); gtk_tree_store_remove (gns->ts, &it); } g_free (n_name); g_free (n_exp_color); g_free (n_exp_str); g_free (n_value); g_free (n_value_color); } else if (0 != strcmp (name, ROOT_STR)) { /* Removing the whole name record */ rcc = GNUNET_malloc(sizeof (struct Remove_Context)); rcc->gns = gns; rcc->path = strdup (path); GNUNET_NAMESTORE_record_remove(gns->ns, gns->pkey, name, NULL, &check_name_validity_and_remove_proc, rcc); } g_free (name); } /** * The user has selected a new record type. Update the * model, possibly invalidating (marking 'red') the existing * value. * * @param renderer updated renderer * @param path the path identifying the edited cell * @param new_iter selected cell in the combo's model (with the record type) * @param user_data unused */ void GNUNET_GNS_GTK_type_cellrenderercombo_changed_cb (GtkCellRendererCombo *combo, gchar *path, GtkTreeIter *new_iter, gpointer user_data) { struct GNUNET_GNS_Context *gns = user_data; GtkTreeIter it; GtkTreeIter child; guint type; int record_row; char *type_str; char *value_str; char *name_str; void *data; size_t data_size; gtk_tree_model_get(GTK_TREE_MODEL(gns->ls), new_iter, 0, &type, -1); gtk_tree_model_get(GTK_TREE_MODEL(gns->ls), new_iter, GNS_TYPE_TO_NAME_LISTSTORE_COLUMN_TYPENAME, &type_str, -1); /* check if this is a new record */ gtk_tree_model_get_iter_from_string(gns->tm, &it, path); gtk_tree_model_get(gns->tm, &it, GNS_TREESTORE_COL_IS_RECORD_ROW, &record_row, -1); gtk_tree_model_get(gns->tm, &it, GNS_TREESTORE_COL_NAME, &name_str, -1); if (GNUNET_YES == record_row) { /* Updating an existing record */ gtk_tree_store_set(gns->ts, &it, GNS_TREESTORE_COL_RECORD_TYPE, type, GNS_TREESTORE_COL_RECORD_TYPE_AS_STR, type_str, -1); } else if ((NULL != name_str) && (0 != strcmp (NEW_NAME_STR, name_str))) { /* Adding a new record */ gtk_tree_store_insert_with_values(gns->ts, &child , &it, 0, GNS_TREESTORE_COL_NAME, name_str, GNS_TREESTORE_COL_NAME_IS_VISIBLE, FALSE, GNS_TREESTORE_COL_RECORD_TYPE, type, GNS_TREESTORE_COL_RECORD_TYPE_AS_STR, type_str, GNS_TREESTORE_COL_EXP_TIME_AS_STR, EXPIRE_NEVER_STRING, GNS_TREESTORE_COL_EXP_TIME, GNUNET_TIME_UNIT_FOREVER_ABS, GNS_TREESTORE_COL_EXP_TIME_IS_REL, FALSE, GNS_TREESTORE_COL_IS_RECORD_ROW, GNUNET_YES, GNS_TREESTORE_COL_NOT_DUMMY_ROW, GNUNET_YES, -1); gtk_tree_view_expand_row (gns->tv, gtk_tree_model_get_path(gns->tm, &it), 0); } GNUNET_free (type_str); /* check if value is still valid */ gtk_tree_model_get(gns->tm, &it, GNS_TREESTORE_COL_VAL_AS_STR, &value_str, -1); if (NULL != value_str) { if (GNUNET_OK != GNUNET_NAMESTORE_string_to_value (type, value_str, &data, &data_size)) gtk_tree_store_set (gns->ts, &it, GNS_TREESTORE_COL_VAL_COLOR, "red", -1); else gtk_tree_store_set (gns->ts, &it, GNS_TREESTORE_COL_VAL_COLOR, NULL, -1); GNUNET_free (value_str); } else if (NULL == value_str) { /* Empty value field */ if (GNUNET_YES == record_row) gtk_tree_store_set (gns->ts, &it, GNS_TREESTORE_COL_VAL_COLOR, "red", -1); else gtk_tree_store_set (gns->ts, &child, GNS_TREESTORE_COL_VAL_COLOR, "red", -1); } check_name_validity_and_commit (gns, path, NULL); GNUNET_free_non_null (name_str); } /** * The user has toggled the 'public' checkmark of a cell. Update the * model. * * @param renderer updated renderer * @param path the path identifying the edited cell * @param user_data unused */ void GNUNET_GNS_GTK_ispublic_cellrenderertoggle_toggled_cb (GtkCellRendererToggle *cell_renderer, gchar *path, gpointer user_data) { struct GNUNET_GNS_Context *gns = user_data; GtkTreeIter it; gboolean value; gtk_tree_model_get_iter_from_string(gns->tm, &it, path); gtk_tree_model_get(gns->tm, &it, GNS_TREESTORE_COL_IS_PUBLIC, &value, -1); gtk_tree_store_set(gns->ts, &it, GNS_TREESTORE_COL_IS_PUBLIC, !value, -1); check_name_validity_and_commit (gns, path, NULL); } static char * convert_time_to_string (struct GNUNET_TIME_Absolute t) { time_t tt; struct tm *time; char *ret; if (t.abs_value == GNUNET_TIME_UNIT_FOREVER_ABS.abs_value) return GNUNET_strdup (_(EXPIRE_NEVER_STRING)); if (t.abs_value == GNUNET_TIME_UNIT_ZERO_ABS.abs_value) return GNUNET_strdup (_(EXPIRE_INVALID_STRING)); tt = t.abs_value / 1000; time = localtime (&tt); GNUNET_asprintf(&ret, "%02u/%02u/%04u %02u:%02u",time->tm_mon, time->tm_mday, 1900 + time->tm_year, time->tm_hour, time->tm_min); return ret; } static int check_time (const char * text) { unsigned int t_mon; unsigned int t_day; unsigned int t_year; unsigned int t_hrs; unsigned int t_min; int count = SSCANF (text, "%02u/%02u/%04u %02u:%02u", &t_mon, &t_day, &t_year, &t_hrs, &t_min); if ((EOF == count) || (5 != count)) return GNUNET_SYSERR; if (t_mon > 12) return GNUNET_SYSERR; if (t_day > 31) return GNUNET_SYSERR; if (t_hrs > 24) return GNUNET_SYSERR; if (t_min > 59) return GNUNET_SYSERR; return GNUNET_OK; } static const struct GNUNET_TIME_Absolute convert_string_to_abs_time (const char * text) { static struct GNUNET_TIME_Absolute abs_t; struct tm time; time_t t; int t_mon; int t_day; int t_year; int t_hrs; int t_min; GNUNET_assert (NULL != text); if (0 == strcmp(text, EXPIRE_NEVER_STRING)) return GNUNET_TIME_UNIT_FOREVER_ABS; memset (&time, '\0', sizeof (struct tm)); if (GNUNET_SYSERR == check_time(text)) { GNUNET_break (0); return GNUNET_TIME_UNIT_ZERO_ABS; } int count = SSCANF (text, "%02d/%02d/%04d %02d:%02d", &t_mon, &t_day, &t_year, &t_hrs, &t_min); if ((EOF == count) || (5 != count)) return GNUNET_TIME_UNIT_ZERO_ABS; time.tm_mon = (t_mon - 1); time.tm_mday = t_day; time.tm_year = t_year - 1900; time.tm_hour = (t_hrs); time.tm_min = t_min; t = mktime (&time); if (-1 == t) return GNUNET_TIME_UNIT_ZERO_ABS; abs_t.abs_value = t * 1000; return abs_t; } /** * The user has edited a 'expiration' cell. Update the model. * * @param renderer updated renderer * @param path the path identifying the edited cell * @param new_text the new expiration time * @param user_data unused */ void GNUNET_GNS_GTK_expiration_cellrenderertext_edited_cb (GtkCellRendererText *renderer, gchar *path, gchar *new_text, gpointer user_data) { struct GNUNET_GNS_Context * gns = user_data; GtkTreeIter it; struct GNUNET_TIME_Absolute abstime; gboolean is_rel; char *old_text; if ((NULL != new_text)) { gtk_tree_model_get_iter_from_string(gns->tm, &it, path); gtk_tree_model_get(gns->tm, &it, GNS_TREESTORE_COL_EXP_TIME_AS_STR, &old_text, GNS_TREESTORE_COL_EXP_TIME_IS_REL, &is_rel, -1); if (0 == strcmp(new_text, old_text)) return; if ((0 == strcmp(new_text,"")) || (0 == strcmp(new_text,EXPIRE_NEVER_STRING))) { new_text = EXPIRE_NEVER_STRING; abstime = GNUNET_TIME_UNIT_FOREVER_ABS; } else { if (GNUNET_SYSERR == check_time(new_text)) { gtk_tree_store_set (gns->ts, &it, GNS_TREESTORE_COL_EXP_TIME_AS_STR, new_text, GNS_TREESTORE_COL_EXP_TIME_COLOR, "red", GNS_TREESTORE_COL_EXP_TIME, 0, -1); abstime = GNUNET_TIME_UNIT_ZERO_ABS; return; } /* TODO: fix this when we have relative time */ if (TRUE == is_rel) { abstime = convert_string_to_abs_time(new_text); } else { abstime = convert_string_to_abs_time(new_text); } } gtk_tree_store_set (gns->ts, &it, GNS_TREESTORE_COL_EXP_TIME_AS_STR, new_text, GNS_TREESTORE_COL_EXP_TIME, abstime.abs_value, GNS_TREESTORE_COL_EXP_TIME_COLOR, NULL, -1); check_name_validity_and_commit (gns, path, NULL); } } /** * The user has edited a 'value' cell. Update the model, * including the status on the consistency of the value with * the type. * * @param renderer updated renderer * @param path the path identifying the edited cell * @param new_text the new value * @param user_data unused */ void GNUNET_GNS_GTK_value_cellrenderertext_edited_cb (GtkCellRendererText *renderer, gchar *path, gchar *new_text, gpointer user_data) { struct GNUNET_GNS_Context *gns = user_data; GtkTreeModel *tm = GTK_TREE_MODEL(gns->ts); GtkTreeIter it; size_t data_size; void * data; int type; gchar * old_value; if (0 != strcmp(new_text,"")) { gtk_tree_model_get_iter_from_string(tm, &it, path); gtk_tree_model_get(tm, &it, GNS_TREESTORE_COL_RECORD_TYPE, &type, GNS_TREESTORE_COL_VAL_AS_STR, &old_value, -1); if (old_value != NULL) { if (0 == strcmp(new_text, old_value)) { GNUNET_free (old_value); return; } GNUNET_free (old_value); } if (GNUNET_OK == GNUNET_NAMESTORE_string_to_value (type, new_text, &data, &data_size)) { gtk_tree_store_set (gns->ts, &it, GNS_TREESTORE_COL_VAL_COLOR, NULL, -1); gtk_tree_store_set (gns->ts, &it, GNS_TREESTORE_COL_VAL_AS_STR, new_text, -1); check_name_validity_and_commit (gns, path, NULL); } else { gtk_tree_store_set (gns->ts, &it, GNS_TREESTORE_COL_VAL_COLOR, "red", -1); gtk_tree_store_set (gns->ts, &it, GNS_TREESTORE_COL_VAL_AS_STR, new_text, -1); } } } /** * The user has edited a 'name' cell. Update the model (and if needed * create another fresh line for additional records). * * @param renderer updated renderer * @param path the path identifying the edited cell * @param new_text the new name * @param user_data unused */ void GNUNET_GNS_GTK_name_cellrenderertext_edited_cb (GtkCellRendererText *renderer, gchar *path, gchar *new_text, gpointer user_data) { struct GNUNET_GNS_Context *gns = user_data; GtkTreeIter it; GtkTreeIter child; GtkTreeModel *tm = GTK_TREE_MODEL(gns->ts); int not_dummy; char *name; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "New text for `%s' is `%s'\n", path, new_text); if ((0 == strcmp (new_text, NEW_NAME_STR)) || (0 == strcmp (new_text, ""))) return; gtk_tree_model_get_iter_from_string(tm, &it, path); gtk_tree_model_get(tm, &it, GNS_TREESTORE_COL_NOT_DUMMY_ROW, ¬_dummy, -1); gtk_tree_model_get(tm, &it, GNS_TREESTORE_COL_NAME, &name, -1); if (not_dummy == GNUNET_NO) { /* update name */ gtk_tree_store_set (gns->ts, &it, GNS_TREESTORE_COL_NAME, new_text, GNS_TREESTORE_COL_RECORD_TYPE, 0, GNS_TREESTORE_COL_RECORD_TYPE_AS_STR, _(NEW_RECORD_STR), GNS_TREESTORE_COL_NOT_DUMMY_ROW, GNUNET_YES, -1); check_name_validity_and_commit (gns, gtk_tree_model_get_string_from_iter(gns->tm, &it), name); /* add a new dummy line */ gtk_tree_store_insert_with_values (gns->ts, &it,NULL, 0, GNS_TREESTORE_COL_NAME, _(NEW_NAME_STR), GNS_TREESTORE_COL_NAME_IS_VISIBLE, TRUE, GNS_TREESTORE_COL_RECORD_TYPE, 1, GNS_TREESTORE_COL_NOT_DUMMY_ROW, GNUNET_NO, GNS_TREESTORE_COL_IS_RECORD_ROW, GNUNET_NO, -1); } else { /* update name */ gtk_tree_store_set (gns->ts, &it, GNS_TREESTORE_COL_NAME, new_text, -1); if (TRUE == gtk_tree_model_iter_children (gns->tm, &child, &it)) { do { gtk_tree_store_set (gns->ts, &child, GNS_TREESTORE_COL_NAME, &new_text, -1); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "New text for `%s' is `%s'\n", path, new_text); } while (TRUE == gtk_tree_model_iter_next (gns->tm, &child)); } check_name_validity_and_commit (gns, gtk_tree_model_get_string_from_iter(gns->tm, &it), name); } if (GNUNET_SYSERR == GNUNET_NAMESTORE_check_name (new_text)) { gtk_tree_store_set (gns->ts, &it, GNS_TREESTORE_COL_NAME_COLOR, "red", -1); } else { gtk_tree_store_set (gns->ts, &it, GNS_TREESTORE_COL_NAME_COLOR, NULL, -1); } } /** * The zone treeview pop up menu is supposed to be created. * (Note: this is not the only method that might need to be * written to handle events to create pop up menus; right-clicks * might need to be managed separately). * * @param widget the widget * @param user_data unused * @return TRUE if a menu was activated */ gboolean GNUNET_GNS_GTK_main_treeview_popup_menu_cb (GtkWidget *widget, gpointer user_data) { struct GNUNET_GNS_Context *gns = user_data; GtkTreeModel *tm; GtkTreeIter it; GtkMenu *popup; GtkTreeSelection * ts; int not_dummy; ts = gtk_tree_view_get_selection(gns->tv); if (! gtk_tree_selection_get_selected (ts, &tm, &it)) return TRUE; gtk_tree_model_get(gns->tm, &it, GNS_TREESTORE_COL_NOT_DUMMY_ROW, ¬_dummy, -1); if (GNUNET_NO == not_dummy) return TRUE; popup = GTK_MENU(gtk_builder_get_object (gns->builder, "GNUNET_GNS_GTK_delete_popup_menu")); gtk_widget_show_all (GTK_WIDGET(popup)); gtk_menu_popup(popup, NULL, NULL, NULL, NULL, 0, 0); return TRUE; } static void set_relative_expiration_time (struct GNUNET_GNS_Context *gns, struct GNUNET_TIME_Relative reltime) { GtkTreeIter it; GtkTreeIter parent; GtkCellRendererText *renderer; GtkTreeModel *tm; GtkTreeSelection * ts = gtk_tree_view_get_selection(gns->tv); gboolean has_parent; struct GNUNET_TIME_Absolute abstime; char *path; int not_dummy; if (! gtk_tree_selection_get_selected (ts, &tm, &it)) return; gtk_tree_model_get(tm, &it, GNS_TREESTORE_COL_NOT_DUMMY_ROW, ¬_dummy, -1); if (GNUNET_NO == not_dummy) return; /* Has parent? */ has_parent = gtk_tree_model_iter_parent (tm, &parent, &it); if (FALSE == has_parent) return; abstime = GNUNET_TIME_absolute_add(GNUNET_TIME_absolute_get(), reltime); /* this is a single record */ renderer = GTK_CELL_RENDERER_TEXT((gtk_builder_get_object (gns->builder, "GNUNET_GNS_GTK_name_cellrenderertext"))); path = gtk_tree_model_get_string_from_iter (tm, &it); GNUNET_GNS_GTK_expiration_cellrenderertext_edited_cb (renderer, path, convert_time_to_string (abstime), gns); } gboolean GNUNET_GNS_GTK_main_treeview_popup_menu_exp1d_cb (GtkWidget *widget, gpointer user_data) { set_relative_expiration_time (user_data, GNUNET_TIME_UNIT_DAYS); return TRUE; } gboolean GNUNET_GNS_GTK_main_treeview_popup_menu_exp1w_cb (GtkWidget *widget, gpointer user_data) { set_relative_expiration_time (user_data, GNUNET_TIME_UNIT_WEEKS); return TRUE; } gboolean GNUNET_GNS_GTK_main_treeview_popup_menu_exp1y_cb (GtkWidget *widget, gpointer user_data) { set_relative_expiration_time (user_data, GNUNET_TIME_UNIT_YEARS); return TRUE; } gboolean GNUNET_GNS_GTK_main_treeview_popup_menu_expinf_cb (GtkWidget *widget, gpointer user_data) { set_relative_expiration_time (user_data, GNUNET_TIME_UNIT_FOREVER_REL); return TRUE; } gboolean GNUNET_GNS_GTK_main_treeview_button_press_popup_menu_cb (GtkWidget *widget, GdkEventButton *event, gpointer user_data) { /* Check for right click*/ if (NULL == widget) return FALSE; if (event->type == GDK_BUTTON_PRESS && event->button == 3) GNUNET_GNS_GTK_main_treeview_popup_menu_cb (widget, user_data); return FALSE; } gboolean GNUNET_GNS_GTK_main_treeview_key_press_popup_menu_cb (GtkWidget *widget, GdkEventKey *event, gpointer user_data) { /* Check for delete key */ if ((event->type == GDK_KEY_PRESS) && (GDK_KEY_Delete == event->keyval)) GNUNET_GNS_GTK_main_treeview_popup_menu_cb (widget, user_data); return FALSE; } struct ZoneIteration_Context { struct GNUNET_GNS_Context *gns; struct GNUNET_CRYPTO_ShortHashCode zone; struct GNUNET_NAMESTORE_ZoneIterator * it; char *label; }; void GNUNET_GNS_GTK_delete_popup_menu_delete_cb (GtkMenuItem *menuitem, gpointer user_data) { struct GNUNET_GNS_Context *gns = user_data; GtkTreeIter it; GtkTreeModel *tm; GtkTreeSelection * ts; int not_dummy; char *path; ts = gtk_tree_view_get_selection(gns->tv); if (gtk_tree_selection_get_selected (ts, &tm, &it)) { gtk_tree_model_get(tm, &it, GNS_TREESTORE_COL_NOT_DUMMY_ROW, ¬_dummy, -1); if (GNUNET_NO == not_dummy) return; /* do not delete the dummy line */ path = gtk_tree_model_get_string_from_iter (gns->tm, &it); check_name_validity_and_remove(gns, path); g_free (path); } } static void zone_iteration_proc (void *cls, const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key, struct GNUNET_TIME_Absolute expire, const char *name, unsigned int rd_count, const struct GNUNET_NAMESTORE_RecordData *rd, const struct GNUNET_CRYPTO_RsaSignature *signature) { struct ZoneIteration_Context * zc_ctx = cls; GtkTreeIter iter_name; GtkTreeIter iter_record; GtkEntry *pseu_entry; int c; int time_is_relative; char *exp; char *val; char * type_str; int public; guint64 exp_t; GNUNET_assert (zc_ctx != NULL); if ((NULL == zone_key) && (NULL == name)) { struct GNUNET_CRYPTO_ShortHashAsciiEncoded shenc; GNUNET_CRYPTO_short_hash_to_enc(&zc_ctx->zone, &shenc); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Zone `%s 'iteration done\n", &shenc); pseu_entry = GTK_ENTRY((gtk_builder_get_object (zc_ctx->gns->builder, "GNUNET_GNS_GTK_pseu_entry"))); if (zc_ctx->label == NULL) GNUNET_asprintf(&zc_ctx->label, "%s", PSEU_EMPTY_STR); gtk_entry_set_text (pseu_entry, zc_ctx->label); zc_ctx->gns->iteration = GNUNET_NO; GNUNET_free (zc_ctx->label); GNUNET_free (zc_ctx); return; } struct GNUNET_CRYPTO_ShortHashAsciiEncoded shenc; GNUNET_CRYPTO_short_hash_to_enc(&zc_ctx->zone, &shenc); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Zone `%s' iteration result `%s', %u records\n", &shenc, name, rd_count); GNUNET_assert(GTK_IS_TREE_STORE(zc_ctx->gns->ts)); gtk_tree_store_append(zc_ctx->gns->ts, &iter_name, NULL); gtk_tree_store_set(zc_ctx->gns->ts, &iter_name, GNS_TREESTORE_COL_NAME, name, GNS_TREESTORE_COL_NAME_IS_VISIBLE, TRUE, GNS_TREESTORE_COL_RECORD_TYPE, 0, GNS_TREESTORE_COL_RECORD_TYPE_AS_STR, _(NEW_RECORD_STR), GNS_TREESTORE_COL_IS_RECORD_ROW, GNUNET_NO, GNS_TREESTORE_COL_NOT_DUMMY_ROW, GNUNET_YES, -1); if (GNUNET_SYSERR == GNUNET_NAMESTORE_check_name (name)) { gtk_tree_store_set (zc_ctx->gns->ts, &iter_name, GNS_TREESTORE_COL_NAME_COLOR, "red", -1); } /* Append elements for records */ for (c = 0; c < rd_count; c ++) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Record %u: type %u flags %u expiration %llu data_size %u\n", c, rd[c].record_type, rd[c].flags, rd[c].expiration_time, rd[c].data_size); /* Set public toggle */ if ((rd[c].flags & GNUNET_NAMESTORE_RF_PRIVATE) == GNUNET_NAMESTORE_RF_PRIVATE) { public = GNUNET_NO; } else { public = GNUNET_YES; } /* Expiration time */ time_is_relative = GNUNET_NO; if (GNUNET_YES == time_is_relative) { /* TODO: FIX THIS WHEN WE HAVE RELATIVE TIME */ struct GNUNET_TIME_Relative rel_time = GNUNET_TIME_UNIT_ZERO; struct GNUNET_TIME_Absolute exp_abs; exp_abs = GNUNET_TIME_absolute_add(GNUNET_TIME_absolute_get(), rel_time); exp_t = exp_abs.abs_value; exp = convert_time_to_string (exp_abs); } else { struct GNUNET_TIME_Absolute exp_abs; exp_abs.abs_value = rd[c].expiration_time; exp_t = exp_abs.abs_value; exp = convert_time_to_string (exp_abs); } /* value */ val = GNUNET_NAMESTORE_value_to_string (rd[c].record_type, rd[c].data, rd[c].data_size); if (NULL == val) GNUNET_asprintf(&val, "%s", EXPIRE_INVALID_STRING); if (NULL != GNUNET_NAMESTORE_number_to_typename(rd[c].record_type)) type_str = strdup (GNUNET_NAMESTORE_number_to_typename(rd[c].record_type)); else GNUNET_asprintf(&type_str, "%s", EXPIRE_INVALID_STRING); if ((0 ==strcmp (name, ROOT_STR)) && (GNUNET_NAMESTORE_TYPE_PSEU == rd[c].record_type)) { zc_ctx->label = strdup(val); zc_ctx->gns->iteration = GNUNET_YES; } else { gtk_tree_store_insert_with_values(zc_ctx->gns->ts, &iter_record , &iter_name, 0, GNS_TREESTORE_COL_NAME, name, GNS_TREESTORE_COL_NAME_IS_VISIBLE, FALSE, GNS_TREESTORE_COL_RECORD_TYPE, rd[c].record_type, GNS_TREESTORE_COL_RECORD_TYPE_AS_STR, type_str, GNS_TREESTORE_COL_IS_PUBLIC, public, GNS_TREESTORE_COL_EXP_TIME, exp_t, GNS_TREESTORE_COL_EXP_TIME_AS_STR, exp, GNS_TREESTORE_COL_EXP_TIME_IS_REL, time_is_relative, GNS_TREESTORE_COL_VAL_AS_STR, val, GNS_TREESTORE_COL_IS_RECORD_ROW, GNUNET_YES, GNS_TREESTORE_COL_NOT_DUMMY_ROW, GNUNET_YES, -1); } GNUNET_free (type_str); GNUNET_free (exp); GNUNET_free (val); } GNUNET_NAMESTORE_zone_iterator_next(zc_ctx->it); } /** * The zone treeview was realized. Setup the model. * * @param widget the widget * @param user_data unused */ void GNUNET_GNS_GTK_main_treeview_realize_cb (GtkWidget *widget, gpointer user_data) { struct GNUNET_GNS_Context *gns = user_data; struct ZoneIteration_Context *zc_ctx; GtkTreeIter toplevel; /* Append a top level row and leave it empty */ gtk_tree_store_insert_with_values(gns->ts, &toplevel, NULL, 0, GNS_TREESTORE_COL_NAME, _(NEW_NAME_STR), GNS_TREESTORE_COL_NAME_IS_VISIBLE, TRUE, GNS_TREESTORE_COL_RECORD_TYPE, 1, GNS_TREESTORE_COL_IS_RECORD_ROW, GNUNET_NO, GNS_TREESTORE_COL_NOT_DUMMY_ROW, GNUNET_NO, -1); zc_ctx = GNUNET_malloc (sizeof (struct ZoneIteration_Context)); zc_ctx->gns = user_data; zc_ctx->zone = gns->zone; zc_ctx->it = GNUNET_NAMESTORE_zone_iteration_start(gns->ns, &gns->zone, GNUNET_NAMESTORE_RF_NONE, GNUNET_NAMESTORE_RF_NONE, &zone_iteration_proc, zc_ctx); } static void pseu_change_cont (void *cls, int32_t success, const char *emsg) { struct GNUNET_GNS_Context *gns = cls; GtkWidget *dialog; if (GNUNET_SYSERR == success) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("New Pseudonym could not be set: `%s'\n"), emsg); dialog = gtk_message_dialog_new (GTK_WINDOW (gns->main_window), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, _("New Pseudonym could not be set: `%s'\n"), emsg); g_signal_connect_swapped (dialog, "response", G_CALLBACK (gtk_widget_destroy), dialog); gtk_widget_show_all (dialog); } } /** * Task run on shutdown. * * @param cls unused * @param tc scheduler context, unused */ static void shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_GNS_Context *gns = cls; if (NULL == gns) return; if (NULL != gns->ns) { GNUNET_NAMESTORE_disconnect (gns->ns, GNUNET_NO); gns->ns = NULL; } if (NULL != gns->pkey) { GNUNET_CRYPTO_rsa_key_free (gns->pkey); gns->pkey = NULL; } if (NULL != zonekey_directory) { GNUNET_free (zonekey_directory); zonekey_directory = NULL; } GNUNET_free (gns); } gboolean GNUNET_GNS_GTK_pseu_entry_enter_cb (GtkWidget *widget, GdkEvent *event, gpointer user_data) { const gchar * pseu; pseu = gtk_entry_get_text (GTK_ENTRY(widget)); if ((pseu == NULL) || (0 == strcmp (pseu, ""))) { //gtk_entry_set_text (GTK_ENTRY(widget), PSEU_EMPTY_STR); } return FALSE; } /** * The user edited the preferred name (PSEU) of this namespace. * Push the update to the namestore. * * @param editable the edited widget * @param user_data unused */ void GNUNET_GNS_GTK_pseu_entry_changed_cb (GtkEditable *editable, gpointer user_data) { struct GNUNET_GNS_Context *gns = user_data; struct GNUNET_NAMESTORE_RecordData rd; const gchar * pseu; pseu = gtk_entry_get_text (GTK_ENTRY(editable)); if ((pseu != NULL) && (0 != strcmp (pseu, PSEU_EMPTY_STR)) && (0 != strcmp ("", pseu)) && (GNUNET_NO == gns->iteration)) { rd.record_type = GNUNET_NAMESTORE_TYPE_PSEU; rd.expiration_time = UINT64_MAX; rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY; rd.data_size = strlen (pseu) + 1; rd.data = strdup (pseu); GNUNET_NAMESTORE_record_create(gns->ns, gns->pkey, "+", &rd, pseu_change_cont, gns); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "New Pseudonym is `%s' %u\n", (char *) rd.data, rd.data_size); } else if ((0 != strcmp (pseu, PSEU_EMPTY_STR)) && ((pseu == NULL) || (0 == strcmp ("", pseu)))) { gtk_entry_set_text (GTK_ENTRY(editable), PSEU_EMPTY_STR); } } /** * The user toggled the 'autoshort' option. Update the configuration. * * @param checkmenuitem the menu item * @param user_data unused */ void GNUNET_GNS_GTK_autoshort_imagemenuitem_toggled_cb (GtkCheckMenuItem *checkmenuitem, gpointer user_data) { struct GNUNET_GNS_Context *gns = user_data; GtkWidget *dialog; struct GNUNET_CONFIGURATION_Handle *cfg = (struct GNUNET_CONFIGURATION_Handle *) get_configuration(); gboolean state = gtk_check_menu_item_get_active (gns->shorten_menu); if (TRUE == state) GNUNET_CONFIGURATION_set_value_string(cfg,"gns", "AUTO_IMPORT_PKEY","YES"); else GNUNET_CONFIGURATION_set_value_string(cfg,"gns", "AUTO_IMPORT_PKEY","NO"); char * cfgfile = strdup (GNUNET_GTK_main_loop_get_configuration_file(ml)); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_write(cfg, cfgfile)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Changes to autoshorten could not be written to configuration file: `%s'\n"), cfgfile); dialog = gtk_message_dialog_new (GTK_WINDOW (gns->main_window), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, _("Changes to autoshorten option could not be written to configuration file: `%s'\n"), cfgfile); g_signal_connect_swapped (dialog, "response", G_CALLBACK (gtk_widget_destroy), dialog); gtk_widget_show_all (dialog); } GNUNET_free (cfgfile); } /** * The user selected 'NEW' in the menu. Open a dialog to enter a filename * to create a new zone (for editing). * * @param checkmenuitem the menu item * @param user_data unused */ void GNUNET_GNS_GTK_new_imagemenuitem_activate_cb (GtkMenuItem *menuitem, gpointer user_data) { GNUNET_break (0); // FIXME, not implemented } /** * Function called from the open-directory dialog upon completion. * * @param dialog the pseudonym selection dialog * @param response_id response code from the dialog * @param user_data the builder of the dialog */ void GNUNET_GNS_GTK_zone_open_dialog_response_cb (GtkDialog * dialog, gint response_id, gpointer user_data) { char *filename; if (GTK_RESPONSE_OK != response_id) { gtk_widget_destroy (GTK_WIDGET (dialog)); g_object_unref (G_OBJECT (dialog)); return; } filename = GNUNET_GTK_filechooser_get_filename_utf8 (GTK_FILE_CHOOSER (dialog)); gtk_widget_destroy (GTK_WIDGET (dialog)); g_object_unref (G_OBJECT (dialog)); /* FIXME: move to new zone 'filename' */ fprintf (stderr, "Got zone `%s'\n", filename); GNUNET_free (filename); } /** * The user selected 'OPEN' in the menu. Open a dialog to select * a different zonefile (for editing). * * @param checkmenuitem the menu item * @param user_data unused */ void GNUNET_GNS_GTK_open_imagemenuitem_activate_cb (GtkMenuItem *menuitem, gpointer user_data) { GtkWidget *ad; GtkBuilder *builder; GtkWidget *toplevel; GtkFileFilter *ff; GtkFileChooser *fc; builder = GNUNET_GTK_get_new_builder ("gnunet_gns_gtk_zone_open.glade", NULL); if (NULL == builder) { GNUNET_break (0); return; } /* This file filter could be set with glade if we use gtk3 * With gtk2 we have to set it manually */ ff = GTK_FILE_FILTER (gtk_builder_get_object (builder, "GNUNET_GNS_GTK_zone_open_filefilter")); gtk_file_filter_add_pattern (ff, "*.zkey"); ad = GTK_WIDGET (gtk_builder_get_object (builder, "GNUNET_GNS_GTK_zone_open_filechooserdialog")); if (GTK_IS_FILE_CHOOSER(ad)) { fc = GTK_FILE_CHOOSER(ad); if (NULL != fc) gtk_file_chooser_set_current_folder(fc, zonekey_directory); } toplevel = gtk_widget_get_toplevel (GTK_WIDGET (menuitem)); if (GTK_IS_WINDOW (toplevel)) gtk_window_set_transient_for (GTK_WINDOW (ad), GTK_WINDOW (toplevel)); gtk_window_present (GTK_WINDOW (ad)); } /** * The user clicked on the 'copy' button. Copy the full string * with the hash of our public key to the clipboard. * * @param button the button that was clicked * @param user_data unused */ void GNUNET_GNS_GTK_public_key_copy_button_clicked_cb (GtkButton *button, gpointer user_data) { GtkClipboard *cb; cb = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD); gtk_clipboard_set_text (cb, zone_as_string, -1); } /** * Callback invoked if the application is supposed to exit (via menu). * * @param menuitem the quit menu * @param user_data unused */ void GNUNET_GNS_GTK_quit_imagemenuitem_activate_cb (GtkMenuItem *menuitem, gpointer user_data) { GNUNET_GTK_tray_icon_destroy (); GNUNET_GTK_main_loop_quit (ml); GNUNET_SCHEDULER_add_now (&shutdown_task, user_data); } /** * Callback invoked if the application is supposed to exit (via window-close). * * @param widget the main window * @param event deletion event * @param user_data unused */ void GNUNET_GNS_GTK_main_window_delete_event_cb (GtkWidget *widget, GdkEvent *event, gpointer user_data) { GNUNET_GTK_tray_icon_destroy (); GNUNET_GTK_main_loop_quit (ml); GNUNET_SCHEDULER_add_now (&shutdown_task, user_data); } static void close_error_box (GtkDialog *dialog, gint response_id, gpointer user_data) { gtk_widget_destroy (GTK_WIDGET(dialog)); GNUNET_GNS_GTK_shutdown (user_data); } static void namestore_service_check (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_GNS_Context *gns = NULL; struct GNUNET_CRYPTO_ShortHashAsciiEncoded shenc; GtkWidget *dialog; char *label; char *keyfile; char *servicehome; gns = GNUNET_malloc (sizeof (struct GNUNET_GNS_Context)); if ((tc->reason & GNUNET_SCHEDULER_REASON_TIMEOUT) != 0) { char * message = _("Namestore service is not running!\n"); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, message); dialog = gtk_message_dialog_new (GTK_WINDOW (gns->main_window), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "%s", message); g_signal_connect (dialog, "response", G_CALLBACK(close_error_box), gns); gtk_widget_show_all (dialog); return; } if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (get_configuration (), "PATHS", "SERVICEHOME", &servicehome)) { GNUNET_asprintf(&zonekey_directory, ""); } else { GNUNET_asprintf(&zonekey_directory, "%s%s%s",servicehome, DIR_SEPARATOR_STR, "gns"); GNUNET_free (servicehome); } /* setup crypto keys */ if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (get_configuration (), "gns", "ZONEKEY", &keyfile)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Option `%s' missing in section `%s'\n"), "ZONEKEY", "gns"); return; } else GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using `%s'\n", keyfile); gns->pkey = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile); GNUNET_free (keyfile); keyfile = NULL; if (NULL == gns->pkey) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to read or create private zone key\n")); return; } GNUNET_CRYPTO_rsa_key_get_public (gns->pkey, &gns->pubkey); GNUNET_CRYPTO_short_hash (&gns->pubkey, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &gns->zone); GNUNET_CRYPTO_short_hash_to_enc(&gns->zone, &shenc); /* connect to namestore */ gns->ns = GNUNET_NAMESTORE_connect (get_configuration ()); if (NULL == gns->ns) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to connect to namestore\n")); return; } /* setup gui */ if (GNUNET_OK != GNUNET_GTK_main_loop_build_window (ml, gns)) { GNUNET_break (0); GNUNET_SCHEDULER_add_now (&shutdown_task, gns); return; } gns->builder = GNUNET_GTK_main_loop_get_builder(ml); gns->main_window = GTK_WIDGET (get_object ("GNUNET_GNS_GTK_main_window")); gns->ts = GTK_TREE_STORE (gtk_builder_get_object (gns->builder, "GNUNET_GNS_GTK_treestore")); gns->ls = GTK_LIST_STORE (gtk_builder_get_object (gns->builder, "GNUNET_GNS_GTK_type_liststore")); gns->tv = GTK_TREE_VIEW (gtk_builder_get_object (gns->builder, "GNUNET_GNS_GTK_main_treeview")); gns->tm = GTK_TREE_MODEL(gns->ts); gns->shorten_menu = GTK_CHECK_MENU_ITEM(gtk_builder_get_object (gns->builder, "GNUNET_GNS_GTK_autoshort_imagemenuitem")); if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (get_configuration (), "gns", "AUTO_IMPORT_PKEY")) gtk_check_menu_item_set_active (gns->shorten_menu, TRUE); else gtk_check_menu_item_set_active (gns->shorten_menu, FALSE); /* TODO: implements menus */ gtk_widget_set_visible (GTK_WIDGET (gtk_builder_get_object (gns->builder, "GNUNET_GNS_GTK_new_imagemenuitem")), FALSE); gtk_widget_set_visible (GTK_WIDGET (gtk_builder_get_object (gns->builder, "GNUNET_GNS_GTK_open_imagemenuitem")), FALSE); zone_as_string = GNUNET_strdup ((char *) &shenc); label = g_markup_printf_escaped (_("Editing zone %s"), zone_as_string); gtk_label_set_markup (GTK_LABEL (get_object ("GNUNET_GNS_GTK_zone_label")), label); g_free (label); } /* end of gnunet-setup-gns.c */