aboutsummaryrefslogtreecommitdiff
path: root/src/setup/gnunet-setup-gns.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/setup/gnunet-setup-gns.c')
-rw-r--r--src/setup/gnunet-setup-gns.c1504
1 files changed, 511 insertions, 993 deletions
diff --git a/src/setup/gnunet-setup-gns.c b/src/setup/gnunet-setup-gns.c
index 2cdcb6ba..3578a002 100644
--- a/src/setup/gnunet-setup-gns.c
+++ b/src/setup/gnunet-setup-gns.c
@@ -148,7 +148,12 @@ enum GNSTreestoreColumn
148 /** 148 /**
149 * A gboolean; TRUE if the value is a shadow record. 149 * A gboolean; TRUE if the value is a shadow record.
150 */ 150 */
151 GNS_TREESTORE_COL_IS_SHADOW 151 GNS_TREESTORE_COL_IS_SHADOW,
152
153 /**
154 * A gboolean; TRUE if the name is editable (dummy line).
155 */
156 GNS_TREESTORE_COL_NAME_IS_EDITABLE
152}; 157};
153 158
154 159
@@ -171,149 +176,87 @@ enum LIST_COLUMNS
171}; 176};
172 177
173 178
174
175/** 179/**
176 * Context we use for making changes to the namestore. 180 * Closure for 'check_name_validity_and_remove_proc'.
177 * (closure for 'add_new_records_after_removing_old_records').
178 */ 181 */
179struct UpdateContext 182struct OperationContext
180{ 183{
181 184
182 /** 185 /**
183 * Kept in a DLL. 186 * Kept in a DLL.
184 */ 187 */
185 struct UpdateContext *next; 188 struct OperationContext *next;
186 189
187 /** 190 /**
188 * Kept in a DLL. 191 * Kept in a DLL.
189 */ 192 */
190 struct UpdateContext *prev; 193 struct OperationContext *prev;
191
192 /**
193 * Array of records to add.
194 */
195 struct GNUNET_NAMESTORE_RecordData *rd;
196
197 /**
198 * Name under which we should add the records.
199 */
200 char *name;
201 194
202 /** 195 /**
203 * Associated namestore operation. 196 * Associated namestore operation.
204 */ 197 */
205 struct GNUNET_NAMESTORE_QueueEntry *qe; 198 struct GNUNET_NAMESTORE_QueueEntry *qe;
206 199
207 /**
208 * Size of the 'rd' array.
209 */
210 unsigned int rd_count;
211
212 /**
213 * Current position for record creation.
214 */
215 unsigned int rd_pos;
216}; 200};
217 201
218 202
219/** 203/**
220 * Closure for 'check_name_validity_and_remove_proc'. 204 * Information we keep per name.
221 */ 205 */
222struct RemoveContext 206struct RecordInfo
223{ 207{
224 208
225 /**
226 * Kept in a DLL.
227 */
228 struct RemoveContext *next;
229
230 /**
231 * Kept in a DLL.
232 */
233 struct RemoveContext *prev;
234
235 /** 209 /**
236 * Associated namestore operation. 210 * Name for this record.
237 */ 211 */
238 struct GNUNET_NAMESTORE_QueueEntry *qe; 212 char *name;
239 213
240 /** 214 /**
241 * Path for 'gtk_tree_model_get_iter_from_string' for removing 215 * Location of this record in the tree view.
242 * the record from the tree view IF the operation was successful.
243 * FIXME: replace with a 'GtkTreeIter'?
244 */ 216 */
245 char *path; 217 GtkTreeRowReference *rr;
246};
247
248
249/**
250 * Handle created for pseudonym-operations.
251 */
252struct PseuContext
253{
254 218
255 /** 219 /**
256 * Kept in a DLL. 220 * Serialized records under this name.
257 */ 221 */
258 struct PseuContext *next; 222 void *data;
259 223
260 /** 224 /**
261 * Kept in a DLL. 225 * Number of bytes in 'data'.
262 */ 226 */
263 struct PseuContext *prev; 227 size_t data_size;
264 228
265 /** 229 /**
266 * Associated namestore operation. 230 * Number of records serialized in 'data'.
267 */ 231 */
268 struct GNUNET_NAMESTORE_QueueEntry *qe; 232 unsigned int rd_count;
269 233
270}; 234};
271 235
272 236
273/**
274 * Our current zone monitor.
275 */
276static struct GNUNET_NAMESTORE_ZoneMonitor *zmon;
277 237
278/**
279 * Head of linked list of active update operations.
280 */
281static struct UpdateContext *uc_head;
282 238
283/**
284 * Tail of linked list of active update operations.
285 */
286static struct UpdateContext *uc_tail;
287 239
288/** 240/**
289 * Head of linked list of active remove operations. 241 * Hash map from the H(name) in the zone to the 'struct RecordInfo'
242 * for the respective entry in the tree view.
290 */ 243 */
291static struct RemoveContext *rc_head; 244static struct GNUNET_CONTAINER_MultiHashMap *n2r;
292 245
293/** 246/**
294 * Tail of linked list of active remove operations. 247 * Our current zone monitor.
295 */
296static struct RemoveContext *rc_tail;
297
298/**
299 * Head of linked list of active pseudonym operations.
300 */
301static struct PseuContext *pc_head;
302
303/**
304 * Tail of linked list of active pseudonym operations.
305 */ 248 */
306static struct PseuContext *pc_tail; 249static struct GNUNET_NAMESTORE_ZoneMonitor *zmon;
307 250
308/** 251/**
309 * Tail of linked list of active record move operations. 252 * Head of linked list of active operations.
310 */ 253 */
311static struct EditDialogContext *edc_head; 254static struct OperationContext *oc_head;
312 255
313/** 256/**
314 * Tail of linked list of active record move operations. 257 * Tail of linked list of active operations.
315 */ 258 */
316static struct EditDialogContext *edc_tail; 259static struct OperationContext *oc_tail;
317 260
318/** 261/**
319 * Name of our zone as a string. 262 * Name of our zone as a string.
@@ -343,12 +286,12 @@ static GtkTreeView *tv;
343/** 286/**
344 * Private key of the zone we are currently editing. 287 * Private key of the zone we are currently editing.
345 */ 288 */
346static struct GNUNET_CRYPTO_RsaPrivateKey *pkey; 289static struct GNUNET_CRYPTO_EccPrivateKey *pkey;
347 290
348/** 291/**
349 * Public key of the zone we are currently editing. 292 * Public key of the zone we are currently editing.
350 */ 293 */
351static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pubkey; 294static struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded pubkey;
352 295
353/** 296/**
354 * Short hash of the public key of the zone we are currently editing. 297 * Short hash of the public key of the zone we are currently editing.
@@ -367,7 +310,6 @@ static char *current_pseudonym;
367static const char *current_zone_option; 310static const char *current_zone_option;
368 311
369 312
370
371#if HAVE_QRENCODE_H 313#if HAVE_QRENCODE_H
372#include <qrencode.h> 314#include <qrencode.h>
373#include <gdk-pixbuf/gdk-pixbuf.h> 315#include <gdk-pixbuf/gdk-pixbuf.h>
@@ -571,6 +513,45 @@ GNUNET_setup_gns_qr_saveas_button_clicked_cb (GtkButton *button,
571 513
572 514
573/** 515/**
516 * Function called upon completion of an operation.
517 *
518 * @param cls the 'struct OperationContext' of the operation that completed
519 * @param success GNUNET_OK if the operation succeeded
520 * @param emsg error message if the operation failed
521 */
522static void
523operation_done_cont (void *cls,
524 int32_t success,
525 const char *emsg)
526{
527 struct OperationContext *oc = cls;
528 GtkWidget *dialog;
529 GtkWindow *main_window;
530
531 oc->qe = NULL;
532 GNUNET_CONTAINER_DLL_remove (oc_head,
533 oc_tail,
534 oc);
535 if (GNUNET_SYSERR == success)
536 {
537 main_window = GTK_WINDOW (GNUNET_SETUP_get_object ("GNUNET_setup_dialog"));
538 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Operation failed: `%s'\n"), emsg);
539 dialog = gtk_message_dialog_new (main_window,
540 GTK_DIALOG_DESTROY_WITH_PARENT,
541 GTK_MESSAGE_ERROR,
542 GTK_BUTTONS_CLOSE,
543 _("Operation failed: `%s'\n"),
544 emsg);
545 g_signal_connect_swapped (dialog, "response",
546 G_CALLBACK (gtk_widget_destroy),
547 dialog);
548 gtk_widget_show_all (dialog);
549 }
550 GNUNET_free (oc);
551}
552
553
554/**
574 * Clear all entries in the zone view and hide the tree view. 555 * Clear all entries in the zone view and hide the tree view.
575 */ 556 */
576static void 557static void
@@ -600,20 +581,6 @@ load_zone (const char *zonename);
600 581
601 582
602/** 583/**
603 * Our model is somehow are inconsistent with the namestore database.
604 * Clear our model and resync by loading all of it from the namestore.
605 * (Naturally, this should never happen in normal operation; however,
606 * if multiple users edit the same namestore, it might happen without
607 * there being a bug ...).
608 */
609static void
610resync_db ()
611{
612 load_zone (current_zone_option);
613}
614
615
616/**
617 * Display an error message for the user. 584 * Display an error message for the user.
618 * 585 *
619 * @param title title of the error message 586 * @param title title of the error message
@@ -641,379 +608,98 @@ show_error_message (const char *title,
641 608
642 609
643/** 610/**
644 * Release resources of this update context. 611 * Remove selected record from the namestore.
645 * 612 *
646 * @param uc context to free 613 * @param edc identifying record to remove
647 */
648static void
649free_update_context (struct UpdateContext *uc)
650{
651 unsigned int c;
652
653 if (NULL != uc->qe)
654 {
655 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
656 _("Setup shutdown before all records could be written. Record lost!\n"));
657 GNUNET_NAMESTORE_cancel (uc->qe);
658 uc->qe = NULL;
659 }
660 GNUNET_CONTAINER_DLL_remove (uc_head, uc_tail, uc);
661 for (c = 0; c < uc->rd_count; c++)
662 GNUNET_free ((void *) uc->rd[c].data);
663 GNUNET_free (uc->rd);
664 GNUNET_free (uc->name);
665 GNUNET_free (uc);
666}
667
668
669/**
670 * Function called to transmit the next record from this update context
671 * to the database.
672 *
673 * @param uc update context
674 */
675static void
676create_next_record (struct UpdateContext *uc);
677
678
679/**
680 * Function called after we created a new record. If the creation was
681 * successful, add more records from the update context.
682 *
683 * @param cls the 'struct UpdateContext'
684 * @param success GNUNET_SYSERR on failure (including timeout/queue drop/failure to validate)
685 * GNUNET_NO if content was already there or not found
686 * GNUNET_YES (or other positive value) on success
687 * @param emsg NULL on success, otherwise an error message
688 */
689static void
690create_more_records (void *cls,
691 int32_t success,
692 const char *emsg)
693{
694 struct UpdateContext *uc = cls;
695
696 uc->qe = NULL;
697 switch (success)
698 {
699 case GNUNET_OK:
700 uc->rd_pos++;
701 create_next_record (uc);
702 return;
703 case GNUNET_NO:
704 case GNUNET_SYSERR:
705 show_error_message (_("Failed to create record"),
706 emsg);
707 resync_db ();
708 break;
709 default:
710 GNUNET_break (0);
711 break;
712 }
713 free_update_context (uc);
714}
715
716
717
718/**
719 * Function called to transmit the next record from this update context
720 * to the database.
721 *
722 * @param uc update context
723 */
724static void
725create_next_record (struct UpdateContext *uc)
726{
727 if (uc->rd_pos == uc->rd_count)
728 {
729 free_update_context (uc);
730 return;
731 }
732#if 0
733 /* FIXME: what were we doing here again? */
734 uc->qe = GNUNET_NAMESTORE_record_create (namestore, pkey,
735 uc->name, &uc->rd[uc->rd_pos],
736 &create_more_records, uc);
737#endif
738}
739
740
741/**
742 * Function called after we removed the old record. If the
743 * removal was successful, add the new records from the
744 * update context.
745 *
746 * @param cls the 'struct UpdateContext'
747 * @param success GNUNET_SYSERR on failure (including timeout/queue drop/failure to validate)
748 * GNUNET_NO if content was already there or not found
749 * GNUNET_YES (or other positive value) on success
750 * @param emsg NULL on success, otherwise an error message
751 */ 614 */
752static void 615static void
753add_new_records_after_removing_old_records (void *cls, 616remove_record_at_offset (struct EditDialogContext *edc)
754 int32_t success,
755 const char *emsg)
756{ 617{
757 struct UpdateContext *uc = cls; 618 struct RecordInfo *ri = edc->ri;
758 619 struct OperationContext *oc;
759 uc->qe = NULL; 620
760 switch (success) 621 if ( (NULL == ri) ||
622 (edc->off >= ri->rd_count) )
761 { 623 {
762 case GNUNET_OK:
763 case GNUNET_NO:
764 create_next_record (uc);
765 return;
766 case GNUNET_SYSERR:
767 show_error_message (_("Failed to remove record"),
768 emsg);
769 resync_db ();
770 break;
771 default:
772 GNUNET_break (0); 624 GNUNET_break (0);
773 resync_db ();
774 break;
775 }
776 free_update_context (uc);
777}
778
779
780/**
781 * Check that the data at the given 'path' (see gtk_tree_model_get_iter_from_string)
782 * is valid, and if so commit it after removing the old data.
783 *
784 * @param it iter identifying the new record
785 * @param oldname name of the old record, NULL if this is a fresh name
786 */
787static void
788check_name_validity_and_commit (GtkTreeIter *it,
789 const char *oldname)
790{
791 GtkTreeIter parent; /* parent record with the 'name' */
792 char *name; /* name of the records */
793 struct GNUNET_NAMESTORE_RecordData *rd;
794 unsigned int records; /* number of records in 'rd' */
795 int children; /* number of records below 'parent' */
796 int append_pseu; /* do we need to create a '+' PSEU record? */
797 struct UpdateContext * uc;
798 int c;
799
800 if (! gtk_tree_model_iter_parent (tm, &parent, it))
801 {
802 if (NULL != oldname)
803 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
804 "Name of existing record `%s' was changed, moving associated records\n",
805 oldname);
806 parent = *it;
807 }
808 gtk_tree_model_get (tm, &parent,
809 GNS_TREESTORE_COL_NAME, &name,
810 -1);
811 children = gtk_tree_model_iter_n_children (tm, &parent);
812 if (children < 1)
813 {
814 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
815 "Changed name `%s' has no associated records, not committing to namestore\n",
816 name);
817 g_free (name);
818 return; 625 return;
819 } 626 }
820 if ( (0 == strcmp (name, GNUNET_GNS_MASTERZONE_STR)) && 627
821 (0 == strcmp (current_zone_option, "ZONEKEY")) )
822 {
823 /* We have to append PSEU RECORD, this is the 'master' zone */
824 append_pseu = GNUNET_YES;
825 records = children + 1;
826 }
827 else
828 {
829 append_pseu = GNUNET_NO;
830 records = children;
831 }
832
833 rd = GNUNET_malloc (records * sizeof (struct GNUNET_NAMESTORE_RecordData));
834 GNUNET_assert (gtk_tree_model_iter_children (tm, it, &parent));
835
836 for (c = 0; c < children; c++)
837 {
838 gchar *n_name;
839 gint n_type;
840 gboolean n_public;
841 gboolean n_is_shadow;
842 guint64 n_exp_time;
843 gboolean n_is_relative;
844 gchar *n_value;
845 void * data;
846 size_t data_size;
847
848 gtk_tree_model_get (tm, it,
849 GNS_TREESTORE_COL_NAME, &n_name,
850 GNS_TREESTORE_COL_RECORD_TYPE, &n_type,
851 GNS_TREESTORE_COL_IS_PUBLIC, &n_public,
852 GNS_TREESTORE_COL_EXP_TIME, &n_exp_time,
853 GNS_TREESTORE_COL_EXP_TIME_IS_REL, &n_is_relative,
854 GNS_TREESTORE_COL_IS_SHADOW, &n_is_shadow,
855 GNS_TREESTORE_COL_VAL_AS_STR, &n_value,
856 -1);
857 if ( (NULL == n_name) ||
858 ( (GNUNET_SYSERR == GNUNET_DNSPARSER_check_label (n_name)) &&
859 (0 != strcmp (n_name, GNUNET_GNS_MASTERZONE_STR)) ) ||
860 (0 == n_type) ||
861 (0 == n_exp_time) ||
862 (NULL == n_value) ||
863 (GNUNET_OK != GNUNET_NAMESTORE_string_to_value (n_type, n_value, &data, &data_size)) )
864 {
865 GNUNET_break (0);
866 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
867 "Invalid record, skipping\n");
868 records--;
869 children--;
870 c--;
871 }
872 else
873 {
874 if (n_public)
875 rd[c].flags = GNUNET_NAMESTORE_RF_AUTHORITY;
876 else
877 rd[c].flags = GNUNET_NAMESTORE_RF_AUTHORITY | GNUNET_NAMESTORE_RF_PRIVATE;
878 if (n_is_shadow)
879 rd[c].flags |= GNUNET_NAMESTORE_RF_SHADOW_RECORD;
880 rd[c].record_type = n_type;
881 rd[c].expiration_time = n_exp_time;
882 if (n_is_relative)
883 rd[c].flags |= GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION;
884 rd[c].data_size = data_size;
885 rd[c].data = GNUNET_malloc(data_size);
886 memcpy ((void *) rd[c].data, data, data_size);
887 }
888 g_free (n_name);
889 g_free (n_value);
890 GNUNET_assert (gtk_tree_model_iter_next (tm, it) ^ (c + 1 == children));
891 }
892
893 if (GNUNET_YES == append_pseu)
894 { 628 {
895 GtkEntry *entry; 629 struct GNUNET_NAMESTORE_RecordData rd_old[ri->rd_count];
896 const gchar *pseu; 630 struct GNUNET_NAMESTORE_RecordData rd_new[ri->rd_count - 1];
897 631
898 /* Append PSEU record */ 632 /* Removing a single record */
899 GNUNET_assert (children == (records -1));
900 entry = GTK_ENTRY (GNUNET_SETUP_get_object ("GNUNET_setup_gns_pseu_entry"));
901 pseu = gtk_entry_get_text (GTK_ENTRY(entry));
902 if ( (NULL == pseu) ||
903 (0 == strcmp ("", pseu)) )
904 {
905 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
906 "No zone pseudonym given, not creating PSEU record\n");
907 records--;
908 }
909 else
910 {
911 if (GNUNET_OK != GNUNET_NAMESTORE_string_to_value (GNUNET_NAMESTORE_TYPE_PSEU,
912 pseu,
913 (void **) &rd[records - 1].data,
914 &rd[records - 1].data_size))
915 {
916 show_error_message (_("Invalid pseudonym specified for zone"),
917 pseu);
918 records--;
919 }
920 else
921 {
922 rd[records - 1].record_type = GNUNET_NAMESTORE_TYPE_PSEU;
923 rd[records - 1].expiration_time = UINT64_MAX;
924 rd[records - 1].flags = GNUNET_NAMESTORE_RF_AUTHORITY | GNUNET_NAMESTORE_RF_NONE;
925 }
926 }
927 }
928 if (0 == records)
929 {
930 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 633 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
931 "No valid records remaining, not storing to namestore\n"); 634 "Removing single record for name `%s'\n",
932 GNUNET_free (rd); 635 edc->name);
933 return; 636 GNUNET_break (GNUNET_OK ==
934 } 637 GNUNET_NAMESTORE_records_deserialize (ri->data_size,
935 638 ri->data,
936 /* FIXME: modify entries! */ 639 ri->rd_count,
937#if 0 640 rd_old));
938 uc = GNUNET_malloc (sizeof (struct UpdateContext)); 641 GNUNET_assert (edc->off < ri->rd_count);
939 uc->rd = rd; 642 memcpy (rd_new, rd_old, (ri->rd_count - 1) * sizeof (struct GNUNET_NAMESTORE_RecordData));
940 uc->rd_count = records; 643 rd_new[edc->off] = rd_old[ri->rd_count - 1];
941 uc->name = name; 644 oc = GNUNET_new (struct OperationContext);
942 GNUNET_CONTAINER_DLL_insert (uc_head, uc_tail, uc); 645 GNUNET_CONTAINER_DLL_insert (oc_head, oc_tail, oc);
943 uc->qe = GNUNET_NAMESTORE_record_remove (namestore, 646 oc->qe = GNUNET_NAMESTORE_record_put_by_authority (namestore,
944 pkey, 647 pkey, edc->name,
945 (NULL != oldname) ? oldname : name, 648 ri->rd_count - 1,
946 NULL, 649 rd_new,
947 &add_new_records_after_removing_old_records, uc); 650 &operation_done_cont, oc);
948 if (NULL == uc->qe)
949 {
950 show_error_message (_("Failed to commit record to database"),
951 _("Internal error"));
952 resync_db ();
953 free_update_context (uc);
954 return;
955 } 651 }
956#endif
957} 652}
958 653
959 654
960/**
961 * Release resources of the given remove context.
962 *
963 * @param rc remove context to release
964 */
965static void
966free_remove_context (struct RemoveContext *rc)
967{
968 if (NULL != rc->qe)
969 {
970 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
971 _("Setup shutdown before all records could be written. Record lost!\n"));
972 GNUNET_NAMESTORE_cancel (rc->qe);
973 rc->qe = NULL;
974 }
975 GNUNET_CONTAINER_DLL_remove (rc_head,
976 rc_tail,
977 rc);
978 GNUNET_free (rc->path);
979 GNUNET_free (rc);
980}
981
982 655
983/** 656/**
984 * Remove a record from the model (and if it is valid, also from 657 * Remove a record from the model. If the given iter identifies an
985 * the namestore). If the given path identifies an entire 'name', 658 * entire 'name', remove all records under that name.
986 * remove all records under that name.
987 * 659 *
988 * @param path identifying record(s) to remove; FIXME: consider doing this with an 'iter' instead 660 * @param iter identifying record(s) to remove
989 */ 661 */
990static void 662static void
991remove_records_by_path (const gchar *path) 663remove_records_by_iter (GtkTreeIter *iter)
992{ 664{
993 GtkTreeIter it;
994 GtkTreeIter parent; 665 GtkTreeIter parent;
995 char *name; 666 char *name;
996 struct GNUNET_NAMESTORE_RecordData rd; 667 struct GNUNET_HashCode name_hash;
997 struct RemoveContext *rc; 668 struct RecordInfo *ri;
998 char *n_name; 669 struct OperationContext *oc;
999 int n_type; 670
1000 gboolean n_public; 671 gtk_tree_model_get (tm, iter,
1001 guint64 n_exp_time;
1002 gboolean n_is_relative;
1003 gboolean n_is_shadow;
1004 char *n_value;
1005
1006 gtk_tree_model_get_iter_from_string (tm, &it, path);
1007 gtk_tree_model_get (tm, &it,
1008 GNS_TREESTORE_COL_NAME, &name, 672 GNS_TREESTORE_COL_NAME, &name,
1009 -1); 673 -1);
1010 if (gtk_tree_model_iter_parent (tm, &parent, &it)) 674 GNUNET_CRYPTO_hash (name, strlen (name), &name_hash);
675 ri = GNUNET_CONTAINER_multihashmap_get (n2r,
676 &name_hash);
677 GNUNET_assert (NULL != ri);
678
679 if ( (gtk_tree_model_iter_parent (tm, &parent, iter)) &&
680 (ri->rd_count > 0) )
1011 { 681 {
682 struct GNUNET_NAMESTORE_RecordData rd_old[ri->rd_count];
683 struct GNUNET_NAMESTORE_RecordData rd_new[ri->rd_count - 1];
684 struct GNUNET_NAMESTORE_RecordData rd;
685 unsigned int off;
686 int n_type;
687 gboolean n_public;
688 guint64 n_exp_time;
689 gboolean n_is_relative;
690 gboolean n_is_shadow;
691 char *n_value;
692
1012 /* Removing a single record */ 693 /* Removing a single record */
1013 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 694 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1014 "Removing single record for name `%s'\n", name); 695 "Removing single record for name `%s'\n",
1015 gtk_tree_model_get (tm, &it, 696 name);
1016 GNS_TREESTORE_COL_NAME, &n_name, 697 GNUNET_break (GNUNET_OK ==
698 GNUNET_NAMESTORE_records_deserialize (ri->data_size,
699 ri->data,
700 ri->rd_count,
701 rd_old));
702 gtk_tree_model_get (tm, iter,
1017 GNS_TREESTORE_COL_RECORD_TYPE, &n_type, 703 GNS_TREESTORE_COL_RECORD_TYPE, &n_type,
1018 GNS_TREESTORE_COL_IS_PUBLIC, &n_public, 704 GNS_TREESTORE_COL_IS_PUBLIC, &n_public,
1019 GNS_TREESTORE_COL_EXP_TIME, &n_exp_time, 705 GNS_TREESTORE_COL_EXP_TIME, &n_exp_time,
@@ -1021,7 +707,6 @@ remove_records_by_path (const gchar *path)
1021 GNS_TREESTORE_COL_IS_SHADOW, &n_is_shadow, 707 GNS_TREESTORE_COL_IS_SHADOW, &n_is_shadow,
1022 GNS_TREESTORE_COL_VAL_AS_STR, &n_value, 708 GNS_TREESTORE_COL_VAL_AS_STR, &n_value,
1023 -1); 709 -1);
1024
1025 /* valid name */ 710 /* valid name */
1026 if (n_public) 711 if (n_public)
1027 rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY; 712 rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY;
@@ -1038,49 +723,38 @@ remove_records_by_path (const gchar *path)
1038 (void**)&rd.data, &rd.data_size)) 723 (void**)&rd.data, &rd.data_size))
1039 { 724 {
1040 /* can't remove, value invalid */ 725 /* can't remove, value invalid */
1041 g_free (n_name); 726 GNUNET_assert (0);
1042 g_free (n_value); 727 g_free (n_value);
728 g_free (name);
1043 return; 729 return;
1044 } 730 }
1045 731 for (off=0;off<ri->rd_count;off++)
1046 /* FIXME: actually apply changes! */ 732 if (GNUNET_YES ==
1047 GNUNET_free ((void *) rd.data); 733 GNUNET_NAMESTORE_records_cmp (&rd,
1048 g_free (n_name); 734 &rd_old[off]))
735 break;
736 GNUNET_assert (off != ri->rd_count);
737 memcpy (rd_new, rd_old, (ri->rd_count - 1) * sizeof (struct GNUNET_NAMESTORE_RecordData));
738 rd_new[off] = rd_old[ri->rd_count - 1];
739 oc = GNUNET_new (struct OperationContext);
740 GNUNET_CONTAINER_DLL_insert (oc_head, oc_tail, oc);
741 oc->qe = GNUNET_NAMESTORE_record_put_by_authority (namestore,
742 pkey, name,
743 ri->rd_count - 1,
744 rd_new,
745 &operation_done_cont, oc);
1049 g_free (n_value); 746 g_free (n_value);
1050 } 747 }
1051 else if (0 != strcmp (name, GNUNET_GNS_MASTERZONE_STR))
1052 {
1053 /* FIXME: actually apply changes! */
1054 }
1055 g_free (name);
1056}
1057
1058
1059/**
1060 * Convert an expiration time to a string for display.
1061 *
1062 * @param is_relative is the given time relative?
1063 * @param exp_val expiration value
1064 * @return string representing the value
1065 */
1066static char *
1067exp_time_to_string (gboolean is_relative,
1068 uint64_t exp_val)
1069{
1070 if (is_relative)
1071 {
1072 struct GNUNET_TIME_Relative rel_time;
1073
1074 rel_time.rel_value = exp_val;
1075 return GNUNET_strdup (GNUNET_STRINGS_relative_time_to_string (rel_time, GNUNET_NO));
1076 }
1077 else 748 else
1078 { 749 {
1079 struct GNUNET_TIME_Absolute exp_abs; 750 oc = GNUNET_new (struct OperationContext);
1080 751 GNUNET_CONTAINER_DLL_insert (oc_head, oc_tail, oc);
1081 exp_abs.abs_value = exp_val; 752 oc->qe = GNUNET_NAMESTORE_record_put_by_authority (namestore,
1082 return GNUNET_strdup (GNUNET_STRINGS_absolute_time_to_string (exp_abs)); 753 pkey, name,
754 0, NULL,
755 &operation_done_cont, oc);
1083 } 756 }
757 g_free (name);
1084} 758}
1085 759
1086 760
@@ -1092,8 +766,7 @@ exp_time_to_string (gboolean is_relative,
1092static void 766static void
1093free_edit_dialog_context (struct EditDialogContext *edc) 767free_edit_dialog_context (struct EditDialogContext *edc)
1094{ 768{
1095 g_free (edc->n_name); 769 g_free (edc->name);
1096 g_free (edc->n_new_name);
1097 g_free (edc->n_value); 770 g_free (edc->n_value);
1098 g_free (edc->new_zone_option); 771 g_free (edc->new_zone_option);
1099 GNUNET_free (edc); 772 GNUNET_free (edc);
@@ -1101,97 +774,6 @@ free_edit_dialog_context (struct EditDialogContext *edc)
1101 774
1102 775
1103/** 776/**
1104 * Function called upon completion of a 'move' operation.
1105 *
1106 * @param cls the 'struct EditDialogContext' of the operation that completed
1107 * @param success GNUNET_OK if the operation succeeded
1108 * @param emsg error message if the operation failed
1109 */
1110static void
1111record_move_finish (void *cls,
1112 int32_t success,
1113 const char *emsg)
1114{
1115 struct EditDialogContext *edc = cls;
1116
1117 edc->qe = NULL;
1118 GNUNET_CONTAINER_DLL_remove (edc_head,
1119 edc_tail,
1120 edc);
1121 if (NULL != emsg)
1122 show_error_message (_("Failed to move record to target zone"),
1123 emsg);
1124 free_edit_dialog_context (edc);
1125}
1126
1127
1128/**
1129 * Function called upon completion of 'GNUNET_CRYPTO_rsa_key_create_async'.
1130 * Displays an error message upon failure, otherwise stores the moved record
1131 * in the target zone.
1132 *
1133 * @param cls closure with the struct EditDialogContext;
1134 * @param pk NULL on error, otherwise the private key (which must be free'd by the callee)
1135 * @param emsg NULL on success, otherwise an error message
1136 */
1137static void
1138record_move_continuation (void *cls,
1139 struct GNUNET_CRYPTO_RsaPrivateKey *pk,
1140 const char *emsg)
1141{
1142 struct EditDialogContext *edc = cls;
1143 struct GNUNET_NAMESTORE_RecordData rd;
1144 void *data;
1145 size_t data_size;
1146
1147 edc->rkgc = NULL;
1148 if (NULL != emsg)
1149 {
1150 show_error_message (_("Failed to access key for target zone"),
1151 emsg);
1152 GNUNET_CONTAINER_DLL_remove (edc_head,
1153 edc_tail,
1154 edc);
1155 free_edit_dialog_context (edc);
1156 return;
1157 }
1158 if (GNUNET_OK !=
1159 GNUNET_NAMESTORE_string_to_value (edc->record_type,
1160 edc->n_value,
1161 &data,
1162 &data_size))
1163 {
1164 /* edit dialog produced invalid value string!? */
1165 GNUNET_break (0);
1166 GNUNET_CONTAINER_DLL_remove (edc_head,
1167 edc_tail,
1168 edc);
1169 free_edit_dialog_context (edc);
1170 return;
1171 }
1172 rd.record_type = edc->record_type;
1173 rd.expiration_time = UINT64_MAX;
1174 if (edc->n_public)
1175 rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY;
1176 else
1177 rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY | GNUNET_NAMESTORE_RF_PRIVATE;
1178 if (edc->n_is_relative)
1179 rd.flags |= GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION;
1180 if (edc->n_is_shadow)
1181 rd.flags |= GNUNET_NAMESTORE_RF_SHADOW_RECORD;
1182 rd.data_size = data_size;
1183 rd.data = data;
1184#if 0
1185 /* FIXME: actually apply changes! */
1186 edc->qe = GNUNET_NAMESTORE_record_create (namestore, pk,
1187 edc->n_new_name,
1188 &rd,
1189 &record_move_finish, edc);
1190#endif
1191}
1192
1193
1194/**
1195 * The edit dialog completed; update the namestore and the 777 * The edit dialog completed; update the namestore and the
1196 * view based on the new values in 'edc'. 778 * view based on the new values in 'edc'.
1197 * 779 *
@@ -1202,87 +784,50 @@ static void
1202edit_dialog_continuation (struct EditDialogContext *edc, 784edit_dialog_continuation (struct EditDialogContext *edc,
1203 GtkResponseType ret) 785 GtkResponseType ret)
1204{ 786{
1205 char *path;
1206 char *estr;
1207
1208 switch (ret) 787 switch (ret)
1209 { 788 {
1210 case GTK_RESPONSE_REJECT: /* code for 'delete' */ 789 case GTK_RESPONSE_REJECT: /* code for 'delete' */
1211 if (GNUNET_YES == edc->old_record_in_namestore) 790 if (GNUNET_YES == edc->old_record_in_namestore)
1212 { 791 {
1213 /* remove item from tree view and namestore */ 792 /* remove item from tree view and namestore */
1214 path = gtk_tree_model_get_string_from_iter (tm, &edc->it); 793 remove_record_at_offset (edc);
1215 remove_records_by_path (path);
1216 g_free (path);
1217 } 794 }
1218 else 795 else
1219 { 796 {
1220 /* invalid choice, 'delete' should have been hidden... */ 797 /* invalid choice, 'delete' should have been hidden... */
1221 GNUNET_break (0); 798 GNUNET_break (0);
1222 gtk_tree_store_remove (ts, &edc->it);
1223 } 799 }
1224 break; 800 break;
1225 case GTK_RESPONSE_CANCEL: 801 case GTK_RESPONSE_CANCEL:
1226 case GTK_RESPONSE_DELETE_EVENT: /* window deletion counts as 'cancel' */ 802 case GTK_RESPONSE_DELETE_EVENT: /* window deletion counts as 'cancel' */
1227 if (GNUNET_NO == edc->old_record_in_namestore) 803 /* do nothing */
1228 {
1229 /* re-enable type selection */
1230 gtk_tree_store_set (ts, &edc->it,
1231 GNS_TREESTORE_COL_TYPE_IS_EDITABLE, TRUE,
1232 GNS_TREESTORE_COL_VAL_COLOR, "red",
1233 -1);
1234 }
1235 else
1236 {
1237 /* do nothing */
1238 }
1239 break; 804 break;
1240 case GTK_RESPONSE_OK: 805 case GTK_RESPONSE_OK:
1241 /* update model */ 806 /* update model */
1242 if (0 == strcmp (edc->new_zone_option, 807 if (0 == strcmp (edc->new_zone_option,
1243 current_zone_option)) 808 current_zone_option))
1244 { 809 {
1245 /* zone stayed the same, update record in current model/zone */
1246 estr = exp_time_to_string (edc->n_is_relative,
1247 edc->n_exp_time);
1248 gtk_tree_store_set (ts, &edc->it,
1249 GNS_TREESTORE_COL_NAME, edc->n_name,
1250 GNS_TREESTORE_COL_IS_PUBLIC, edc->n_public,
1251 GNS_TREESTORE_COL_EXP_TIME, edc->n_exp_time,
1252 GNS_TREESTORE_COL_EXP_TIME_IS_REL, edc->n_is_relative,
1253 GNS_TREESTORE_COL_EXP_TIME_AS_STR, estr,
1254 GNS_TREESTORE_COL_IS_SHADOW, edc->n_is_shadow,
1255 GNS_TREESTORE_COL_VAL_AS_STR, edc->n_value,
1256 GNS_TREESTORE_COL_VAL_COLOR, NULL,
1257 -1);
1258 GNUNET_free (estr);
1259 if (GNUNET_YES == edc->old_record_in_namestore) 810 if (GNUNET_YES == edc->old_record_in_namestore)
1260 { 811 {
1261 /* replace record in database with that from model */ 812 /* replace record in database with that from model */
1262 check_name_validity_and_commit (&edc->it, edc->n_name); 813 GNUNET_break (0); // not implemented
1263 } 814 }
1264 else 815 else
1265 { 816 {
1266 /* add record in database based on model */ 817 /* add record in database based on model */
1267 check_name_validity_and_commit (&edc->it, NULL); 818 GNUNET_break (0); // not implemented
1268 } 819 }
1269 } 820 }
1270 else 821 else
1271 { 822 {
1272 char *keyfile; 823 char *keyfile;
824 struct GNUNET_CRYPTO_EccPrivateKey *pk;
1273 825
1274 /* zone changed, remove record from old zone, add to new zone! */ 826 /* zone changed, remove record from old zone, add to new zone! */
1275 if (GNUNET_YES == edc->old_record_in_namestore) 827 if (GNUNET_YES == edc->old_record_in_namestore)
1276 { 828 {
1277 /* remove item from tree view and namestore */ 829 /* remove item from tree view and namestore */
1278 path = gtk_tree_model_get_string_from_iter (tm, &edc->it); 830 remove_record_at_offset (edc);
1279 remove_records_by_path (path);
1280 g_free (path);
1281 }
1282 else
1283 {
1284 /* remove item just from tree view, as it was not in the model */
1285 gtk_tree_store_remove (ts, &edc->it);
1286 } 831 }
1287 832
1288 /* now add item to target zone */ 833 /* now add item to target zone */
@@ -1300,19 +845,17 @@ edit_dialog_continuation (struct EditDialogContext *edc,
1300 emsg); 845 emsg);
1301 GNUNET_free (emsg); 846 GNUNET_free (emsg);
1302 } 847 }
1303 edc->rkgc = GNUNET_CRYPTO_rsa_key_create_start (keyfile, 848 pk = GNUNET_CRYPTO_ecc_key_create_from_file (keyfile);
1304 &record_move_continuation, 849 GNUNET_free (keyfile);
1305 edc); 850 if (NULL == pk)
1306 if (NULL == edc->rkgc)
1307 { 851 {
1308 GNUNET_break (0); 852 show_error_message (_("Failed to load private key for target zone"),
1309 GNUNET_free (keyfile); 853 NULL);
1310 break; 854 return;
1311 } 855 }
1312 GNUNET_CONTAINER_DLL_insert (edc_head, 856 GNUNET_break (0); // not implemented
1313 edc_tail, 857 /* FIXME: get target zone records, merge with new one, commit! */
1314 edc); 858 GNUNET_CRYPTO_ecc_key_free (pk);
1315 GNUNET_free (keyfile);
1316 return; 859 return;
1317 } 860 }
1318 break; 861 break;
@@ -1324,45 +867,51 @@ edit_dialog_continuation (struct EditDialogContext *edc,
1324} 867}
1325 868
1326 869
870
1327/** 871/**
1328 * Edit the record at the currently selected row. If the old record 872 * Launch a record editing dialog.
1329 * exists, allow the user to modify or delete it; if it does not
1330 * exist, make the record type editable again (by offering the user the
1331 * 'cancel' option; hide 'delete' in this case).
1332 * 873 *
1333 * @param old_record_in_namestore GNUNET_YES if the old record exists in the namestore, 874 * @param n_type type of the record to edit
1334 * GNUNET_NO if this is a new record that doesn't exist yet 875 * @param name name of the record to edit
876 * @param ri record information for this name (can be NULL
877 * if this is the first record for the name)
878 * @param off offset of the record being edited in the
879 * ri's list; UINT_MAX if this is a new record
1335 */ 880 */
1336static void 881static void
1337edit_selected_row (int old_record_in_namestore) 882launch_edit_dialog (gint n_type,
883 const char *name,
884 struct RecordInfo *ri,
885 unsigned int off)
1338{ 886{
1339 GtkTreeSelection *sel;
1340 gint n_type;
1341 struct EditDialogContext *edc; 887 struct EditDialogContext *edc;
1342 888
1343 sel = gtk_tree_view_get_selection (tv); 889 edc = GNUNET_new (struct EditDialogContext);
1344 edc = GNUNET_malloc (sizeof (struct EditDialogContext)); 890 if ( (NULL != ri) &&
1345 if (! gtk_tree_selection_get_selected (sel, NULL, &edc->it)) 891 (off < ri->rd_count) )
1346 { 892 {
1347 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 893 struct GNUNET_NAMESTORE_RecordData rd_old[ri->rd_count];
1348 "No row selected\n"); 894
1349 GNUNET_free (edc); 895 GNUNET_break (GNUNET_OK ==
1350 return; 896 GNUNET_NAMESTORE_records_deserialize (ri->data_size,
897 ri->data,
898 ri->rd_count,
899 rd_old));
900 edc->n_value = GNUNET_NAMESTORE_value_to_string (n_type,
901 rd_old[off].data,
902 rd_old[off].data_size);
903 edc->n_public = (0 == (rd_old[off].flags & GNUNET_NAMESTORE_RF_PRIVATE));
904 edc->n_is_relative = (0 != (rd_old[off].flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION));
905 edc->n_is_shadow = (0 != (rd_old[off].flags & GNUNET_NAMESTORE_RF_SHADOW_RECORD));
906 edc->n_exp_time = rd_old[off].expiration_time;
907 edc->old_record_in_namestore = GNUNET_YES;
1351 } 908 }
1352 gtk_tree_model_get (tm, &edc->it, 909 edc->ri = ri;
1353 GNS_TREESTORE_COL_NAME, &edc->n_name, 910 edc->off = off;
1354 GNS_TREESTORE_COL_RECORD_TYPE, &n_type, 911 edc->name = GNUNET_strdup (name);
1355 GNS_TREESTORE_COL_IS_PUBLIC, &edc->n_public,
1356 GNS_TREESTORE_COL_EXP_TIME, &edc->n_exp_time,
1357 GNS_TREESTORE_COL_EXP_TIME_IS_REL, &edc->n_is_relative,
1358 GNS_TREESTORE_COL_IS_SHADOW, &edc->n_is_shadow,
1359 GNS_TREESTORE_COL_VAL_AS_STR, &edc->n_value,
1360 -1);
1361 edc->old_record_in_namestore = old_record_in_namestore;
1362 edc->new_zone_option = g_strdup (current_zone_option); 912 edc->new_zone_option = g_strdup (current_zone_option);
1363 edc->n_new_name = g_strdup (edc->n_name);
1364 edc->cont = &edit_dialog_continuation;
1365 edc->record_type = n_type; 913 edc->record_type = n_type;
914 edc->cont = &edit_dialog_continuation;
1366 switch (n_type) 915 switch (n_type)
1367 { 916 {
1368 case GNUNET_DNSPARSER_TYPE_A: 917 case GNUNET_DNSPARSER_TYPE_A:
@@ -1404,13 +953,57 @@ edit_selected_row (int old_record_in_namestore)
1404 case GNUNET_DNSPARSER_TYPE_TLSA: 953 case GNUNET_DNSPARSER_TYPE_TLSA:
1405 default: 954 default:
1406 GNUNET_break (0); 955 GNUNET_break (0);
1407 edc->cont (edc, GTK_RESPONSE_CANCEL); /* treat as 'cancel' */ 956 edit_dialog_continuation (edc,
957 GTK_RESPONSE_CANCEL);
1408 break; 958 break;
1409 } 959 }
1410} 960}
1411 961
1412 962
1413/** 963/**
964 * User selected 'edit' in the popup menu. Edit the
965 * selected row.
966 *
967 * @param widget the GtkTreeView
968 * @param user_data main window builder
969 */
970void
971GNUNET_setup_gns_popup_edit_button_activate_cb (GtkWidget *widget,
972 gpointer user_data)
973{
974 GtkTreeSelection *sel;
975 gint n_type;
976 gchar *n_name;
977 unsigned int off;
978 struct RecordInfo *ri;
979 GtkTreeIter iter;
980
981 /* FIXME: not this easy! Row may still be a 'fresh' row (user
982 can right-click anywhere, right? -- maybe suppress pop-up
983 in that case?? */
984 sel = gtk_tree_view_get_selection (tv);
985 if (! gtk_tree_selection_get_selected (sel, NULL, &iter))
986 {
987 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
988 "No row selected\n");
989 return;
990 }
991 gtk_tree_model_get (tm, &iter,
992 GNS_TREESTORE_COL_NAME, &n_name,
993 GNS_TREESTORE_COL_RECORD_TYPE, &n_type,
994 -1);
995 // FIXME: determine 'off', 'ri', ...
996 // Idea: simply store 'off' in model!
997 off = 42;
998 ri = NULL;
999 launch_edit_dialog (n_type, n_name,
1000 ri, off);
1001 g_free (n_name);
1002}
1003
1004
1005
1006/**
1414 * The user has selected a new record type. Update the 1007 * The user has selected a new record type. Update the
1415 * model and then start the 'edit' dialog. 1008 * model and then start the 'edit' dialog.
1416 * 1009 *
@@ -1425,14 +1018,17 @@ GNUNET_setup_gns_type_cellrenderercombo_edited_cb (GtkCellRendererCombo *combo,
1425 gchar *new_text, 1018 gchar *new_text,
1426 gpointer user_data) 1019 gpointer user_data)
1427{ 1020{
1428 GtkTreeSelection *sel;
1429 GtkTreeIter it; 1021 GtkTreeIter it;
1430 GtkTreeIter child;
1431 guint type; 1022 guint type;
1432 char *name_str; 1023 char *name_str;
1024 struct GNUNET_HashCode name_hash;
1025 struct RecordInfo *ri;
1433 1026
1434 if (0 == strcmp (new_text, _(NEW_RECORD_STR))) 1027 if (0 == strcmp (new_text, _(NEW_RECORD_STR)))
1028 {
1029 GNUNET_break (0);
1435 return; /* no record type was selected */ 1030 return; /* no record type was selected */
1031 }
1436 type = GNUNET_NAMESTORE_typename_to_number (new_text); 1032 type = GNUNET_NAMESTORE_typename_to_number (new_text);
1437 if (UINT32_MAX == type) 1033 if (UINT32_MAX == type)
1438 { 1034 {
@@ -1448,102 +1044,15 @@ GNUNET_setup_gns_type_cellrenderercombo_edited_cb (GtkCellRendererCombo *combo,
1448 gtk_tree_model_get (tm, &it, 1044 gtk_tree_model_get (tm, &it,
1449 GNS_TREESTORE_COL_NAME, &name_str, 1045 GNS_TREESTORE_COL_NAME, &name_str,
1450 -1); 1046 -1);
1451 gtk_tree_store_insert_with_values (ts, &child , &it, -1, 1047 if (NULL == name_str)
1452 GNS_TREESTORE_COL_NAME, name_str,
1453 GNS_TREESTORE_COL_NAME_IS_VISIBLE, FALSE,
1454 GNS_TREESTORE_COL_RECORD_TYPE, type,
1455 GNS_TREESTORE_COL_RECORD_TYPE_AS_STR, new_text,
1456 GNS_TREESTORE_COL_EXP_TIME_AS_STR, EXPIRE_NEVER_STRING,
1457 GNS_TREESTORE_COL_EXP_TIME, GNUNET_TIME_UNIT_FOREVER_ABS,
1458 GNS_TREESTORE_COL_EXP_TIME_IS_REL, FALSE,
1459 GNS_TREESTORE_COL_IS_RECORD_ROW, TRUE,
1460 GNS_TREESTORE_COL_NOT_DUMMY_ROW, TRUE,
1461 GNS_TREESTORE_COL_TYPE_IS_EDITABLE, FALSE,
1462 -1);
1463 /* select new row and start editing 'value' */
1464 gtk_tree_view_expand_row (tv, gtk_tree_model_get_path (tm, &it), 0);
1465 sel = gtk_tree_view_get_selection (tv);
1466 gtk_tree_selection_select_iter (sel, &child);
1467 g_free (name_str);
1468 edit_selected_row (GNUNET_NO);
1469}
1470
1471
1472/**
1473 * The user has toggled the 'public' checkmark of a cell. Update the
1474 * model.
1475 *
1476 * @param renderer updated renderer
1477 * @param path the path identifying the edited cell
1478 * @param user_data unused
1479 */
1480void
1481GNUNET_setup_gns_ispublic_cellrenderertoggle_toggled_cb (GtkCellRendererToggle *cell_renderer,
1482 gchar *path,
1483 gpointer user_data)
1484{
1485 GtkTreeIter it;
1486 gboolean value;
1487
1488 gtk_tree_model_get_iter_from_string (tm, &it, path);
1489 gtk_tree_model_get (tm, &it, GNS_TREESTORE_COL_IS_PUBLIC, &value, -1);
1490 gtk_tree_store_set (ts, &it, GNS_TREESTORE_COL_IS_PUBLIC, !value, -1);
1491 check_name_validity_and_commit (&it, NULL);
1492}
1493
1494
1495/**
1496 * The user has edited a 'expiration' cell. Update the model.
1497 *
1498 * @param renderer updated renderer
1499 * @param path the path identifying the edited cell
1500 * @param new_text the new expiration time
1501 * @param user_data unused
1502 */
1503void
1504GNUNET_setup_gns_expiration_cellrenderertext_edited_cb (GtkCellRendererText *renderer,
1505 gchar *path,
1506 gchar *new_text,
1507 gpointer user_data)
1508{
1509 GtkTreeIter it;
1510 struct GNUNET_TIME_Absolute abstime;
1511 struct GNUNET_TIME_Relative reltime;
1512
1513 if (NULL == new_text)
1514 return; /* can this happen? */
1515 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1516 "New expiration time: `%s'\n",
1517 new_text);
1518 gtk_tree_model_get_iter_from_string (tm, &it, path);
1519 if (GNUNET_OK ==
1520 GNUNET_STRINGS_fancy_time_to_absolute (new_text,
1521 &abstime))
1522 { 1048 {
1523 gtk_tree_store_set (ts, &it, 1049 GNUNET_break (0);
1524 GNS_TREESTORE_COL_EXP_TIME_AS_STR, new_text,
1525 GNS_TREESTORE_COL_EXP_TIME, abstime.abs_value,
1526 GNS_TREESTORE_COL_EXP_TIME_IS_REL, FALSE,
1527 GNS_TREESTORE_COL_EXP_TIME_COLOR, NULL,
1528 -1);
1529 check_name_validity_and_commit (&it, NULL);
1530 return;
1531 }
1532 if (GNUNET_OK ==
1533 GNUNET_STRINGS_fancy_time_to_relative (new_text,
1534 &reltime))
1535 {
1536 gtk_tree_store_set (ts, &it,
1537 GNS_TREESTORE_COL_EXP_TIME_AS_STR, new_text,
1538 GNS_TREESTORE_COL_EXP_TIME, reltime.rel_value,
1539 GNS_TREESTORE_COL_EXP_TIME_IS_REL, TRUE,
1540 GNS_TREESTORE_COL_EXP_TIME_COLOR, NULL,
1541 -1);
1542 check_name_validity_and_commit (&it, NULL);
1543 return; 1050 return;
1544 } 1051 }
1545 show_error_message (_("Invalid time value"), 1052 GNUNET_CRYPTO_hash (name_str, strlen (name_str), &name_hash);
1546 new_text); 1053 ri = GNUNET_CONTAINER_multihashmap_get (n2r, &name_hash);
1054 launch_edit_dialog (type, name_str, ri, UINT_MAX);
1055 g_free (name_str);
1547} 1056}
1548 1057
1549 1058
@@ -1563,7 +1072,6 @@ GNUNET_setup_gns_name_cellrenderertext_edited_cb (GtkCellRendererText *renderer,
1563 gpointer user_data) 1072 gpointer user_data)
1564{ 1073{
1565 GtkTreeIter it; 1074 GtkTreeIter it;
1566 GtkTreeIter child;
1567 gboolean not_dummy; 1075 gboolean not_dummy;
1568 char *name; 1076 char *name;
1569 1077
@@ -1587,55 +1095,31 @@ GNUNET_setup_gns_name_cellrenderertext_edited_cb (GtkCellRendererText *renderer,
1587 GNS_TREESTORE_COL_NOT_DUMMY_ROW, &not_dummy, 1095 GNS_TREESTORE_COL_NOT_DUMMY_ROW, &not_dummy,
1588 GNS_TREESTORE_COL_NAME, &name, 1096 GNS_TREESTORE_COL_NAME, &name,
1589 -1); 1097 -1);
1098 GNUNET_break (! not_dummy);
1099 GNUNET_break (0 == strcmp (name, _(NEW_NAME_STR)));
1100 g_free (name);
1590 1101
1591 if (! not_dummy) 1102 /* change dummy line to new name, then add new dummy */
1592 { 1103 gtk_tree_store_set (ts, &it,
1593 /* change dummy line to new name, then add new dummy */ 1104 GNS_TREESTORE_COL_NAME, new_text,
1594 gtk_tree_store_set (ts, &it, 1105 GNS_TREESTORE_COL_NAME_IS_VISIBLE, TRUE,
1595 GNS_TREESTORE_COL_NAME, new_text, 1106 GNS_TREESTORE_COL_RECORD_TYPE, 0,
1596 GNS_TREESTORE_COL_NAME_IS_VISIBLE, TRUE, 1107 GNS_TREESTORE_COL_RECORD_TYPE_AS_STR, _(NEW_RECORD_STR),
1597 GNS_TREESTORE_COL_RECORD_TYPE, 0, 1108 GNS_TREESTORE_COL_NOT_DUMMY_ROW, FALSE,
1598 GNS_TREESTORE_COL_RECORD_TYPE_AS_STR, _(NEW_RECORD_STR), 1109 GNS_TREESTORE_COL_IS_RECORD_ROW, TRUE,
1599 GNS_TREESTORE_COL_NOT_DUMMY_ROW, FALSE, 1110 GNS_TREESTORE_COL_TYPE_IS_EDITABLE, TRUE,
1600 GNS_TREESTORE_COL_IS_RECORD_ROW, TRUE, 1111 GNS_TREESTORE_COL_NAME_IS_EDITABLE, FALSE,
1601 GNS_TREESTORE_COL_TYPE_IS_EDITABLE, TRUE, 1112 -1);
1602 -1); 1113 /* add a new dummy line */
1603 check_name_validity_and_commit (&it, 1114 gtk_tree_store_insert_with_values (ts, &it,NULL, 0,
1604 name); 1115 GNS_TREESTORE_COL_NAME, _(NEW_NAME_STR),
1605 if (0 == strcmp (name, _(NEW_NAME_STR))) 1116 GNS_TREESTORE_COL_NAME_IS_VISIBLE, TRUE,
1606 { 1117 GNS_TREESTORE_COL_RECORD_TYPE, GNUNET_DNSPARSER_TYPE_A,
1607 /* add a new dummy line */ 1118 GNS_TREESTORE_COL_NOT_DUMMY_ROW, FALSE,
1608 gtk_tree_store_insert_with_values (ts, &it,NULL, 0, 1119 GNS_TREESTORE_COL_IS_RECORD_ROW, FALSE,
1609 GNS_TREESTORE_COL_NAME, _(NEW_NAME_STR), 1120 GNS_TREESTORE_COL_TYPE_IS_EDITABLE, FALSE,
1610 GNS_TREESTORE_COL_NAME_IS_VISIBLE, TRUE, 1121 GNS_TREESTORE_COL_NAME_IS_EDITABLE, TRUE,
1611 GNS_TREESTORE_COL_RECORD_TYPE, GNUNET_DNSPARSER_TYPE_A, 1122 -1);
1612 GNS_TREESTORE_COL_NOT_DUMMY_ROW, FALSE,
1613 GNS_TREESTORE_COL_IS_RECORD_ROW, FALSE,
1614 GNS_TREESTORE_COL_TYPE_IS_EDITABLE, FALSE,
1615 -1);
1616 }
1617 }
1618 else
1619 {
1620 /* update name */
1621 gtk_tree_store_set (ts, &it,
1622 GNS_TREESTORE_COL_NAME, new_text,
1623 -1);
1624
1625 if (gtk_tree_model_iter_children (tm, &child, &it))
1626 {
1627 do
1628 {
1629 gtk_tree_store_set (ts, &child,
1630 GNS_TREESTORE_COL_NAME, new_text,
1631 -1);
1632 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "New text for `%s' is `%s'\n", path, new_text);
1633 }
1634 while (gtk_tree_model_iter_next (tm, &child));
1635 }
1636
1637 check_name_validity_and_commit (&it, name);
1638 }
1639} 1123}
1640 1124
1641 1125
@@ -1682,7 +1166,7 @@ create_popup_menu ()
1682 * The zone treeview pop up menu is supposed to be created. 1166 * The zone treeview pop up menu is supposed to be created.
1683 * (Note: this is not the only method that might need to be 1167 * (Note: this is not the only method that might need to be
1684 * written to handle events to create pop up menus; right-clicks 1168 * written to handle events to create pop up menus; right-clicks
1685 * might need to be managed separately). 1169 * need to be managed separately).
1686 * 1170 *
1687 * @param widget the widget 1171 * @param widget the widget
1688 * @param user_data unused 1172 * @param user_data unused
@@ -1697,49 +1181,6 @@ GNUNET_setup_gns_main_treeview_popup_menu_cb (GtkWidget *widget,
1697 1181
1698 1182
1699/** 1183/**
1700 * Delete the selected row from the GtkTreeView (unless it is a dummy row).
1701 */
1702static void
1703delete_selected_row ()
1704{
1705 GtkTreeIter it;
1706 GtkTreeSelection *sel;
1707 int not_dummy;
1708 char *path;
1709
1710 sel = gtk_tree_view_get_selection(tv);
1711 if (! gtk_tree_selection_get_selected (sel, NULL, &it))
1712 return; /* nothing selected */
1713 gtk_tree_model_get (tm, &it,
1714 GNS_TREESTORE_COL_NOT_DUMMY_ROW, &not_dummy,
1715 -1);
1716 if (GNUNET_NO == not_dummy)
1717 return; /* do not delete the dummy line */
1718 path = gtk_tree_model_get_string_from_iter (tm, &it);
1719 remove_records_by_path (path);
1720 g_free (path);
1721}
1722
1723
1724/**
1725 * User selected 'edit' in the popup menu. Edit the
1726 * selected row.
1727 *
1728 * @param widget the GtkTreeView
1729 * @param user_data main window builder
1730 */
1731void
1732GNUNET_setup_gns_popup_edit_button_activate_cb (GtkWidget *widget,
1733 gpointer user_data)
1734{
1735 /* FIXME: not this easy! Row may still be a 'fresh' row!
1736 Need to check model to determine if argument should
1737 be YES or NO! */
1738 edit_selected_row (GNUNET_YES);
1739}
1740
1741
1742/**
1743 * A button was pressed in the GtkTreeView, check for right button and 1184 * A button was pressed in the GtkTreeView, check for right button and
1744 * if applicable create the popup menu. 1185 * if applicable create the popup menu.
1745 * 1186 *
@@ -1766,59 +1207,35 @@ GNUNET_setup_gns_main_treeview_button_press_event_cb (GtkWidget *widget,
1766/** 1207/**
1767 * User pushed a key in the GtkTreeView. Check for 'del' and if so, delete 1208 * User pushed a key in the GtkTreeView. Check for 'del' and if so, delete
1768 * the currently selected row. 1209 * the currently selected row.
1210 *
1211 * @param widget originating widget
1212 * @param event event information
1213 * @param user_data unused
1214 * @return TRUE if the key was processed ('del')
1769 */ 1215 */
1770gboolean 1216gboolean
1771GNUNET_setup_gns_main_treeview_key_press_event_cb (GtkWidget *widget, 1217GNUNET_setup_gns_main_treeview_key_press_event_cb (GtkWidget *widget,
1772 GdkEventKey *event, 1218 GdkEventKey *event,
1773 gpointer user_data) 1219 gpointer user_data)
1774{ 1220{
1775 /* Check for delete key */ 1221 GtkTreeIter it;
1776 if ( (GDK_KEY_PRESS == event->type) && 1222 GtkTreeSelection *sel;
1777 (GDK_KEY_Delete == event->keyval) ) 1223 int not_dummy;
1778 {
1779 delete_selected_row ();
1780 return TRUE;
1781 }
1782 return FALSE;
1783}
1784
1785 1224
1786/** 1225 /* Check for delete key */
1787 * Function called upon completion of a 'pseu' operation. 1226 if ( (GDK_KEY_PRESS != event->type) ||
1788 * 1227 (GDK_KEY_Delete != event->keyval) )
1789 * @param cls the 'struct PseuContext' of the operation that completed 1228 return FALSE;
1790 * @param success GNUNET_OK if the operation succeeded 1229 sel = gtk_tree_view_get_selection(tv);
1791 * @param emsg error message if the operation failed 1230 if (! gtk_tree_selection_get_selected (sel, NULL, &it))
1792 */ 1231 return TRUE; /* nothing selected */
1793static void 1232 gtk_tree_model_get (tm, &it,
1794pseu_change_cont (void *cls, 1233 GNS_TREESTORE_COL_NOT_DUMMY_ROW, &not_dummy,
1795 int32_t success, 1234 -1);
1796 const char *emsg) 1235 if (GNUNET_NO == not_dummy)
1797{ 1236 return TRUE; /* do not delete the dummy line */
1798 struct PseuContext *pc = cls; 1237 remove_records_by_iter (&it);
1799 GtkWidget *dialog; 1238 return TRUE;
1800 GtkWindow *main_window;
1801
1802 pc->qe = NULL;
1803 GNUNET_CONTAINER_DLL_remove (pc_head,
1804 pc_tail,
1805 pc);
1806 if (GNUNET_SYSERR == success)
1807 {
1808 main_window = GTK_WINDOW (GNUNET_SETUP_get_object ("GNUNET_setup_dialog"));
1809 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("New Pseudonym could not be set: `%s'\n"), emsg);
1810 dialog = gtk_message_dialog_new (main_window,
1811 GTK_DIALOG_DESTROY_WITH_PARENT,
1812 GTK_MESSAGE_ERROR,
1813 GTK_BUTTONS_CLOSE,
1814 _("New Pseudonym could not be set: `%s'\n"),
1815 emsg);
1816 g_signal_connect_swapped (dialog, "response",
1817 G_CALLBACK (gtk_widget_destroy),
1818 dialog);
1819 gtk_widget_show_all (dialog);
1820 resync_db ();
1821 }
1822} 1239}
1823 1240
1824 1241
@@ -1833,9 +1250,11 @@ void
1833GNUNET_setup_gns_pseu_entry_changed_cb (GtkEditable *editable, 1250GNUNET_setup_gns_pseu_entry_changed_cb (GtkEditable *editable,
1834 gpointer user_data) 1251 gpointer user_data)
1835{ 1252{
1836 struct GNUNET_NAMESTORE_RecordData rd;
1837 const gchar *pseu; 1253 const gchar *pseu;
1838 struct PseuContext *pc; 1254 struct RecordInfo *ri;
1255 struct GNUNET_HashCode hc;
1256 unsigned int rd_count;
1257 struct OperationContext *oc;
1839 1258
1840 pseu = gtk_entry_get_text (GTK_ENTRY (editable)); 1259 pseu = gtk_entry_get_text (GTK_ENTRY (editable));
1841 if (GNUNET_OK != 1260 if (GNUNET_OK !=
@@ -1849,46 +1268,60 @@ GNUNET_setup_gns_pseu_entry_changed_cb (GtkEditable *editable,
1849 pseu); 1268 pseu);
1850 return; 1269 return;
1851 } 1270 }
1852 if ( (pseu != NULL) && 1271 GNUNET_CRYPTO_hash ("+", 1, &hc);
1853 (0 != strcmp ("", pseu)) ) 1272 ri = GNUNET_CONTAINER_multihashmap_get (n2r, &hc);
1273 if (NULL == ri)
1274 rd_count = 0;
1275 else
1276 rd_count = ri->rd_count;
1277
1278 /* get old records, append new one or update/remove existing one */
1854 { 1279 {
1855 rd.record_type = GNUNET_NAMESTORE_TYPE_PSEU; 1280 struct GNUNET_NAMESTORE_RecordData rd_old[rd_count];
1856 rd.expiration_time = UINT64_MAX; 1281 struct GNUNET_NAMESTORE_RecordData rd_new[rd_count + 1];
1857 rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY; 1282 unsigned int off;
1858 rd.data_size = strlen (pseu) + 1; 1283 unsigned int total;
1859 rd.data = pseu; 1284
1860 pc = GNUNET_malloc (sizeof (struct PseuContext)); 1285 total = rd_count;
1861 GNUNET_CONTAINER_DLL_insert (pc_head, pc_tail, pc); 1286 if (NULL != ri)
1862#if 0 1287 GNUNET_break (GNUNET_OK ==
1863 /* FIXME: actually apply changes! */ 1288 GNUNET_NAMESTORE_records_deserialize (ri->data_size,
1864 pc->qe = GNUNET_NAMESTORE_record_create (namestore, pkey, "+", 1289 ri->data,
1865 &rd, 1290 rd_count,
1866 &pseu_change_cont, pc); 1291 rd_old));
1867#endif 1292 memcpy (rd_new, rd_old, sizeof (struct GNUNET_NAMESTORE_RecordData) * rd_count);
1293 for (off=0;off<rd_count;off++)
1294 if (GNUNET_NAMESTORE_TYPE_PSEU == rd_new[off].record_type)
1295 break;
1296 if (off == rd_count)
1297 total++;
1298 rd_new[off].record_type = GNUNET_NAMESTORE_TYPE_PSEU;
1299 rd_new[off].expiration_time = UINT64_MAX;
1300 rd_new[off].flags = GNUNET_NAMESTORE_RF_AUTHORITY;
1301 rd_new[off].data_size = strlen (pseu) + 1;
1302 rd_new[off].data = pseu;
1303 if ( (NULL == pseu) ||
1304 (0 == strlen (pseu)) )
1305 {
1306 rd_new[off] = rd_new[rd_count - 1];
1307 total--;
1308 }
1309 oc = GNUNET_new (struct OperationContext);
1310 GNUNET_CONTAINER_DLL_insert (oc_head, oc_tail, oc);
1311 oc->qe = GNUNET_NAMESTORE_record_put_by_authority (namestore,
1312 pkey, "+",
1313 total,
1314 rd_new,
1315 &operation_done_cont, oc);
1868 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1316 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1869 "New Pseudonym is `%s' %u\n", 1317 "New Pseudonym is `%s' %u\n",
1870 (char *) rd.data, rd.data_size); 1318 (char *) pseu, rd_new[off].data_size);
1871 GNUNET_free_non_null (current_pseudonym);
1872 current_pseudonym = GNUNET_strdup (pseu);
1873 }
1874 else if (NULL != current_pseudonym)
1875 {
1876 rd.record_type = GNUNET_NAMESTORE_TYPE_PSEU;
1877 rd.expiration_time = UINT64_MAX;
1878 rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY;
1879 rd.data_size = strlen (current_pseudonym) + 1;
1880 rd.data = current_pseudonym;
1881 pc = GNUNET_malloc (sizeof (struct PseuContext));
1882 GNUNET_CONTAINER_DLL_insert (pc_head, pc_tail, pc);
1883#if 0
1884 /* FIXME: actually apply changes! */
1885 pc->qe = GNUNET_NAMESTORE_record_remove (namestore, pkey, "+",
1886 &rd,
1887 &pseu_change_cont, pc);
1888#endif
1889 gtk_entry_set_text (GTK_ENTRY(editable), "");
1890 GNUNET_free_non_null (current_pseudonym); 1319 GNUNET_free_non_null (current_pseudonym);
1891 current_pseudonym = NULL; 1320 if ( (NULL != pseu) &&
1321 (0 != strlen (pseu)) )
1322 current_pseudonym = GNUNET_strdup (pseu);
1323 else
1324 current_pseudonym = NULL;
1892 } 1325 }
1893#if HAVE_QRENCODE_H 1326#if HAVE_QRENCODE_H
1894 setup_qrcode (); 1327 setup_qrcode ();
@@ -1925,13 +1358,8 @@ GNUNET_setup_gns_public_key_copy_button_clicked_cb (GtkButton *button,
1925static void 1358static void
1926zone_sync_proc (void *cls) 1359zone_sync_proc (void *cls)
1927{ 1360{
1928 GtkEntry *pseu_entry;
1929
1930 pseu_entry = GTK_ENTRY((GNUNET_SETUP_get_object ("GNUNET_setup_gns_pseu_entry")));
1931 if (0 == strcmp (current_zone_option, "ZONEKEY")) 1361 if (0 == strcmp (current_zone_option, "ZONEKEY"))
1932 gtk_widget_show (GTK_WIDGET (GNUNET_SETUP_get_object ("GNUNET_setup_gns_pseu_hbox"))); 1362 gtk_widget_show (GTK_WIDGET (GNUNET_SETUP_get_object ("GNUNET_setup_gns_pseu_hbox")));
1933 GNUNET_setup_gns_pseu_entry_changed_cb (GTK_EDITABLE (pseu_entry),
1934 NULL);
1935#if HAVE_QRENCODE_H 1363#if HAVE_QRENCODE_H
1936 setup_qrcode (); 1364 setup_qrcode ();
1937 gtk_widget_show (GTK_WIDGET (GNUNET_SETUP_get_object ("GNUNET_setup_gns_qr_image"))); 1365 gtk_widget_show (GTK_WIDGET (GNUNET_SETUP_get_object ("GNUNET_setup_gns_qr_image")));
@@ -1952,9 +1380,6 @@ zone_sync_proc (void *cls)
1952 * Function called for each record in the current zone. Update the 1380 * Function called for each record in the current zone. Update the
1953 * widgets accordingly. 1381 * widgets accordingly.
1954 * 1382 *
1955 * FIXME: we need to UPDATE records if an existing record is changed,
1956 * not merely append!
1957 *
1958 * @param NULL 1383 * @param NULL
1959 * @param zone_key public key of the zone 1384 * @param zone_key public key of the zone
1960 * @param freshness when does the corresponding block in the DHT expire (until 1385 * @param freshness when does the corresponding block in the DHT expire (until
@@ -1976,6 +1401,8 @@ zone_iteration_proc (void *cls,
1976 const struct GNUNET_NAMESTORE_RecordData *rd, 1401 const struct GNUNET_NAMESTORE_RecordData *rd,
1977 const struct GNUNET_CRYPTO_EccSignature *signature) 1402 const struct GNUNET_CRYPTO_EccSignature *signature)
1978{ 1403{
1404 GtkTreeRowReference *rr;
1405 GtkTreePath *path;
1979 GtkTreeIter iter_name; 1406 GtkTreeIter iter_name;
1980 GtkTreeIter iter_record; 1407 GtkTreeIter iter_record;
1981 int c; 1408 int c;
@@ -1987,6 +1414,8 @@ zone_iteration_proc (void *cls,
1987 guint64 exp_t; 1414 guint64 exp_t;
1988 struct GNUNET_CRYPTO_ShortHashAsciiEncoded shenc; 1415 struct GNUNET_CRYPTO_ShortHashAsciiEncoded shenc;
1989 GtkEntry *pseu_entry; 1416 GtkEntry *pseu_entry;
1417 struct GNUNET_HashCode name_hash;
1418 struct RecordInfo *ri;
1990 1419
1991 if ((NULL == zone_key) && (NULL == name)) 1420 if ((NULL == zone_key) && (NULL == name))
1992 { 1421 {
@@ -2007,18 +1436,78 @@ zone_iteration_proc (void *cls,
2007 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1436 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2008 "Zone `%s' iteration result `%s', %u records\n", 1437 "Zone `%s' iteration result `%s', %u records\n",
2009 &shenc, name, rd_count); 1438 &shenc, name, rd_count);
2010 gtk_tree_store_append (ts, &iter_name, NULL); 1439 GNUNET_CRYPTO_hash (name,
2011 gtk_tree_store_set (ts, &iter_name, 1440 strlen (name),
2012 GNS_TREESTORE_COL_NAME, name, 1441 &name_hash);
2013 GNS_TREESTORE_COL_NAME_IS_VISIBLE, TRUE, 1442 ri = GNUNET_CONTAINER_multihashmap_get (n2r, &name_hash);
2014 GNS_TREESTORE_COL_RECORD_TYPE, GNUNET_NAMESTORE_TYPE_ANY, 1443 if (NULL != ri)
2015 GNS_TREESTORE_COL_RECORD_TYPE_AS_STR, _(NEW_RECORD_STR), 1444 {
2016 GNS_TREESTORE_COL_IS_RECORD_ROW, TRUE, 1445 rr = ri->rr;
2017 GNS_TREESTORE_COL_NOT_DUMMY_ROW, FALSE, 1446 path = gtk_tree_row_reference_get_path (rr);
2018 GNS_TREESTORE_COL_TYPE_IS_EDITABLE, TRUE, 1447 GNUNET_assert (gtk_tree_model_get_iter (tm,
2019 -1); 1448 &iter_name,
2020 1449 path));
2021 /* Append elements for records */ 1450 gtk_tree_path_free (path);
1451 /* remove all records, we'll re-add those that are left next */
1452 if (gtk_tree_model_iter_children (tm, &iter_record, &iter_name))
1453 {
1454 do
1455 {
1456 gtk_tree_store_remove (ts, &iter_record);
1457 }
1458 while (gtk_tree_model_iter_next (tm, &iter_record));
1459 }
1460 }
1461 else
1462 {
1463 ri = GNUNET_new (struct RecordInfo);
1464 gtk_tree_store_append (ts, &iter_name, NULL);
1465 gtk_tree_store_set (ts, &iter_name,
1466 GNS_TREESTORE_COL_NAME, name,
1467 GNS_TREESTORE_COL_NAME_IS_VISIBLE, TRUE,
1468 GNS_TREESTORE_COL_RECORD_TYPE, GNUNET_NAMESTORE_TYPE_ANY,
1469 GNS_TREESTORE_COL_RECORD_TYPE_AS_STR, _(NEW_RECORD_STR),
1470 GNS_TREESTORE_COL_IS_RECORD_ROW, TRUE,
1471 GNS_TREESTORE_COL_NOT_DUMMY_ROW, FALSE,
1472 GNS_TREESTORE_COL_TYPE_IS_EDITABLE, TRUE,
1473 -1);
1474
1475 path = gtk_tree_model_get_path (tm,
1476 &iter_name);
1477 rr = gtk_tree_row_reference_new (tm,
1478 path);
1479 ri->rr = rr;
1480 ri->name = GNUNET_strdup (name);
1481 gtk_tree_path_free (path);
1482 GNUNET_assert (GNUNET_OK ==
1483 GNUNET_CONTAINER_multihashmap_put (n2r,
1484 &name_hash,
1485 ri,
1486 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1487 }
1488 if (0 == rd_count)
1489 {
1490 /* all records removed, remove name as well */
1491 gtk_tree_store_remove (ts, &iter_name);
1492 GNUNET_assert (GNUNET_YES ==
1493 GNUNET_CONTAINER_multihashmap_remove (n2r, &name_hash, ri));
1494 gtk_tree_row_reference_free (rr);
1495 GNUNET_free (ri->name);
1496 GNUNET_free_non_null (ri->data);
1497 GNUNET_free (ri);
1498 return;
1499 }
1500 /* update record info serialized version of the records */
1501 GNUNET_free_non_null (ri->data);
1502 ri->rd_count = rd_count;
1503 ri->data_size = GNUNET_NAMESTORE_records_get_size (rd_count, rd);
1504 if (0 != ri->data_size)
1505 ri->data = GNUNET_malloc (ri->data_size);
1506 GNUNET_break (GNUNET_OK ==
1507 GNUNET_NAMESTORE_records_serialize (rd_count, rd,
1508 ri->data_size, ri->data));
1509
1510 /* Append elements for records in tree view */
2022 for (c = 0; c < rd_count; c ++) 1511 for (c = 0; c < rd_count; c ++)
2023 { 1512 {
2024 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1513 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -2065,23 +1554,23 @@ zone_iteration_proc (void *cls,
2065 { 1554 {
2066 pseu_entry = GTK_ENTRY((GNUNET_SETUP_get_object ("GNUNET_setup_gns_pseu_entry"))); 1555 pseu_entry = GTK_ENTRY((GNUNET_SETUP_get_object ("GNUNET_setup_gns_pseu_entry")));
2067 gtk_entry_set_text (pseu_entry, val); 1556 gtk_entry_set_text (pseu_entry, val);
1557#if HAVE_QRENCODE_H
1558 setup_qrcode ();
1559#endif
2068 } 1560 }
2069 else 1561 gtk_tree_store_insert_with_values (ts, &iter_record , &iter_name, 0,
2070 { 1562 GNS_TREESTORE_COL_NAME, name,
2071 gtk_tree_store_insert_with_values (ts, &iter_record , &iter_name, 0, 1563 GNS_TREESTORE_COL_NAME_IS_VISIBLE, FALSE,
2072 GNS_TREESTORE_COL_NAME, name, 1564 GNS_TREESTORE_COL_RECORD_TYPE, rd[c].record_type,
2073 GNS_TREESTORE_COL_NAME_IS_VISIBLE, FALSE, 1565 GNS_TREESTORE_COL_RECORD_TYPE_AS_STR, type_str,
2074 GNS_TREESTORE_COL_RECORD_TYPE, rd[c].record_type, 1566 GNS_TREESTORE_COL_IS_PUBLIC, public,
2075 GNS_TREESTORE_COL_RECORD_TYPE_AS_STR, type_str, 1567 GNS_TREESTORE_COL_EXP_TIME, exp_t,
2076 GNS_TREESTORE_COL_IS_PUBLIC, public, 1568 GNS_TREESTORE_COL_EXP_TIME_AS_STR, exp,
2077 GNS_TREESTORE_COL_EXP_TIME, exp_t, 1569 GNS_TREESTORE_COL_EXP_TIME_IS_REL, time_is_relative,
2078 GNS_TREESTORE_COL_EXP_TIME_AS_STR, exp, 1570 GNS_TREESTORE_COL_VAL_AS_STR, val,
2079 GNS_TREESTORE_COL_EXP_TIME_IS_REL, time_is_relative, 1571 GNS_TREESTORE_COL_IS_RECORD_ROW, TRUE,
2080 GNS_TREESTORE_COL_VAL_AS_STR, val, 1572 GNS_TREESTORE_COL_NOT_DUMMY_ROW, TRUE,
2081 GNS_TREESTORE_COL_IS_RECORD_ROW, TRUE, 1573 -1);
2082 GNS_TREESTORE_COL_NOT_DUMMY_ROW, TRUE,
2083 -1);
2084 }
2085 GNUNET_free (type_str); 1574 GNUNET_free (type_str);
2086 GNUNET_free (val); 1575 GNUNET_free (val);
2087 } 1576 }
@@ -2099,7 +1588,7 @@ static void
2099load_zone (const char *zonename) 1588load_zone (const char *zonename)
2100{ 1589{
2101 char *keyfile; 1590 char *keyfile;
2102 struct GNUNET_CRYPTO_RsaPrivateKey *pk; 1591 struct GNUNET_CRYPTO_EccPrivateKey *pk;
2103 char *emsg; 1592 char *emsg;
2104 struct GNUNET_CRYPTO_ShortHashAsciiEncoded shenc; 1593 struct GNUNET_CRYPTO_ShortHashAsciiEncoded shenc;
2105 char *label; 1594 char *label;
@@ -2130,7 +1619,7 @@ load_zone (const char *zonename)
2130 return; 1619 return;
2131 } 1620 }
2132 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using `%s'\n", keyfile); 1621 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using `%s'\n", keyfile);
2133 pk = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile); 1622 pk = GNUNET_CRYPTO_ecc_key_create_from_file (keyfile);
2134 GNUNET_free (keyfile); 1623 GNUNET_free (keyfile);
2135 if (NULL == pk) 1624 if (NULL == pk)
2136 { 1625 {
@@ -2139,9 +1628,9 @@ load_zone (const char *zonename)
2139 return; 1628 return;
2140 } 1629 }
2141 pkey = pk; 1630 pkey = pk;
2142 GNUNET_CRYPTO_rsa_key_get_public (pkey, &pubkey); 1631 GNUNET_CRYPTO_ecc_key_get_public (pkey, &pubkey);
2143 GNUNET_CRYPTO_short_hash (&pubkey, 1632 GNUNET_CRYPTO_short_hash (&pubkey,
2144 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), 1633 sizeof (struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded),
2145 &zone); 1634 &zone);
2146 GNUNET_CRYPTO_short_hash_to_enc(&zone, &shenc); 1635 GNUNET_CRYPTO_short_hash_to_enc(&zone, &shenc);
2147 1636
@@ -2158,9 +1647,13 @@ load_zone (const char *zonename)
2158 GNS_TREESTORE_COL_RECORD_TYPE, GNUNET_DNSPARSER_TYPE_A, 1647 GNS_TREESTORE_COL_RECORD_TYPE, GNUNET_DNSPARSER_TYPE_A,
2159 GNS_TREESTORE_COL_IS_RECORD_ROW, FALSE, 1648 GNS_TREESTORE_COL_IS_RECORD_ROW, FALSE,
2160 GNS_TREESTORE_COL_NOT_DUMMY_ROW, FALSE, 1649 GNS_TREESTORE_COL_NOT_DUMMY_ROW, FALSE,
2161 GNS_TREESTORE_COL_TYPE_IS_EDITABLE, TRUE, 1650 GNS_TREESTORE_COL_TYPE_IS_EDITABLE, FALSE,
1651 GNS_TREESTORE_COL_NAME_IS_EDITABLE, TRUE,
2162 -1); 1652 -1);
2163 /* Load zone from namestore! */ 1653 /* Load zone from namestore! */
1654#if HAVE_QRENCODE_H
1655 setup_qrcode ();
1656#endif
2164 zmon = GNUNET_NAMESTORE_zone_monitor_start (cfg, &zone, 1657 zmon = GNUNET_NAMESTORE_zone_monitor_start (cfg, &zone,
2165 &zone_iteration_proc, 1658 &zone_iteration_proc,
2166 &zone_sync_proc, 1659 &zone_sync_proc,
@@ -2238,42 +1731,67 @@ GNUNET_SETUP_gns_init ()
2238 ts = GTK_TREE_STORE (GNUNET_SETUP_get_object ("GNUNET_setup_gns_treestore")); 1731 ts = GTK_TREE_STORE (GNUNET_SETUP_get_object ("GNUNET_setup_gns_treestore"));
2239 tv = GTK_TREE_VIEW (GNUNET_SETUP_get_object ("GNUNET_setup_gns_main_treeview")); 1732 tv = GTK_TREE_VIEW (GNUNET_SETUP_get_object ("GNUNET_setup_gns_main_treeview"));
2240 tm = GTK_TREE_MODEL (ts); 1733 tm = GTK_TREE_MODEL (ts);
1734 n2r = GNUNET_CONTAINER_multihashmap_create (128, GNUNET_NO);
2241 load_zone ("ZONEKEY"); 1735 load_zone ("ZONEKEY");
2242} 1736}
2243 1737
2244 1738
2245/** 1739/**
1740 * Release the record info.
1741 *
1742 * @param cls NULL
1743 * @param key unused
1744 * @param value a RecordInfo to release
1745 * @return GNUNET_OK (continue to iterate)
1746 */
1747static int
1748release_ri (void *cls,
1749 const struct GNUNET_HashCode *key,
1750 void *value)
1751{
1752 struct RecordInfo *ri = value;
1753
1754 gtk_tree_row_reference_free (ri->rr);
1755 GNUNET_free_non_null (ri->data);
1756 GNUNET_free (ri->name);
1757 GNUNET_free (ri);
1758 return GNUNET_OK;
1759}
1760
1761
1762/**
2246 * Disconnect from the namestore and clean up the main 1763 * Disconnect from the namestore and clean up the main
2247 * GNS tree view. 1764 * GNS tree view.
2248 */ 1765 */
2249void 1766void
2250GNUNET_SETUP_gns_done () 1767GNUNET_SETUP_gns_done ()
2251{ 1768{
2252 struct EditDialogContext *edc; 1769 struct OperationContext *oc;
2253 1770
2254 gtk_widget_show (GTK_WIDGET (GNUNET_SETUP_get_object ("GNUNET_setup_gns_status_label"))); 1771 gtk_widget_show (GTK_WIDGET (GNUNET_SETUP_get_object ("GNUNET_setup_gns_status_label")));
2255 gtk_widget_hide (GTK_WIDGET (GNUNET_SETUP_get_object ("GNUNET_setup_gns_main_scrolledwindow"))); 1772 gtk_widget_hide (GTK_WIDGET (GNUNET_SETUP_get_object ("GNUNET_setup_gns_main_scrolledwindow")));
2256 gtk_tree_store_clear (ts);
2257 if (NULL != zmon) 1773 if (NULL != zmon)
2258 { 1774 {
2259 GNUNET_NAMESTORE_zone_monitor_stop (zmon); 1775 GNUNET_NAMESTORE_zone_monitor_stop (zmon);
2260 zmon = NULL; 1776 zmon = NULL;
2261 } 1777 }
2262 while (NULL != uc_head) 1778 while (NULL != (oc = oc_head))
2263 free_update_context (uc_head);
2264 while (NULL != rc_head)
2265 free_remove_context (rc_head);
2266 while (NULL != (edc = edc_head))
2267 { 1779 {
2268 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1780 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2269 _("Setup shutdown before all records could be written. Record lost!\n")); 1781 _("A pending namestore operation was not transmitted to the namestore.\n"));
2270 if (NULL != edc->qe) 1782 GNUNET_CONTAINER_DLL_remove (oc_head, oc_tail, oc);
2271 GNUNET_NAMESTORE_cancel (edc->qe); 1783 GNUNET_NAMESTORE_cancel (oc->qe);
2272 if (NULL != edc->rkgc) 1784 GNUNET_free (oc);
2273 GNUNET_CRYPTO_rsa_key_create_stop (edc->rkgc); 1785 }
2274 GNUNET_CONTAINER_DLL_remove (edc_head, edc_tail, edc); 1786 if (NULL != n2r)
2275 free_edit_dialog_context (edc); 1787 {
1788 GNUNET_CONTAINER_multihashmap_iterate (n2r,
1789 &release_ri,
1790 NULL);
1791 GNUNET_CONTAINER_multihashmap_destroy (n2r);
1792 n2r = NULL;
2276 } 1793 }
1794 gtk_tree_store_clear (ts);
2277 if (NULL != namestore) 1795 if (NULL != namestore)
2278 { 1796 {
2279 GNUNET_NAMESTORE_disconnect (namestore); 1797 GNUNET_NAMESTORE_disconnect (namestore);
@@ -2281,7 +1799,7 @@ GNUNET_SETUP_gns_done ()
2281 } 1799 }
2282 if (NULL != pkey) 1800 if (NULL != pkey)
2283 { 1801 {
2284 GNUNET_CRYPTO_rsa_key_free (pkey); 1802 GNUNET_CRYPTO_ecc_key_free (pkey);
2285 pkey = NULL; 1803 pkey = NULL;
2286 } 1804 }
2287 if (NULL != current_pseudonym) 1805 if (NULL != current_pseudonym)