diff options
Diffstat (limited to 'src/setup/gnunet-setup-gns.c')
-rw-r--r-- | src/setup/gnunet-setup-gns.c | 431 |
1 files changed, 237 insertions, 194 deletions
diff --git a/src/setup/gnunet-setup-gns.c b/src/setup/gnunet-setup-gns.c index 3578a002..1ee8531d 100644 --- a/src/setup/gnunet-setup-gns.c +++ b/src/setup/gnunet-setup-gns.c | |||
@@ -153,7 +153,12 @@ enum GNSTreestoreColumn | |||
153 | /** | 153 | /** |
154 | * A gboolean; TRUE if the name is editable (dummy line). | 154 | * A gboolean; TRUE if the name is editable (dummy line). |
155 | */ | 155 | */ |
156 | GNS_TREESTORE_COL_NAME_IS_EDITABLE | 156 | GNS_TREESTORE_COL_NAME_IS_EDITABLE, |
157 | |||
158 | /** | ||
159 | * A guint; offset of this record in the array. | ||
160 | */ | ||
161 | GNS_TREESTORE_COL_RECORD_OFFSET | ||
157 | }; | 162 | }; |
158 | 163 | ||
159 | 164 | ||
@@ -568,7 +573,6 @@ clear_zone_view () | |||
568 | } | 573 | } |
569 | 574 | ||
570 | 575 | ||
571 | |||
572 | /** | 576 | /** |
573 | * Load a particular zone into the main tree view. | 577 | * Load a particular zone into the main tree view. |
574 | * | 578 | * |
@@ -593,7 +597,7 @@ show_error_message (const char *title, | |||
593 | GtkWindow *main_window; | 597 | GtkWindow *main_window; |
594 | GtkDialog *dialog; | 598 | GtkDialog *dialog; |
595 | 599 | ||
596 | /* FIXME: consider replacing with widget in the main window */ | 600 | /* TODO: consider replacing with widget in the main window */ |
597 | main_window = GTK_WINDOW (GNUNET_SETUP_get_object ("GNUNET_setup_dialog")); | 601 | main_window = GTK_WINDOW (GNUNET_SETUP_get_object ("GNUNET_setup_dialog")); |
598 | dialog = GTK_DIALOG(gtk_message_dialog_new (main_window, | 602 | dialog = GTK_DIALOG(gtk_message_dialog_new (main_window, |
599 | GTK_DIALOG_DESTROY_WITH_PARENT, | 603 | GTK_DIALOG_DESTROY_WITH_PARENT, |
@@ -608,157 +612,6 @@ show_error_message (const char *title, | |||
608 | 612 | ||
609 | 613 | ||
610 | /** | 614 | /** |
611 | * Remove selected record from the namestore. | ||
612 | * | ||
613 | * @param edc identifying record to remove | ||
614 | */ | ||
615 | static void | ||
616 | remove_record_at_offset (struct EditDialogContext *edc) | ||
617 | { | ||
618 | struct RecordInfo *ri = edc->ri; | ||
619 | struct OperationContext *oc; | ||
620 | |||
621 | if ( (NULL == ri) || | ||
622 | (edc->off >= ri->rd_count) ) | ||
623 | { | ||
624 | GNUNET_break (0); | ||
625 | return; | ||
626 | } | ||
627 | |||
628 | { | ||
629 | struct GNUNET_NAMESTORE_RecordData rd_old[ri->rd_count]; | ||
630 | struct GNUNET_NAMESTORE_RecordData rd_new[ri->rd_count - 1]; | ||
631 | |||
632 | /* Removing a single record */ | ||
633 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
634 | "Removing single record for name `%s'\n", | ||
635 | edc->name); | ||
636 | GNUNET_break (GNUNET_OK == | ||
637 | GNUNET_NAMESTORE_records_deserialize (ri->data_size, | ||
638 | ri->data, | ||
639 | ri->rd_count, | ||
640 | rd_old)); | ||
641 | GNUNET_assert (edc->off < ri->rd_count); | ||
642 | memcpy (rd_new, rd_old, (ri->rd_count - 1) * sizeof (struct GNUNET_NAMESTORE_RecordData)); | ||
643 | rd_new[edc->off] = rd_old[ri->rd_count - 1]; | ||
644 | oc = GNUNET_new (struct OperationContext); | ||
645 | GNUNET_CONTAINER_DLL_insert (oc_head, oc_tail, oc); | ||
646 | oc->qe = GNUNET_NAMESTORE_record_put_by_authority (namestore, | ||
647 | pkey, edc->name, | ||
648 | ri->rd_count - 1, | ||
649 | rd_new, | ||
650 | &operation_done_cont, oc); | ||
651 | } | ||
652 | } | ||
653 | |||
654 | |||
655 | |||
656 | /** | ||
657 | * Remove a record from the model. If the given iter identifies an | ||
658 | * entire 'name', remove all records under that name. | ||
659 | * | ||
660 | * @param iter identifying record(s) to remove | ||
661 | */ | ||
662 | static void | ||
663 | remove_records_by_iter (GtkTreeIter *iter) | ||
664 | { | ||
665 | GtkTreeIter parent; | ||
666 | char *name; | ||
667 | struct GNUNET_HashCode name_hash; | ||
668 | struct RecordInfo *ri; | ||
669 | struct OperationContext *oc; | ||
670 | |||
671 | gtk_tree_model_get (tm, iter, | ||
672 | GNS_TREESTORE_COL_NAME, &name, | ||
673 | -1); | ||
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) ) | ||
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 | |||
693 | /* Removing a single record */ | ||
694 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
695 | "Removing single record for name `%s'\n", | ||
696 | 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, | ||
703 | GNS_TREESTORE_COL_RECORD_TYPE, &n_type, | ||
704 | GNS_TREESTORE_COL_IS_PUBLIC, &n_public, | ||
705 | GNS_TREESTORE_COL_EXP_TIME, &n_exp_time, | ||
706 | GNS_TREESTORE_COL_EXP_TIME_IS_REL, &n_is_relative, | ||
707 | GNS_TREESTORE_COL_IS_SHADOW, &n_is_shadow, | ||
708 | GNS_TREESTORE_COL_VAL_AS_STR, &n_value, | ||
709 | -1); | ||
710 | /* valid name */ | ||
711 | if (n_public) | ||
712 | rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY; | ||
713 | else | ||
714 | rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY | GNUNET_NAMESTORE_RF_PRIVATE; | ||
715 | if (n_is_relative) | ||
716 | rd.flags |= GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION; | ||
717 | if (n_is_shadow) | ||
718 | rd.flags |= GNUNET_NAMESTORE_RF_SHADOW_RECORD; | ||
719 | rd.record_type = n_type; | ||
720 | rd.expiration_time = n_exp_time; | ||
721 | if (GNUNET_OK != | ||
722 | GNUNET_NAMESTORE_string_to_value (n_type, n_value, | ||
723 | (void**)&rd.data, &rd.data_size)) | ||
724 | { | ||
725 | /* can't remove, value invalid */ | ||
726 | GNUNET_assert (0); | ||
727 | g_free (n_value); | ||
728 | g_free (name); | ||
729 | return; | ||
730 | } | ||
731 | for (off=0;off<ri->rd_count;off++) | ||
732 | if (GNUNET_YES == | ||
733 | GNUNET_NAMESTORE_records_cmp (&rd, | ||
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); | ||
746 | g_free (n_value); | ||
747 | } | ||
748 | else | ||
749 | { | ||
750 | oc = GNUNET_new (struct OperationContext); | ||
751 | GNUNET_CONTAINER_DLL_insert (oc_head, oc_tail, oc); | ||
752 | oc->qe = GNUNET_NAMESTORE_record_put_by_authority (namestore, | ||
753 | pkey, name, | ||
754 | 0, NULL, | ||
755 | &operation_done_cont, oc); | ||
756 | } | ||
757 | g_free (name); | ||
758 | } | ||
759 | |||
760 | |||
761 | /** | ||
762 | * Release resources of an edit dialog context. | 615 | * Release resources of an edit dialog context. |
763 | * | 616 | * |
764 | * @param edc resources to free | 617 | * @param edc resources to free |
@@ -784,13 +637,68 @@ static void | |||
784 | edit_dialog_continuation (struct EditDialogContext *edc, | 637 | edit_dialog_continuation (struct EditDialogContext *edc, |
785 | GtkResponseType ret) | 638 | GtkResponseType ret) |
786 | { | 639 | { |
640 | struct RecordInfo *ri = edc->ri; | ||
641 | unsigned int rd_count = (NULL == ri) ? 0 : ri->rd_count; | ||
642 | struct GNUNET_NAMESTORE_RecordData rd_old[rd_count]; | ||
643 | struct GNUNET_NAMESTORE_RecordData rd; | ||
644 | void *data; | ||
645 | size_t data_size; | ||
646 | struct OperationContext *oc; | ||
647 | |||
648 | if ( (NULL != ri) && | ||
649 | (GNUNET_OK != | ||
650 | GNUNET_NAMESTORE_records_deserialize (ri->data_size, | ||
651 | ri->data, | ||
652 | ri->rd_count, | ||
653 | rd_old)) ) | ||
654 | { | ||
655 | GNUNET_break (0); | ||
656 | free_edit_dialog_context (edc); | ||
657 | return; | ||
658 | } | ||
659 | if ( (GTK_RESPONSE_CANCEL == ret) || | ||
660 | (GTK_RESPONSE_DELETE_EVENT == ret) ) | ||
661 | { | ||
662 | free_edit_dialog_context (edc); | ||
663 | return; | ||
664 | } | ||
665 | if (GNUNET_OK != GNUNET_NAMESTORE_string_to_value (edc->record_type, edc->n_value, | ||
666 | &data, &data_size)) | ||
667 | { | ||
668 | GNUNET_break (0); | ||
669 | free_edit_dialog_context (edc); | ||
670 | return; | ||
671 | } | ||
672 | if (edc->n_public) | ||
673 | rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY; | ||
674 | else | ||
675 | rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY | GNUNET_NAMESTORE_RF_PRIVATE; | ||
676 | if (edc->n_is_shadow) | ||
677 | rd.flags |= GNUNET_NAMESTORE_RF_SHADOW_RECORD; | ||
678 | rd.record_type = edc->record_type; | ||
679 | rd.expiration_time = edc->n_exp_time; | ||
680 | if (edc->n_is_relative) | ||
681 | rd.flags |= GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION; | ||
682 | rd.data_size = data_size; | ||
683 | rd.data = data; | ||
787 | switch (ret) | 684 | switch (ret) |
788 | { | 685 | { |
789 | case GTK_RESPONSE_REJECT: /* code for 'delete' */ | 686 | case GTK_RESPONSE_REJECT: /* code for 'delete' */ |
790 | if (GNUNET_YES == edc->old_record_in_namestore) | 687 | if (GNUNET_YES == edc->old_record_in_namestore) |
791 | { | 688 | { |
792 | /* remove item from tree view and namestore */ | 689 | /* remove item from tree view and namestore */ |
793 | remove_record_at_offset (edc); | 690 | struct GNUNET_NAMESTORE_RecordData rd_new[rd_count - 1]; |
691 | |||
692 | GNUNET_assert (NULL != ri); | ||
693 | memcpy (rd_new, rd_old, (rd_count - 1) * sizeof (struct GNUNET_NAMESTORE_RecordData)); | ||
694 | rd_new[edc->off] = rd_old[rd_count - 1]; | ||
695 | oc = GNUNET_new (struct OperationContext); | ||
696 | GNUNET_CONTAINER_DLL_insert (oc_head, oc_tail, oc); | ||
697 | oc->qe = GNUNET_NAMESTORE_record_put_by_authority (namestore, | ||
698 | pkey, edc->name, | ||
699 | rd_count + 1, | ||
700 | rd_new, | ||
701 | &operation_done_cont, oc); | ||
794 | } | 702 | } |
795 | else | 703 | else |
796 | { | 704 | { |
@@ -798,10 +706,6 @@ edit_dialog_continuation (struct EditDialogContext *edc, | |||
798 | GNUNET_break (0); | 706 | GNUNET_break (0); |
799 | } | 707 | } |
800 | break; | 708 | break; |
801 | case GTK_RESPONSE_CANCEL: | ||
802 | case GTK_RESPONSE_DELETE_EVENT: /* window deletion counts as 'cancel' */ | ||
803 | /* do nothing */ | ||
804 | break; | ||
805 | case GTK_RESPONSE_OK: | 709 | case GTK_RESPONSE_OK: |
806 | /* update model */ | 710 | /* update model */ |
807 | if (0 == strcmp (edc->new_zone_option, | 711 | if (0 == strcmp (edc->new_zone_option, |
@@ -809,13 +713,32 @@ edit_dialog_continuation (struct EditDialogContext *edc, | |||
809 | { | 713 | { |
810 | if (GNUNET_YES == edc->old_record_in_namestore) | 714 | if (GNUNET_YES == edc->old_record_in_namestore) |
811 | { | 715 | { |
812 | /* replace record in database with that from model */ | 716 | struct GNUNET_NAMESTORE_RecordData rd_new[rd_count]; |
813 | GNUNET_break (0); // not implemented | 717 | |
718 | GNUNET_assert (NULL != ri); | ||
719 | memcpy (rd_new, rd_old, rd_count * sizeof (struct GNUNET_NAMESTORE_RecordData)); | ||
720 | rd_new[edc->off] = rd; | ||
721 | oc = GNUNET_new (struct OperationContext); | ||
722 | GNUNET_CONTAINER_DLL_insert (oc_head, oc_tail, oc); | ||
723 | oc->qe = GNUNET_NAMESTORE_record_put_by_authority (namestore, | ||
724 | pkey, edc->name, | ||
725 | rd_count, | ||
726 | rd_new, | ||
727 | &operation_done_cont, oc); | ||
814 | } | 728 | } |
815 | else | 729 | else |
816 | { | 730 | { |
817 | /* add record in database based on model */ | 731 | struct GNUNET_NAMESTORE_RecordData rd_new[rd_count + 1]; |
818 | GNUNET_break (0); // not implemented | 732 | |
733 | memcpy (rd_new, rd_old, rd_count * sizeof (struct GNUNET_NAMESTORE_RecordData)); | ||
734 | rd_new[rd_count] = rd; | ||
735 | oc = GNUNET_new (struct OperationContext); | ||
736 | GNUNET_CONTAINER_DLL_insert (oc_head, oc_tail, oc); | ||
737 | oc->qe = GNUNET_NAMESTORE_record_put_by_authority (namestore, | ||
738 | pkey, edc->name, | ||
739 | rd_count + 1, | ||
740 | rd_new, | ||
741 | &operation_done_cont, oc); | ||
819 | } | 742 | } |
820 | } | 743 | } |
821 | else | 744 | else |
@@ -826,8 +749,19 @@ edit_dialog_continuation (struct EditDialogContext *edc, | |||
826 | /* zone changed, remove record from old zone, add to new zone! */ | 749 | /* zone changed, remove record from old zone, add to new zone! */ |
827 | if (GNUNET_YES == edc->old_record_in_namestore) | 750 | if (GNUNET_YES == edc->old_record_in_namestore) |
828 | { | 751 | { |
829 | /* remove item from tree view and namestore */ | 752 | /* remove item from tree view and namestore */ |
830 | remove_record_at_offset (edc); | 753 | struct GNUNET_NAMESTORE_RecordData rd_new[rd_count - 1]; |
754 | |||
755 | GNUNET_assert (NULL != ri); | ||
756 | memcpy (rd_new, rd_old, (rd_count - 1) * sizeof (struct GNUNET_NAMESTORE_RecordData)); | ||
757 | rd_new[edc->off] = rd_old[rd_count - 1]; | ||
758 | oc = GNUNET_new (struct OperationContext); | ||
759 | GNUNET_CONTAINER_DLL_insert (oc_head, oc_tail, oc); | ||
760 | oc->qe = GNUNET_NAMESTORE_record_put_by_authority (namestore, | ||
761 | pkey, edc->name, | ||
762 | rd_count + 1, | ||
763 | rd_new, | ||
764 | &operation_done_cont, oc); | ||
831 | } | 765 | } |
832 | 766 | ||
833 | /* now add item to target zone */ | 767 | /* now add item to target zone */ |
@@ -851,23 +785,23 @@ edit_dialog_continuation (struct EditDialogContext *edc, | |||
851 | { | 785 | { |
852 | show_error_message (_("Failed to load private key for target zone"), | 786 | show_error_message (_("Failed to load private key for target zone"), |
853 | NULL); | 787 | NULL); |
854 | return; | 788 | break; |
855 | } | 789 | } |
856 | GNUNET_break (0); // not implemented | 790 | GNUNET_break (0); // not implemented |
857 | /* FIXME: get target zone records, merge with new one, commit! */ | 791 | /* FIXME: get target zone records, merge with new one, commit! */ |
858 | GNUNET_CRYPTO_ecc_key_free (pk); | 792 | GNUNET_CRYPTO_ecc_key_free (pk); |
859 | return; | 793 | break; |
860 | } | 794 | } |
861 | break; | 795 | break; |
862 | default: | 796 | default: |
863 | GNUNET_break (0); | 797 | GNUNET_break (0); |
864 | break; | 798 | break; |
865 | } | 799 | } |
800 | GNUNET_free (data); | ||
866 | free_edit_dialog_context (edc); | 801 | free_edit_dialog_context (edc); |
867 | } | 802 | } |
868 | 803 | ||
869 | 804 | ||
870 | |||
871 | /** | 805 | /** |
872 | * Launch a record editing dialog. | 806 | * Launch a record editing dialog. |
873 | * | 807 | * |
@@ -974,13 +908,11 @@ GNUNET_setup_gns_popup_edit_button_activate_cb (GtkWidget *widget, | |||
974 | GtkTreeSelection *sel; | 908 | GtkTreeSelection *sel; |
975 | gint n_type; | 909 | gint n_type; |
976 | gchar *n_name; | 910 | gchar *n_name; |
977 | unsigned int off; | 911 | guint off; |
978 | struct RecordInfo *ri; | 912 | struct RecordInfo *ri; |
979 | GtkTreeIter iter; | 913 | GtkTreeIter iter; |
914 | struct GNUNET_HashCode name_hash; | ||
980 | 915 | ||
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); | 916 | sel = gtk_tree_view_get_selection (tv); |
985 | if (! gtk_tree_selection_get_selected (sel, NULL, &iter)) | 917 | if (! gtk_tree_selection_get_selected (sel, NULL, &iter)) |
986 | { | 918 | { |
@@ -991,18 +923,27 @@ GNUNET_setup_gns_popup_edit_button_activate_cb (GtkWidget *widget, | |||
991 | gtk_tree_model_get (tm, &iter, | 923 | gtk_tree_model_get (tm, &iter, |
992 | GNS_TREESTORE_COL_NAME, &n_name, | 924 | GNS_TREESTORE_COL_NAME, &n_name, |
993 | GNS_TREESTORE_COL_RECORD_TYPE, &n_type, | 925 | GNS_TREESTORE_COL_RECORD_TYPE, &n_type, |
926 | GNS_TREESTORE_COL_RECORD_OFFSET, &off, | ||
994 | -1); | 927 | -1); |
995 | // FIXME: determine 'off', 'ri', ... | 928 | if (NULL == n_name) |
996 | // Idea: simply store 'off' in model! | 929 | { |
997 | off = 42; | 930 | GNUNET_break (0); |
998 | ri = NULL; | 931 | return; |
932 | } | ||
933 | GNUNET_CRYPTO_hash (n_name, strlen (n_name), &name_hash); | ||
934 | ri = GNUNET_CONTAINER_multihashmap_get (n2r, &name_hash); | ||
935 | if ( (NULL == ri) || | ||
936 | (off >= ri->rd_count) ) | ||
937 | { | ||
938 | GNUNET_break (0); | ||
939 | return; | ||
940 | } | ||
999 | launch_edit_dialog (n_type, n_name, | 941 | launch_edit_dialog (n_type, n_name, |
1000 | ri, off); | 942 | ri, off); |
1001 | g_free (n_name); | 943 | g_free (n_name); |
1002 | } | 944 | } |
1003 | 945 | ||
1004 | 946 | ||
1005 | |||
1006 | /** | 947 | /** |
1007 | * The user has selected a new record type. Update the | 948 | * The user has selected a new record type. Update the |
1008 | * model and then start the 'edit' dialog. | 949 | * model and then start the 'edit' dialog. |
@@ -1013,20 +954,28 @@ GNUNET_setup_gns_popup_edit_button_activate_cb (GtkWidget *widget, | |||
1013 | * @param user_data unused | 954 | * @param user_data unused |
1014 | */ | 955 | */ |
1015 | void | 956 | void |
1016 | GNUNET_setup_gns_type_cellrenderercombo_edited_cb (GtkCellRendererCombo *combo, | 957 | GNUNET_setup_gns_type_cellrenderercombo_changed_cb (GtkCellRendererCombo *combo, |
1017 | gchar *path, | 958 | gchar *path_string, |
1018 | gchar *new_text, | 959 | GtkTreeIter *new_iter, |
1019 | gpointer user_data) | 960 | gpointer user_data) |
1020 | { | 961 | { |
962 | GtkListStore *ls; | ||
963 | gchar *new_text; | ||
1021 | GtkTreeIter it; | 964 | GtkTreeIter it; |
1022 | guint type; | 965 | guint type; |
1023 | char *name_str; | 966 | char *name_str; |
1024 | struct GNUNET_HashCode name_hash; | 967 | struct GNUNET_HashCode name_hash; |
1025 | struct RecordInfo *ri; | 968 | struct RecordInfo *ri; |
1026 | 969 | ||
970 | ls = GTK_LIST_STORE (GNUNET_SETUP_get_object ("GNUNET_setup_gns_type_liststore")); | ||
971 | gtk_tree_model_get (GTK_TREE_MODEL (ls), new_iter, | ||
972 | 1, &new_text, | ||
973 | -1); | ||
974 | |||
1027 | if (0 == strcmp (new_text, _(NEW_RECORD_STR))) | 975 | if (0 == strcmp (new_text, _(NEW_RECORD_STR))) |
1028 | { | 976 | { |
1029 | GNUNET_break (0); | 977 | GNUNET_break (0); |
978 | g_free (new_text); | ||
1030 | return; /* no record type was selected */ | 979 | return; /* no record type was selected */ |
1031 | } | 980 | } |
1032 | type = GNUNET_NAMESTORE_typename_to_number (new_text); | 981 | type = GNUNET_NAMESTORE_typename_to_number (new_text); |
@@ -1037,22 +986,25 @@ GNUNET_setup_gns_type_cellrenderercombo_edited_cb (GtkCellRendererCombo *combo, | |||
1037 | new_text); | 986 | new_text); |
1038 | show_error_message (_("Unsupported record type"), | 987 | show_error_message (_("Unsupported record type"), |
1039 | new_text); | 988 | new_text); |
989 | g_free (new_text); | ||
1040 | return; | 990 | return; |
1041 | } | 991 | } |
1042 | /* check if this is a new record */ | 992 | /* check if this is a new record */ |
1043 | gtk_tree_model_get_iter_from_string (tm, &it, path); | 993 | gtk_tree_model_get_iter_from_string (tm, &it, path_string); |
1044 | gtk_tree_model_get (tm, &it, | 994 | gtk_tree_model_get (tm, &it, |
1045 | GNS_TREESTORE_COL_NAME, &name_str, | 995 | GNS_TREESTORE_COL_NAME, &name_str, |
1046 | -1); | 996 | -1); |
1047 | if (NULL == name_str) | 997 | if (NULL == name_str) |
1048 | { | 998 | { |
1049 | GNUNET_break (0); | 999 | GNUNET_break (0); |
1000 | g_free (new_text); | ||
1050 | return; | 1001 | return; |
1051 | } | 1002 | } |
1052 | GNUNET_CRYPTO_hash (name_str, strlen (name_str), &name_hash); | 1003 | GNUNET_CRYPTO_hash (name_str, strlen (name_str), &name_hash); |
1053 | ri = GNUNET_CONTAINER_multihashmap_get (n2r, &name_hash); | 1004 | ri = GNUNET_CONTAINER_multihashmap_get (n2r, &name_hash); |
1054 | launch_edit_dialog (type, name_str, ri, UINT_MAX); | 1005 | launch_edit_dialog (type, name_str, ri, UINT_MAX); |
1055 | g_free (name_str); | 1006 | g_free (name_str); |
1007 | g_free (new_text); | ||
1056 | } | 1008 | } |
1057 | 1009 | ||
1058 | 1010 | ||
@@ -1119,6 +1071,7 @@ GNUNET_setup_gns_name_cellrenderertext_edited_cb (GtkCellRendererText *renderer, | |||
1119 | GNS_TREESTORE_COL_IS_RECORD_ROW, FALSE, | 1071 | GNS_TREESTORE_COL_IS_RECORD_ROW, FALSE, |
1120 | GNS_TREESTORE_COL_TYPE_IS_EDITABLE, FALSE, | 1072 | GNS_TREESTORE_COL_TYPE_IS_EDITABLE, FALSE, |
1121 | GNS_TREESTORE_COL_NAME_IS_EDITABLE, TRUE, | 1073 | GNS_TREESTORE_COL_NAME_IS_EDITABLE, TRUE, |
1074 | GNS_TREESTORE_COL_RECORD_OFFSET, UINT_MAX, | ||
1122 | -1); | 1075 | -1); |
1123 | } | 1076 | } |
1124 | 1077 | ||
@@ -1218,23 +1171,116 @@ GNUNET_setup_gns_main_treeview_key_press_event_cb (GtkWidget *widget, | |||
1218 | GdkEventKey *event, | 1171 | GdkEventKey *event, |
1219 | gpointer user_data) | 1172 | gpointer user_data) |
1220 | { | 1173 | { |
1221 | GtkTreeIter it; | 1174 | GtkTreeIter iter; |
1222 | GtkTreeSelection *sel; | 1175 | GtkTreeSelection *sel; |
1223 | int not_dummy; | 1176 | int not_dummy; |
1177 | GtkTreeIter parent; | ||
1178 | char *name; | ||
1179 | struct GNUNET_HashCode name_hash; | ||
1180 | struct RecordInfo *ri; | ||
1181 | struct OperationContext *oc; | ||
1224 | 1182 | ||
1225 | /* Check for delete key */ | 1183 | /* Check for delete key */ |
1226 | if ( (GDK_KEY_PRESS != event->type) || | 1184 | if ( (GDK_KEY_PRESS != event->type) || |
1227 | (GDK_KEY_Delete != event->keyval) ) | 1185 | (GDK_KEY_Delete != event->keyval) ) |
1228 | return FALSE; | 1186 | return FALSE; |
1229 | sel = gtk_tree_view_get_selection(tv); | 1187 | sel = gtk_tree_view_get_selection(tv); |
1230 | if (! gtk_tree_selection_get_selected (sel, NULL, &it)) | 1188 | if (! gtk_tree_selection_get_selected (sel, NULL, &iter)) |
1231 | return TRUE; /* nothing selected */ | 1189 | return TRUE; /* nothing selected */ |
1232 | gtk_tree_model_get (tm, &it, | 1190 | gtk_tree_model_get (tm, &iter, |
1233 | GNS_TREESTORE_COL_NOT_DUMMY_ROW, ¬_dummy, | 1191 | GNS_TREESTORE_COL_NOT_DUMMY_ROW, ¬_dummy, |
1192 | GNS_TREESTORE_COL_NAME, &name, | ||
1234 | -1); | 1193 | -1); |
1235 | if (GNUNET_NO == not_dummy) | 1194 | if (GNUNET_NO == not_dummy) |
1195 | { | ||
1196 | g_free (name); | ||
1236 | return TRUE; /* do not delete the dummy line */ | 1197 | return TRUE; /* do not delete the dummy line */ |
1237 | remove_records_by_iter (&it); | 1198 | } |
1199 | GNUNET_CRYPTO_hash (name, strlen (name), &name_hash); | ||
1200 | ri = GNUNET_CONTAINER_multihashmap_get (n2r, | ||
1201 | &name_hash); | ||
1202 | GNUNET_assert (NULL != ri); | ||
1203 | |||
1204 | if ( (gtk_tree_model_iter_parent (tm, &parent, &iter)) && | ||
1205 | (ri->rd_count > 0) ) | ||
1206 | { | ||
1207 | struct GNUNET_NAMESTORE_RecordData rd_old[ri->rd_count]; | ||
1208 | struct GNUNET_NAMESTORE_RecordData rd_new[ri->rd_count - 1]; | ||
1209 | struct GNUNET_NAMESTORE_RecordData rd; | ||
1210 | unsigned int off; | ||
1211 | int n_type; | ||
1212 | gboolean n_public; | ||
1213 | guint64 n_exp_time; | ||
1214 | gboolean n_is_relative; | ||
1215 | gboolean n_is_shadow; | ||
1216 | char *n_value; | ||
1217 | |||
1218 | /* Removing a single record */ | ||
1219 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1220 | "Removing single record for name `%s'\n", | ||
1221 | name); | ||
1222 | GNUNET_break (GNUNET_OK == | ||
1223 | GNUNET_NAMESTORE_records_deserialize (ri->data_size, | ||
1224 | ri->data, | ||
1225 | ri->rd_count, | ||
1226 | rd_old)); | ||
1227 | gtk_tree_model_get (tm, &iter, | ||
1228 | GNS_TREESTORE_COL_RECORD_TYPE, &n_type, | ||
1229 | GNS_TREESTORE_COL_IS_PUBLIC, &n_public, | ||
1230 | GNS_TREESTORE_COL_EXP_TIME, &n_exp_time, | ||
1231 | GNS_TREESTORE_COL_EXP_TIME_IS_REL, &n_is_relative, | ||
1232 | GNS_TREESTORE_COL_IS_SHADOW, &n_is_shadow, | ||
1233 | GNS_TREESTORE_COL_VAL_AS_STR, &n_value, | ||
1234 | -1); | ||
1235 | /* valid name */ | ||
1236 | if (n_public) | ||
1237 | rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY; | ||
1238 | else | ||
1239 | rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY | GNUNET_NAMESTORE_RF_PRIVATE; | ||
1240 | if (n_is_relative) | ||
1241 | rd.flags |= GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION; | ||
1242 | if (n_is_shadow) | ||
1243 | rd.flags |= GNUNET_NAMESTORE_RF_SHADOW_RECORD; | ||
1244 | rd.record_type = n_type; | ||
1245 | rd.expiration_time = n_exp_time; | ||
1246 | if (GNUNET_OK != | ||
1247 | GNUNET_NAMESTORE_string_to_value (n_type, n_value, | ||
1248 | (void**)&rd.data, &rd.data_size)) | ||
1249 | { | ||
1250 | /* can't remove, value invalid */ | ||
1251 | GNUNET_assert (0); | ||
1252 | g_free (n_value); | ||
1253 | g_free (name); | ||
1254 | return TRUE; | ||
1255 | } | ||
1256 | for (off=0;off<ri->rd_count;off++) | ||
1257 | if (GNUNET_YES == | ||
1258 | GNUNET_NAMESTORE_records_cmp (&rd, | ||
1259 | &rd_old[off])) | ||
1260 | break; | ||
1261 | GNUNET_assert (off != ri->rd_count); | ||
1262 | memcpy (rd_new, rd_old, (ri->rd_count - 1) * sizeof (struct GNUNET_NAMESTORE_RecordData)); | ||
1263 | rd_new[off] = rd_old[ri->rd_count - 1]; | ||
1264 | oc = GNUNET_new (struct OperationContext); | ||
1265 | GNUNET_CONTAINER_DLL_insert (oc_head, oc_tail, oc); | ||
1266 | oc->qe = GNUNET_NAMESTORE_record_put_by_authority (namestore, | ||
1267 | pkey, name, | ||
1268 | ri->rd_count - 1, | ||
1269 | rd_new, | ||
1270 | &operation_done_cont, oc); | ||
1271 | g_free (n_value); | ||
1272 | } | ||
1273 | else | ||
1274 | { | ||
1275 | oc = GNUNET_new (struct OperationContext); | ||
1276 | GNUNET_CONTAINER_DLL_insert (oc_head, oc_tail, oc); | ||
1277 | oc->qe = GNUNET_NAMESTORE_record_put_by_authority (namestore, | ||
1278 | pkey, name, | ||
1279 | 0, NULL, | ||
1280 | &operation_done_cont, oc); | ||
1281 | } | ||
1282 | g_free (name); | ||
1283 | |||
1238 | return TRUE; | 1284 | return TRUE; |
1239 | } | 1285 | } |
1240 | 1286 | ||
@@ -1450,13 +1496,7 @@ zone_iteration_proc (void *cls, | |||
1450 | gtk_tree_path_free (path); | 1496 | gtk_tree_path_free (path); |
1451 | /* remove all records, we'll re-add those that are left next */ | 1497 | /* remove all records, we'll re-add those that are left next */ |
1452 | if (gtk_tree_model_iter_children (tm, &iter_record, &iter_name)) | 1498 | if (gtk_tree_model_iter_children (tm, &iter_record, &iter_name)) |
1453 | { | 1499 | while (gtk_tree_store_remove (ts, &iter_record)) ; |
1454 | do | ||
1455 | { | ||
1456 | gtk_tree_store_remove (ts, &iter_record); | ||
1457 | } | ||
1458 | while (gtk_tree_model_iter_next (tm, &iter_record)); | ||
1459 | } | ||
1460 | } | 1500 | } |
1461 | else | 1501 | else |
1462 | { | 1502 | { |
@@ -1470,6 +1510,7 @@ zone_iteration_proc (void *cls, | |||
1470 | GNS_TREESTORE_COL_IS_RECORD_ROW, TRUE, | 1510 | GNS_TREESTORE_COL_IS_RECORD_ROW, TRUE, |
1471 | GNS_TREESTORE_COL_NOT_DUMMY_ROW, FALSE, | 1511 | GNS_TREESTORE_COL_NOT_DUMMY_ROW, FALSE, |
1472 | GNS_TREESTORE_COL_TYPE_IS_EDITABLE, TRUE, | 1512 | GNS_TREESTORE_COL_TYPE_IS_EDITABLE, TRUE, |
1513 | GNS_TREESTORE_COL_RECORD_OFFSET, UINT_MAX, | ||
1473 | -1); | 1514 | -1); |
1474 | 1515 | ||
1475 | path = gtk_tree_model_get_path (tm, | 1516 | path = gtk_tree_model_get_path (tm, |
@@ -1503,7 +1544,7 @@ zone_iteration_proc (void *cls, | |||
1503 | ri->data_size = GNUNET_NAMESTORE_records_get_size (rd_count, rd); | 1544 | ri->data_size = GNUNET_NAMESTORE_records_get_size (rd_count, rd); |
1504 | if (0 != ri->data_size) | 1545 | if (0 != ri->data_size) |
1505 | ri->data = GNUNET_malloc (ri->data_size); | 1546 | ri->data = GNUNET_malloc (ri->data_size); |
1506 | GNUNET_break (GNUNET_OK == | 1547 | GNUNET_break (ri->data_size == |
1507 | GNUNET_NAMESTORE_records_serialize (rd_count, rd, | 1548 | GNUNET_NAMESTORE_records_serialize (rd_count, rd, |
1508 | ri->data_size, ri->data)); | 1549 | ri->data_size, ri->data)); |
1509 | 1550 | ||
@@ -1570,6 +1611,7 @@ zone_iteration_proc (void *cls, | |||
1570 | GNS_TREESTORE_COL_VAL_AS_STR, val, | 1611 | GNS_TREESTORE_COL_VAL_AS_STR, val, |
1571 | GNS_TREESTORE_COL_IS_RECORD_ROW, TRUE, | 1612 | GNS_TREESTORE_COL_IS_RECORD_ROW, TRUE, |
1572 | GNS_TREESTORE_COL_NOT_DUMMY_ROW, TRUE, | 1613 | GNS_TREESTORE_COL_NOT_DUMMY_ROW, TRUE, |
1614 | GNS_TREESTORE_COL_RECORD_OFFSET, (guint) c, | ||
1573 | -1); | 1615 | -1); |
1574 | GNUNET_free (type_str); | 1616 | GNUNET_free (type_str); |
1575 | GNUNET_free (val); | 1617 | GNUNET_free (val); |
@@ -1649,6 +1691,7 @@ load_zone (const char *zonename) | |||
1649 | GNS_TREESTORE_COL_NOT_DUMMY_ROW, FALSE, | 1691 | GNS_TREESTORE_COL_NOT_DUMMY_ROW, FALSE, |
1650 | GNS_TREESTORE_COL_TYPE_IS_EDITABLE, FALSE, | 1692 | GNS_TREESTORE_COL_TYPE_IS_EDITABLE, FALSE, |
1651 | GNS_TREESTORE_COL_NAME_IS_EDITABLE, TRUE, | 1693 | GNS_TREESTORE_COL_NAME_IS_EDITABLE, TRUE, |
1694 | GNS_TREESTORE_COL_RECORD_OFFSET, UINT_MAX, | ||
1652 | -1); | 1695 | -1); |
1653 | /* Load zone from namestore! */ | 1696 | /* Load zone from namestore! */ |
1654 | #if HAVE_QRENCODE_H | 1697 | #if HAVE_QRENCODE_H |