aboutsummaryrefslogtreecommitdiff
path: root/src/gns/gnunet-gns-gtk_zone.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gns/gnunet-gns-gtk_zone.c')
-rw-r--r--src/gns/gnunet-gns-gtk_zone.c1268
1 files changed, 0 insertions, 1268 deletions
diff --git a/src/gns/gnunet-gns-gtk_zone.c b/src/gns/gnunet-gns-gtk_zone.c
deleted file mode 100644
index 4015248d..00000000
--- a/src/gns/gnunet-gns-gtk_zone.c
+++ /dev/null
@@ -1,1268 +0,0 @@
1/*
2 This file is part of GNUnet
3 (C) 2012 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file src/gns/gnunet-gns-gtk_zone.c
23 * @author Christian Grothoff
24 * @brief everything releated to the zone tree view
25 */
26#include "gnunet_gtk.h"
27#include "gnunet-gns-gtk.h"
28
29
30/**
31 * FIXME: duplicated with "enum GNS_ModelColumns"!
32 */
33enum GNSTreestoreColumn
34{
35 /**
36 *
37 */
38 GNS_TREESTORE_COL_NAME = 0,
39
40 /**
41 *
42 */
43 GNS_TREESTORE_COL_IS_PUBLIC,
44
45 /**
46 *
47 */
48 GNS_TREESTORE_COL_RECORD_TYPE,
49
50 /**
51 *
52 */
53 GNS_TREESTORE_COL_RECORD_TYPE_AS_STR,
54
55 /**
56 *
57 */
58 GNS_TREESTORE_COL_EXP_TIME,
59
60 /**
61 *
62 */
63 GNS_TREESTORE_COL_EXP_TIME_IS_REL,
64
65 /**
66 *
67 */
68 GNS_TREESTORE_COL_EXP_TIME_AS_STR,
69
70 /**
71 *
72 */
73 GNS_TREESTORE_COL_VAL_AS_STR,
74
75 /**
76 *
77 */
78 GNS_TREESTORE_COL_VAL_COLOR,
79
80 /**
81 *
82 */
83 GNS_TREESTORE_COL_NAME_IS_VISIBLE,
84
85 /**
86 *
87 */
88 GNS_TREESTORE_COL_IS_RECORD_ROW,
89
90 /**
91 *
92 */
93 GNS_TREESTORE_COL_NOT_DUMMY_ROW,
94
95 /**
96 *
97 */
98 GNS_TREESTORE_COL_EXP_TIME_COLOR,
99
100 /**
101 *
102 */
103 GNS_TREESTORE_COL_NAME_COLOR
104};
105
106
107/**
108 *
109 */
110enum LIST_COLUMNS
111{
112
113 /**
114 *
115 */
116 GNS_TYPE_TO_NAME_LISTSTORE_COLUMN_TYPE = 0,
117
118
119 /**
120 *
121 */
122 GNS_TYPE_TO_NAME_LISTSTORE_COLUMN_TYPENAME
123};
124
125
126/**
127 *
128 */
129struct UpdateContext
130{
131 /**
132 *
133 */
134 struct GNUNET_GNS_Context *gns;
135
136 /**
137 *
138 */
139 struct GNUNET_NAMESTORE_RecordData *rd;
140
141 /**
142 *
143 */
144 char * name;
145
146 /**
147 *
148 */
149 unsigned int rd_count;
150};
151
152
153static void
154check_name_validity_and_commit_remove_proc (void *cls,
155 int32_t success,
156 const char *emsg)
157{
158 struct UpdateContext * uc = cls;
159 unsigned int c;
160 if ((GNUNET_OK == success) || (GNUNET_NO == success))
161 {
162 for (c = 0; c < uc->rd_count; c++)
163 {
164 GNUNET_NAMESTORE_record_create(uc->gns->ns, uc->gns->pkey,
165 uc->name, &uc->rd[c],NULL, NULL);
166 GNUNET_free ((void *) uc->rd[c].data);
167 }
168 GNUNET_free (uc->rd);
169 GNUNET_free (uc->name);
170 GNUNET_free (uc);
171 }
172 else if (GNUNET_SYSERR == success)
173 {
174 for (c = 0; c < uc->rd_count; c++)
175 GNUNET_free ((void *) uc->rd[c].data);
176 GNUNET_free (uc->rd);
177 GNUNET_free (uc->name);
178 GNUNET_free (uc);
179 }
180 else
181 {
182 GNUNET_break (0);
183 GNUNET_free (uc);
184 }
185}
186
187
188static void
189check_name_validity_and_commit (struct GNUNET_GNS_Context *gns, gchar *path, char * oldname)
190{
191 GtkTreeIter it;
192 GtkTreeIter parent;
193 int records;
194 int children;
195 int append_pseu;
196 int c;
197 int valid = GNUNET_YES;
198 char * name;
199 void * data;
200 size_t data_size;
201 const gchar * pseu;
202
203 char *n_name;
204 int n_type;
205 gboolean n_public;
206 char *n_exp_color;
207 guint64 n_exp_time;
208 char *n_exp_str;
209 gboolean n_is_relative;
210 char *n_value;
211 char *n_value_color;
212
213
214 gtk_tree_model_get_iter_from_string(gns->tm, &it, path);
215
216 if (FALSE == gtk_tree_model_iter_parent (gns->tm, &parent, &it))
217 parent = it;
218
219 children = gtk_tree_model_iter_n_children (gns->tm, &parent);
220 if (children < 1)
221 {
222 return;
223 }
224
225 gtk_tree_model_get(gns->tm, &parent,
226 GNS_TREESTORE_COL_NAME, &name,
227 -1);
228
229 if (0 == strcmp (name, ROOT_STR))
230 {
231 /* We have to append PSEU RECORD */
232 append_pseu = GNUNET_YES;
233 records = children + 1;
234 }
235 else
236 {
237 append_pseu = GNUNET_NO;
238 records = children;
239 }
240
241 struct GNUNET_NAMESTORE_RecordData *rd = GNUNET_malloc (records * sizeof (struct GNUNET_NAMESTORE_RecordData));
242
243 if (FALSE == gtk_tree_model_iter_children (gns->tm, &it, &parent))
244 return;
245
246 for (c = 0; c < children; c++)
247 {
248 gtk_tree_model_get(gns->tm, &it,
249 GNS_TREESTORE_COL_NAME, &n_name,
250 GNS_TREESTORE_COL_RECORD_TYPE, &n_type,
251 GNS_TREESTORE_COL_IS_PUBLIC, &n_public,
252 GNS_TREESTORE_COL_EXP_TIME_COLOR, &n_exp_color,
253 GNS_TREESTORE_COL_EXP_TIME, &n_exp_time,
254 GNS_TREESTORE_COL_EXP_TIME_IS_REL, &n_is_relative,
255 GNS_TREESTORE_COL_EXP_TIME_AS_STR, &n_exp_str,
256 GNS_TREESTORE_COL_VAL_AS_STR, &n_value,
257 GNS_TREESTORE_COL_VAL_COLOR, &n_value_color,
258 -1);
259 /* valid name */
260 if (NULL == n_name)
261 valid = GNUNET_NO;
262 else
263 {
264 if (GNUNET_SYSERR == GNUNET_NAMESTORE_check_name (n_name))
265 valid = GNUNET_NO;
266 }
267
268 /* valid record type */
269 if (0 == n_type)
270 valid = GNUNET_NO;
271
272 /* valid expiration */
273 if ((n_exp_color != NULL) || (NULL == n_exp_str) || (0 == n_exp_time))
274 valid = GNUNET_NO;
275
276 /* valid value */
277 if ((n_value_color != NULL) || (NULL == n_value))
278 valid = GNUNET_NO;
279 if (NULL != n_value)
280 {
281 if (GNUNET_OK != GNUNET_NAMESTORE_string_to_value(n_type, n_value, &data, &data_size))
282 valid = GNUNET_NO;
283 }
284
285 if (GNUNET_YES == valid)
286 {
287 if (FALSE == n_public)
288 rd[c].flags = GNUNET_NAMESTORE_RF_AUTHORITY | GNUNET_NAMESTORE_RF_PRIVATE;
289 else
290 rd[c].flags = GNUNET_NAMESTORE_RF_AUTHORITY | GNUNET_NAMESTORE_RF_NONE;
291 rd[c].record_type = n_type;
292 rd[c].expiration_time = n_exp_time;
293 rd[c].data_size = data_size;
294 rd[c].data = GNUNET_malloc(data_size);
295 memcpy ((void *) rd[c].data, data, data_size);
296 }
297 g_free (n_name);
298 g_free (n_exp_color);
299 g_free (n_exp_str);
300 g_free (n_value);
301 g_free (n_value_color);
302
303 if (FALSE == gtk_tree_model_iter_next (gns->tm, &it))
304 break;
305 }
306
307 if (GNUNET_NO == valid)
308 {
309 for (c = 0; c < children; c++)
310 GNUNET_free_non_null ((void *) rd[c].data);
311 GNUNET_free_non_null (rd);
312 }
313 else
314 {
315
316 if (GNUNET_YES == append_pseu)
317 {
318 GNUNET_assert (children == (records -1));
319
320 /* Append PSEU record */
321 GtkEntry * entry = GTK_ENTRY (gtk_builder_get_object (gns->builder, "GNUNET_GNS_GTK_pseu_entry"));
322 pseu = gtk_entry_get_text (GTK_ENTRY(entry));
323 if ((NULL != pseu) && (0 != strcmp (PSEU_EMPTY_STR, pseu)) && (0 != strcmp ("", pseu)))
324 {
325 if (GNUNET_OK != GNUNET_NAMESTORE_string_to_value(GNUNET_NAMESTORE_TYPE_PSEU,
326 pseu,
327 (void **) &rd[records - 1].data,
328 &rd[records - 1].data_size))
329 {
330 GNUNET_break (0);
331 for (c = 0; c < records; c++)
332 GNUNET_free_non_null ((void *) rd[c].data);
333 GNUNET_free_non_null (rd);
334 }
335 rd[records - 1].record_type = GNUNET_NAMESTORE_TYPE_PSEU;
336 rd[records - 1].expiration_time = UINT64_MAX;
337 rd[records - 1].flags = GNUNET_NAMESTORE_RF_AUTHORITY | GNUNET_NAMESTORE_RF_NONE;
338 }
339 else
340 {
341 GNUNET_break (0);
342 }
343 }
344
345 /* Remove old entries */
346 struct UpdateContext * uc = GNUNET_malloc (sizeof (struct UpdateContext));
347 uc->gns = gns;
348 uc->rd = rd;
349 uc->rd_count = records;
350 uc->name = strdup (name);
351 if (oldname != NULL)
352 GNUNET_NAMESTORE_record_remove(gns->ns, gns->pkey, oldname, NULL, &check_name_validity_and_commit_remove_proc, uc);
353 else
354 GNUNET_NAMESTORE_record_remove(gns->ns, gns->pkey, name, NULL, &check_name_validity_and_commit_remove_proc, uc);
355 g_free (name);
356 }
357}
358
359
360/**
361 *
362 */
363struct Remove_Context
364{
365
366 /**
367 *
368 */
369 struct GNUNET_GNS_Context *gns;
370
371 /**
372 *
373 */
374 char *path;
375};
376
377
378static void
379check_name_validity_and_remove_proc (void *cls,
380 int32_t success,
381 const char *emsg)
382{
383 struct Remove_Context *rcc = cls;
384 GtkDialog *dialog;
385 GtkTreeIter it;
386 if (GNUNET_SYSERR == success)
387 {
388 char * message = _("Record could not be deleted:");
389 dialog = GTK_DIALOG(gtk_message_dialog_new (GTK_WINDOW (rcc->gns->main_window),
390 GTK_DIALOG_DESTROY_WITH_PARENT,
391 GTK_MESSAGE_ERROR,
392 GTK_BUTTONS_CLOSE,
393 _("%s\n%s\n"),
394 message,
395 emsg));
396
397 g_signal_connect (dialog, "response", G_CALLBACK (gtk_widget_destroy), rcc->gns);
398 gtk_widget_show_all (GTK_WIDGET(dialog));
399 }
400 else
401 {
402 gtk_tree_model_get_iter_from_string(rcc->gns->tm, &it, rcc->path);
403 gtk_tree_store_remove (rcc->gns->ts, &it);
404 }
405 GNUNET_free (rcc->path);
406 GNUNET_free (rcc);
407}
408
409
410static void
411check_name_validity_and_remove (struct GNUNET_GNS_Context *gns, gchar *path)
412{
413 GtkTreeIter it;
414 GtkTreeIter parent;
415 char *name;
416 int valid = GNUNET_YES;
417 struct GNUNET_NAMESTORE_RecordData rd;
418 struct Remove_Context *rcc;
419
420 char *n_name;
421 int n_type;
422 gboolean n_public;
423 char *n_exp_color;
424 guint64 n_exp_time;
425 char *n_exp_str;
426 gboolean n_is_relative;
427 char *n_value;
428 char *n_value_color;
429
430 gtk_tree_model_get_iter_from_string(gns->tm, &it, path);
431 gtk_tree_model_get(gns->tm, &it,
432 GNS_TREESTORE_COL_NAME, &name,
433 -1);
434
435 if (TRUE == gtk_tree_model_iter_parent (gns->tm, &parent, &it))
436 {
437 /* Removing a single record */
438 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
439 "Removing single record for name `%s'\n", name);
440
441 gtk_tree_model_get(gns->tm, &it,
442 GNS_TREESTORE_COL_NAME, &n_name,
443 GNS_TREESTORE_COL_RECORD_TYPE, &n_type,
444 GNS_TREESTORE_COL_IS_PUBLIC, &n_public,
445 GNS_TREESTORE_COL_EXP_TIME_COLOR, &n_exp_color,
446 GNS_TREESTORE_COL_EXP_TIME, &n_exp_time,
447 GNS_TREESTORE_COL_EXP_TIME_IS_REL, &n_is_relative,
448 GNS_TREESTORE_COL_EXP_TIME_AS_STR, &n_exp_str,
449 GNS_TREESTORE_COL_VAL_AS_STR, &n_value,
450 GNS_TREESTORE_COL_VAL_COLOR, &n_value_color,
451 -1);
452
453 /* valid name */
454 if (NULL == n_name)
455 valid = GNUNET_NO;
456
457 /* valid record type */
458 if (0 == n_type)
459 valid = GNUNET_NO;
460
461 /* valid expiration */
462 if ((n_exp_color != NULL) || (NULL == n_exp_str) || (0 == n_exp_time))
463 valid = GNUNET_NO;
464
465 /* valid value */
466 if ((n_value_color != NULL) || (NULL == n_value))
467 valid = GNUNET_NO;
468
469 if (GNUNET_YES == valid)
470 {
471 if (FALSE == n_public)
472 rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY | GNUNET_NAMESTORE_RF_PRIVATE;
473 else
474 rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY | GNUNET_NAMESTORE_RF_NONE;
475 rd.record_type = n_type;
476 rd.expiration_time = n_exp_time;
477 rd.data_size = strlen (n_value) + 1;
478 rd.data = GNUNET_malloc(rd.data_size);
479 memcpy ((void *) rd.data, n_value, rd.data_size);
480
481 rcc = GNUNET_malloc(sizeof (struct Remove_Context));
482 rcc->gns = gns;
483 rcc->path = strdup (path);
484 GNUNET_NAMESTORE_record_remove(gns->ns, gns->pkey, name, &rd, &check_name_validity_and_remove_proc, rcc);
485 GNUNET_free ((void *) rd.data);
486 }
487 else
488 {
489 gtk_tree_model_get_iter_from_string(gns->tm, &it, path);
490 gtk_tree_store_remove (gns->ts, &it);
491 }
492 g_free (n_name);
493 g_free (n_exp_color);
494 g_free (n_exp_str);
495 g_free (n_value);
496 g_free (n_value_color);
497 }
498 else if (0 != strcmp (name, ROOT_STR))
499 {
500 /* Removing the whole name record */
501 rcc = GNUNET_malloc(sizeof (struct Remove_Context));
502 rcc->gns = gns;
503 rcc->path = strdup (path);
504 GNUNET_NAMESTORE_record_remove(gns->ns, gns->pkey, name, NULL, &check_name_validity_and_remove_proc, rcc);
505 }
506 g_free (name);
507}
508
509
510/**
511 * The user has selected a new record type. Update the
512 * model, possibly invalidating (marking 'red') the existing
513 * value.
514 *
515 * @param renderer updated renderer
516 * @param path the path identifying the edited cell
517 * @param new_iter selected cell in the combo's model (with the record type)
518 * @param user_data unused
519 */
520void
521GNUNET_GNS_GTK_type_cellrenderercombo_changed_cb (GtkCellRendererCombo *combo,
522 gchar *path,
523 GtkTreeIter *new_iter,
524 gpointer user_data)
525{
526 struct GNUNET_GNS_Context *gns = user_data;
527 GtkTreeIter it;
528 GtkTreeIter child;
529 guint type;
530 int record_row;
531 char *type_str;
532 char *value_str;
533 char *name_str;
534 void *data;
535 size_t data_size;
536
537 gtk_tree_model_get(GTK_TREE_MODEL(gns->ls), new_iter, 0, &type, -1);
538 gtk_tree_model_get(GTK_TREE_MODEL(gns->ls), new_iter, GNS_TYPE_TO_NAME_LISTSTORE_COLUMN_TYPENAME, &type_str, -1);
539
540
541 /* check if this is a new record */
542 gtk_tree_model_get_iter_from_string(gns->tm, &it, path);
543 gtk_tree_model_get(gns->tm, &it, GNS_TREESTORE_COL_IS_RECORD_ROW, &record_row, -1);
544 gtk_tree_model_get(gns->tm, &it, GNS_TREESTORE_COL_NAME, &name_str, -1);
545
546 if (GNUNET_YES == record_row)
547 {
548 /* Updating an existing record */
549 gtk_tree_store_set(gns->ts, &it,
550 GNS_TREESTORE_COL_RECORD_TYPE, type,
551 GNS_TREESTORE_COL_RECORD_TYPE_AS_STR, type_str,
552 -1);
553 }
554 else if ((NULL != name_str) && (0 != strcmp (NEW_NAME_STR, name_str)))
555 {
556 /* Adding a new record */
557
558 gtk_tree_store_insert_with_values(gns->ts, &child , &it, 0,
559 GNS_TREESTORE_COL_NAME, name_str,
560 GNS_TREESTORE_COL_NAME_IS_VISIBLE, FALSE,
561 GNS_TREESTORE_COL_RECORD_TYPE, type,
562 GNS_TREESTORE_COL_RECORD_TYPE_AS_STR, type_str,
563 GNS_TREESTORE_COL_EXP_TIME_AS_STR, EXPIRE_NEVER_STRING,
564 GNS_TREESTORE_COL_EXP_TIME, GNUNET_TIME_UNIT_FOREVER_ABS,
565 GNS_TREESTORE_COL_EXP_TIME_IS_REL, FALSE,
566 GNS_TREESTORE_COL_IS_RECORD_ROW, GNUNET_YES,
567 GNS_TREESTORE_COL_NOT_DUMMY_ROW, GNUNET_YES,
568 -1);
569 gtk_tree_view_expand_row (gns->tv, gtk_tree_model_get_path(gns->tm, &it), 0);
570
571 }
572 GNUNET_free (type_str);
573
574 /* check if value is still valid */
575 gtk_tree_model_get(gns->tm, &it, GNS_TREESTORE_COL_VAL_AS_STR, &value_str, -1);
576 if (NULL != value_str)
577 {
578 if (GNUNET_OK != GNUNET_NAMESTORE_string_to_value (type,
579 value_str,
580 &data,
581 &data_size))
582 gtk_tree_store_set (gns->ts, &it, GNS_TREESTORE_COL_VAL_COLOR, "red", -1);
583 else
584 gtk_tree_store_set (gns->ts, &it, GNS_TREESTORE_COL_VAL_COLOR, NULL, -1);
585 GNUNET_free (value_str);
586 }
587 else if (NULL == value_str)
588 {
589 /* Empty value field */
590 if (GNUNET_YES == record_row)
591 gtk_tree_store_set (gns->ts, &it, GNS_TREESTORE_COL_VAL_COLOR, "red", -1);
592 else
593 gtk_tree_store_set (gns->ts, &child, GNS_TREESTORE_COL_VAL_COLOR, "red", -1);
594 }
595
596 check_name_validity_and_commit (gns, path, NULL);
597 GNUNET_free_non_null (name_str);
598}
599
600
601/**
602 * The user has toggled the 'public' checkmark of a cell. Update the
603 * model.
604 *
605 * @param renderer updated renderer
606 * @param path the path identifying the edited cell
607 * @param user_data unused
608 */
609void
610GNUNET_GNS_GTK_ispublic_cellrenderertoggle_toggled_cb (GtkCellRendererToggle *cell_renderer,
611 gchar *path,
612 gpointer user_data)
613{
614 struct GNUNET_GNS_Context *gns = user_data;
615 GtkTreeIter it;
616 gboolean value;
617
618 gtk_tree_model_get_iter_from_string(gns->tm, &it, path);
619 gtk_tree_model_get(gns->tm, &it, GNS_TREESTORE_COL_IS_PUBLIC, &value, -1);
620 gtk_tree_store_set(gns->ts, &it, GNS_TREESTORE_COL_IS_PUBLIC, !value, -1);
621
622 check_name_validity_and_commit (gns, path, NULL);
623}
624
625
626static char *
627convert_time_to_string (struct GNUNET_TIME_Absolute t)
628{
629 time_t tt;
630 struct tm *time;
631 char *ret;
632
633 if (t.abs_value == GNUNET_TIME_UNIT_FOREVER_ABS.abs_value)
634 return GNUNET_strdup (_(EXPIRE_NEVER_STRING));
635 if (t.abs_value == GNUNET_TIME_UNIT_ZERO_ABS.abs_value)
636 return GNUNET_strdup (_(EXPIRE_INVALID_STRING));
637
638 tt = t.abs_value / 1000;
639 time = localtime (&tt);
640
641 GNUNET_asprintf(&ret, "%02u/%02u/%04u %02u:%02u",time->tm_mon, time->tm_mday, 1900 + time->tm_year, time->tm_hour, time->tm_min);
642 return ret;
643}
644
645
646static int
647check_time (const char * text)
648{
649 unsigned int t_mon;
650 unsigned int t_day;
651 unsigned int t_year;
652 unsigned int t_hrs;
653 unsigned int t_min;
654
655 int count = SSCANF (text, "%02u/%02u/%04u %02u:%02u", &t_mon, &t_day, &t_year, &t_hrs, &t_min);
656 if ((EOF == count) || (5 != count))
657 return GNUNET_SYSERR;
658
659 if (t_mon > 12)
660 return GNUNET_SYSERR;
661 if (t_day > 31)
662 return GNUNET_SYSERR;
663 if (t_hrs > 24)
664 return GNUNET_SYSERR;
665 if (t_min > 59)
666 return GNUNET_SYSERR;
667
668 return GNUNET_OK;
669}
670
671
672static const struct GNUNET_TIME_Absolute
673convert_string_to_abs_time (const char * text)
674{
675 static struct GNUNET_TIME_Absolute abs_t;
676 struct tm time;
677 time_t t;
678
679 int t_mon;
680 int t_day;
681 int t_year;
682 int t_hrs;
683 int t_min;
684
685 GNUNET_assert (NULL != text);
686
687 if (0 == strcmp(text, EXPIRE_NEVER_STRING))
688 return GNUNET_TIME_UNIT_FOREVER_ABS;
689
690 memset (&time, '\0', sizeof (struct tm));
691
692 if (GNUNET_SYSERR == check_time(text))
693 {
694 GNUNET_break (0);
695 return GNUNET_TIME_UNIT_ZERO_ABS;
696 }
697
698 int count = SSCANF (text, "%02d/%02d/%04d %02d:%02d", &t_mon, &t_day, &t_year, &t_hrs, &t_min);
699 if ((EOF == count) || (5 != count))
700 return GNUNET_TIME_UNIT_ZERO_ABS;
701
702 time.tm_mon = (t_mon - 1);
703 time.tm_mday = t_day;
704 time.tm_year = t_year - 1900;
705 time.tm_hour = (t_hrs);
706 time.tm_min = t_min;
707
708 t = mktime (&time);
709 if (-1 == t)
710 return GNUNET_TIME_UNIT_ZERO_ABS;
711
712 abs_t.abs_value = t * 1000;
713
714 return abs_t;
715}
716
717
718/**
719 * The user has edited a 'expiration' cell. Update the model.
720 *
721 * @param renderer updated renderer
722 * @param path the path identifying the edited cell
723 * @param new_text the new expiration time
724 * @param user_data unused
725 */
726void
727GNUNET_GNS_GTK_expiration_cellrenderertext_edited_cb (GtkCellRendererText *renderer,
728 gchar *path,
729 gchar *new_text,
730 gpointer user_data)
731{
732 struct GNUNET_GNS_Context * gns = user_data;
733 GtkTreeIter it;
734 struct GNUNET_TIME_Absolute abstime;
735 gboolean is_rel;
736 char *old_text;
737
738 if ((NULL != new_text))
739 {
740 gtk_tree_model_get_iter_from_string(gns->tm, &it, path);
741 gtk_tree_model_get(gns->tm, &it,
742 GNS_TREESTORE_COL_EXP_TIME_AS_STR, &old_text,
743 GNS_TREESTORE_COL_EXP_TIME_IS_REL, &is_rel,
744 -1);
745 if (0 == strcmp(new_text, old_text))
746 return;
747
748 if ((0 == strcmp(new_text,"")) || (0 == strcmp(new_text,EXPIRE_NEVER_STRING)))
749 {
750 new_text = EXPIRE_NEVER_STRING;
751 abstime = GNUNET_TIME_UNIT_FOREVER_ABS;
752 }
753 else
754 {
755 if (GNUNET_SYSERR == check_time(new_text))
756 {
757 gtk_tree_store_set (gns->ts, &it,
758 GNS_TREESTORE_COL_EXP_TIME_AS_STR, new_text,
759 GNS_TREESTORE_COL_EXP_TIME_COLOR, "red",
760 GNS_TREESTORE_COL_EXP_TIME, 0,
761 -1);
762 abstime = GNUNET_TIME_UNIT_ZERO_ABS;
763 return;
764 }
765 /* TODO: fix this when we have relative time */
766 if (TRUE == is_rel)
767 {
768 abstime = convert_string_to_abs_time(new_text);
769 }
770 else
771 {
772 abstime = convert_string_to_abs_time(new_text);
773 }
774 }
775 gtk_tree_store_set (gns->ts, &it,
776 GNS_TREESTORE_COL_EXP_TIME_AS_STR, new_text,
777 GNS_TREESTORE_COL_EXP_TIME, abstime.abs_value,
778 GNS_TREESTORE_COL_EXP_TIME_COLOR, NULL,
779 -1);
780 check_name_validity_and_commit (gns, path, NULL);
781 }
782}
783
784
785/**
786 * The user has edited a 'value' cell. Update the model,
787 * including the status on the consistency of the value with
788 * the type.
789 *
790 * @param renderer updated renderer
791 * @param path the path identifying the edited cell
792 * @param new_text the new value
793 * @param user_data unused
794 */
795void
796GNUNET_GNS_GTK_value_cellrenderertext_edited_cb (GtkCellRendererText *renderer,
797 gchar *path,
798 gchar *new_text,
799 gpointer user_data)
800{
801 struct GNUNET_GNS_Context *gns = user_data;
802 GtkTreeModel *tm = GTK_TREE_MODEL(gns->ts);
803 GtkTreeIter it;
804 size_t data_size;
805 void * data;
806 int type;
807 gchar * old_value;
808
809 if (0 != strcmp(new_text,""))
810 {
811 gtk_tree_model_get_iter_from_string(tm, &it, path);
812 gtk_tree_model_get(tm, &it,
813 GNS_TREESTORE_COL_RECORD_TYPE, &type,
814 GNS_TREESTORE_COL_VAL_AS_STR, &old_value,
815 -1);
816
817 if (old_value != NULL)
818 {
819 if (0 == strcmp(new_text, old_value))
820 {
821 GNUNET_free (old_value);
822 return;
823 }
824 GNUNET_free (old_value);
825 }
826
827 if (GNUNET_OK == GNUNET_NAMESTORE_string_to_value (type,
828 new_text,
829 &data,
830 &data_size))
831 {
832 gtk_tree_store_set (gns->ts, &it, GNS_TREESTORE_COL_VAL_COLOR, NULL, -1);
833 gtk_tree_store_set (gns->ts, &it, GNS_TREESTORE_COL_VAL_AS_STR, new_text, -1);
834 check_name_validity_and_commit (gns, path, NULL);
835 }
836 else
837 {
838 gtk_tree_store_set (gns->ts, &it, GNS_TREESTORE_COL_VAL_COLOR, "red", -1);
839 gtk_tree_store_set (gns->ts, &it, GNS_TREESTORE_COL_VAL_AS_STR, new_text, -1);
840 }
841 }
842}
843
844
845/**
846 * The user has edited a 'name' cell. Update the model (and if needed
847 * create another fresh line for additional records).
848 *
849 * @param renderer updated renderer
850 * @param path the path identifying the edited cell
851 * @param new_text the new name
852 * @param user_data unused
853 */
854void
855GNUNET_GNS_GTK_name_cellrenderertext_edited_cb (GtkCellRendererText *renderer,
856 gchar *path,
857 gchar *new_text,
858 gpointer user_data)
859{
860 struct GNUNET_GNS_Context *gns = user_data;
861 GtkTreeIter it;
862 GtkTreeIter child;
863 GtkTreeModel *tm = GTK_TREE_MODEL(gns->ts);
864 int not_dummy;
865 char *name;
866
867 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "New text for `%s' is `%s'\n", path, new_text);
868 if ((0 == strcmp (new_text, NEW_NAME_STR)) || (0 == strcmp (new_text, "")))
869 return;
870
871 gtk_tree_model_get_iter_from_string(tm, &it, path);
872 gtk_tree_model_get(tm, &it, GNS_TREESTORE_COL_NOT_DUMMY_ROW, &not_dummy, -1);
873 gtk_tree_model_get(tm, &it, GNS_TREESTORE_COL_NAME, &name, -1);
874
875 if (not_dummy == GNUNET_NO)
876 {
877 /* update name */
878 gtk_tree_store_set (gns->ts, &it,
879 GNS_TREESTORE_COL_NAME, new_text,
880 GNS_TREESTORE_COL_RECORD_TYPE, 0,
881 GNS_TREESTORE_COL_RECORD_TYPE_AS_STR, _(NEW_RECORD_STR),
882 GNS_TREESTORE_COL_NOT_DUMMY_ROW, GNUNET_YES,
883 -1);
884 check_name_validity_and_commit (gns, gtk_tree_model_get_string_from_iter(gns->tm, &it), name);
885
886 /* add a new dummy line */
887 gtk_tree_store_insert_with_values (gns->ts, &it,NULL, 0,
888 GNS_TREESTORE_COL_NAME, _(NEW_NAME_STR),
889 GNS_TREESTORE_COL_NAME_IS_VISIBLE, TRUE,
890 GNS_TREESTORE_COL_RECORD_TYPE, 1,
891 GNS_TREESTORE_COL_NOT_DUMMY_ROW, GNUNET_NO,
892 GNS_TREESTORE_COL_IS_RECORD_ROW, GNUNET_NO,
893 -1);
894 }
895 else
896 {
897 /* update name */
898 gtk_tree_store_set (gns->ts, &it, GNS_TREESTORE_COL_NAME, new_text, -1);
899
900 if (TRUE == gtk_tree_model_iter_children (gns->tm, &child, &it))
901 {
902 do
903 {
904 gtk_tree_store_set (gns->ts, &child,
905 GNS_TREESTORE_COL_NAME, &new_text,
906 -1);
907 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "New text for `%s' is `%s'\n", path, new_text);
908 }
909 while (TRUE == gtk_tree_model_iter_next (gns->tm, &child));
910 }
911
912 check_name_validity_and_commit (gns, gtk_tree_model_get_string_from_iter(gns->tm, &it), name);
913 }
914
915 if (GNUNET_SYSERR == GNUNET_NAMESTORE_check_name (new_text))
916 {
917 gtk_tree_store_set (gns->ts, &it,
918 GNS_TREESTORE_COL_NAME_COLOR, "red",
919 -1);
920 }
921 else
922 {
923 gtk_tree_store_set (gns->ts, &it,
924 GNS_TREESTORE_COL_NAME_COLOR, NULL,
925 -1);
926 }
927}
928
929
930/**
931 * The zone treeview pop up menu is supposed to be created.
932 * (Note: this is not the only method that might need to be
933 * written to handle events to create pop up menus; right-clicks
934 * might need to be managed separately).
935 *
936 * @param widget the widget
937 * @param user_data unused
938 * @return TRUE if a menu was activated
939 */
940gboolean
941GNUNET_GNS_GTK_main_treeview_popup_menu_cb (GtkWidget *widget,
942 gpointer user_data)
943{
944 struct GNUNET_GNS_Context *gns = user_data;
945 GtkTreeModel *tm;
946 GtkTreeIter it;
947 GtkMenu *popup;
948 GtkTreeSelection * ts;
949 int not_dummy;
950
951 ts = gtk_tree_view_get_selection(gns->tv);
952 if (! gtk_tree_selection_get_selected (ts, &tm, &it))
953 return TRUE;
954 gtk_tree_model_get(gns->tm, &it, GNS_TREESTORE_COL_NOT_DUMMY_ROW, &not_dummy, -1);
955 if (GNUNET_NO == not_dummy)
956 return TRUE;
957
958 popup = GTK_MENU(gtk_builder_get_object (gns->builder, "GNUNET_GNS_GTK_delete_popup_menu"));
959 gtk_widget_show_all (GTK_WIDGET(popup));
960 gtk_menu_popup(popup, NULL, NULL, NULL, NULL, 0, 0);
961 return TRUE;
962}
963
964
965static void
966set_relative_expiration_time (struct GNUNET_GNS_Context *gns, struct GNUNET_TIME_Relative reltime)
967{
968 GtkTreeIter it;
969 GtkTreeIter parent;
970 GtkCellRendererText *renderer;
971 GtkTreeModel *tm;
972 GtkTreeSelection * ts = gtk_tree_view_get_selection(gns->tv);
973 gboolean has_parent;
974 struct GNUNET_TIME_Absolute abstime;
975 char *path;
976 int not_dummy;
977
978 if (! gtk_tree_selection_get_selected (ts, &tm, &it))
979 return;
980
981 gtk_tree_model_get(tm, &it, GNS_TREESTORE_COL_NOT_DUMMY_ROW, &not_dummy, -1);
982 if (GNUNET_NO == not_dummy)
983 return;
984
985 /* Has parent? */
986 has_parent = gtk_tree_model_iter_parent (tm, &parent, &it);
987
988 if (FALSE == has_parent)
989 return;
990
991 abstime = GNUNET_TIME_absolute_add(GNUNET_TIME_absolute_get(), reltime);
992
993 /* this is a single record */
994 renderer = GTK_CELL_RENDERER_TEXT((gtk_builder_get_object (gns->builder, "GNUNET_GNS_GTK_name_cellrenderertext")));
995 path = gtk_tree_model_get_string_from_iter (tm, &it);
996 GNUNET_GNS_GTK_expiration_cellrenderertext_edited_cb (renderer,
997 path,
998 convert_time_to_string (abstime),
999 gns);
1000}
1001
1002
1003gboolean
1004GNUNET_GNS_GTK_main_treeview_popup_menu_exp1d_cb (GtkWidget *widget,
1005 gpointer user_data)
1006{
1007 set_relative_expiration_time (user_data, GNUNET_TIME_UNIT_DAYS);
1008 return TRUE;
1009}
1010
1011
1012gboolean
1013GNUNET_GNS_GTK_main_treeview_popup_menu_exp1w_cb (GtkWidget *widget,
1014 gpointer user_data)
1015{
1016 set_relative_expiration_time (user_data, GNUNET_TIME_UNIT_WEEKS);
1017 return TRUE;
1018}
1019
1020
1021gboolean
1022GNUNET_GNS_GTK_main_treeview_popup_menu_exp1y_cb (GtkWidget *widget,
1023 gpointer user_data)
1024{
1025 set_relative_expiration_time (user_data, GNUNET_TIME_UNIT_YEARS);
1026 return TRUE;
1027}
1028
1029
1030gboolean
1031GNUNET_GNS_GTK_main_treeview_popup_menu_expinf_cb (GtkWidget *widget,
1032 gpointer user_data)
1033{
1034 set_relative_expiration_time (user_data, GNUNET_TIME_UNIT_FOREVER_REL);
1035 return TRUE;
1036}
1037
1038
1039gboolean
1040GNUNET_GNS_GTK_main_treeview_button_press_popup_menu_cb (GtkWidget *widget, GdkEventButton *event, gpointer user_data)
1041{
1042 /* Check for right click*/
1043 if (NULL == widget)
1044 return FALSE;
1045 if (event->type == GDK_BUTTON_PRESS && event->button == 3)
1046 GNUNET_GNS_GTK_main_treeview_popup_menu_cb (widget, user_data);
1047 return FALSE;
1048}
1049
1050
1051gboolean
1052GNUNET_GNS_GTK_main_treeview_key_press_popup_menu_cb (GtkWidget *widget, GdkEventKey *event, gpointer user_data)
1053{
1054 /* Check for delete key */
1055 if ((event->type == GDK_KEY_PRESS) && (GDK_KEY_Delete == event->keyval))
1056 GNUNET_GNS_GTK_main_treeview_popup_menu_cb (widget, user_data);
1057 return FALSE;
1058}
1059
1060
1061struct ZoneIteration_Context
1062{
1063 struct GNUNET_GNS_Context *gns;
1064 struct GNUNET_CRYPTO_ShortHashCode zone;
1065 struct GNUNET_NAMESTORE_ZoneIterator * it;
1066 char *label;
1067};
1068
1069
1070void
1071GNUNET_GNS_GTK_delete_popup_menu_delete_cb (GtkMenuItem *menuitem,
1072 gpointer user_data)
1073{
1074 struct GNUNET_GNS_Context *gns = user_data;
1075 GtkTreeIter it;
1076 GtkTreeModel *tm;
1077 GtkTreeSelection * ts;
1078 int not_dummy;
1079 char *path;
1080
1081 ts = gtk_tree_view_get_selection(gns->tv);
1082 if (gtk_tree_selection_get_selected (ts, &tm, &it))
1083 {
1084 gtk_tree_model_get(tm, &it, GNS_TREESTORE_COL_NOT_DUMMY_ROW, &not_dummy, -1);
1085 if (GNUNET_NO == not_dummy)
1086 return; /* do not delete the dummy line */
1087
1088 path = gtk_tree_model_get_string_from_iter (gns->tm, &it);
1089 check_name_validity_and_remove(gns, path);
1090 g_free (path);
1091 }
1092}
1093
1094
1095static void
1096zone_iteration_proc (void *cls,
1097 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
1098 struct GNUNET_TIME_Absolute expire,
1099 const char *name,
1100 unsigned int rd_count,
1101 const struct GNUNET_NAMESTORE_RecordData *rd,
1102 const struct GNUNET_CRYPTO_RsaSignature *signature)
1103{
1104 struct ZoneIteration_Context * zc_ctx = cls;
1105 GtkTreeIter iter_name;
1106 GtkTreeIter iter_record;
1107 GtkEntry *pseu_entry;
1108 int c;
1109 int time_is_relative;
1110
1111 char *exp;
1112 char *val;
1113 char * type_str;
1114 int public;
1115 guint64 exp_t;
1116
1117 GNUNET_assert (zc_ctx != NULL);
1118 if ((NULL == zone_key) && (NULL == name))
1119 {
1120 struct GNUNET_CRYPTO_ShortHashAsciiEncoded shenc;
1121 GNUNET_CRYPTO_short_hash_to_enc(&zc_ctx->zone, &shenc);
1122 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Zone `%s 'iteration done\n", &shenc);
1123 pseu_entry = GTK_ENTRY((gtk_builder_get_object (zc_ctx->gns->builder, "GNUNET_GNS_GTK_pseu_entry")));
1124 if (zc_ctx->label == NULL)
1125 GNUNET_asprintf(&zc_ctx->label, "%s", PSEU_EMPTY_STR);
1126 gtk_entry_set_text (pseu_entry, zc_ctx->label);
1127 zc_ctx->gns->iteration = GNUNET_NO;
1128 GNUNET_free (zc_ctx->label);
1129 GNUNET_free (zc_ctx);
1130 return;
1131 }
1132
1133
1134 struct GNUNET_CRYPTO_ShortHashAsciiEncoded shenc;
1135 GNUNET_CRYPTO_short_hash_to_enc(&zc_ctx->zone, &shenc);
1136 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Zone `%s' iteration result `%s', %u records\n",
1137 &shenc, name, rd_count);
1138
1139 GNUNET_assert(GTK_IS_TREE_STORE(zc_ctx->gns->ts));
1140 gtk_tree_store_append(zc_ctx->gns->ts, &iter_name, NULL);
1141 gtk_tree_store_set(zc_ctx->gns->ts, &iter_name,
1142 GNS_TREESTORE_COL_NAME, name,
1143 GNS_TREESTORE_COL_NAME_IS_VISIBLE, TRUE,
1144 GNS_TREESTORE_COL_RECORD_TYPE, 0,
1145 GNS_TREESTORE_COL_RECORD_TYPE_AS_STR, _(NEW_RECORD_STR),
1146 GNS_TREESTORE_COL_IS_RECORD_ROW, GNUNET_NO,
1147 GNS_TREESTORE_COL_NOT_DUMMY_ROW, GNUNET_YES,
1148 -1);
1149
1150 if (GNUNET_SYSERR == GNUNET_NAMESTORE_check_name (name))
1151 {
1152 gtk_tree_store_set (zc_ctx->gns->ts, &iter_name,
1153 GNS_TREESTORE_COL_NAME_COLOR, "red",
1154 -1);
1155 }
1156 /* Append elements for records */
1157 for (c = 0; c < rd_count; c ++)
1158 {
1159 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Record %u: type %u flags %u expiration %llu data_size %u\n",
1160 c, rd[c].record_type, rd[c].flags, rd[c].expiration_time, rd[c].data_size);
1161
1162 /* Set public toggle */
1163 if ((rd[c].flags & GNUNET_NAMESTORE_RF_PRIVATE) == GNUNET_NAMESTORE_RF_PRIVATE)
1164 {
1165 public = GNUNET_NO;
1166 }
1167 else
1168 {
1169 public = GNUNET_YES;
1170 }
1171
1172 /* Expiration time */
1173 time_is_relative = GNUNET_NO;
1174
1175 if (GNUNET_YES == time_is_relative)
1176 {
1177 /* TODO: FIX THIS WHEN WE HAVE RELATIVE TIME */
1178 struct GNUNET_TIME_Relative rel_time = GNUNET_TIME_UNIT_ZERO;
1179 struct GNUNET_TIME_Absolute exp_abs;
1180 exp_abs = GNUNET_TIME_absolute_add(GNUNET_TIME_absolute_get(), rel_time);
1181 exp_t = exp_abs.abs_value;
1182 exp = convert_time_to_string (exp_abs);
1183 }
1184 else
1185 {
1186 struct GNUNET_TIME_Absolute exp_abs;
1187
1188 exp_abs.abs_value = rd[c].expiration_time;
1189 exp_t = exp_abs.abs_value;
1190 exp = convert_time_to_string (exp_abs);
1191 }
1192 /* value */
1193 val = GNUNET_NAMESTORE_value_to_string (rd[c].record_type,
1194 rd[c].data,
1195 rd[c].data_size);
1196 if (NULL == val)
1197 GNUNET_asprintf(&val, "%s", EXPIRE_INVALID_STRING);
1198
1199 if (NULL != GNUNET_NAMESTORE_number_to_typename(rd[c].record_type))
1200 type_str = strdup (GNUNET_NAMESTORE_number_to_typename(rd[c].record_type));
1201 else
1202 GNUNET_asprintf(&type_str, "%s", EXPIRE_INVALID_STRING);
1203
1204 if ((0 ==strcmp (name, ROOT_STR)) && (GNUNET_NAMESTORE_TYPE_PSEU == rd[c].record_type))
1205 {
1206 zc_ctx->label = strdup(val);
1207 zc_ctx->gns->iteration = GNUNET_YES;
1208 }
1209 else
1210 {
1211 gtk_tree_store_insert_with_values(zc_ctx->gns->ts, &iter_record , &iter_name, 0,
1212 GNS_TREESTORE_COL_NAME, name,
1213 GNS_TREESTORE_COL_NAME_IS_VISIBLE, FALSE,
1214 GNS_TREESTORE_COL_RECORD_TYPE, rd[c].record_type,
1215 GNS_TREESTORE_COL_RECORD_TYPE_AS_STR, type_str,
1216 GNS_TREESTORE_COL_IS_PUBLIC, public,
1217 GNS_TREESTORE_COL_EXP_TIME, exp_t,
1218 GNS_TREESTORE_COL_EXP_TIME_AS_STR, exp,
1219 GNS_TREESTORE_COL_EXP_TIME_IS_REL, time_is_relative,
1220 GNS_TREESTORE_COL_VAL_AS_STR, val,
1221 GNS_TREESTORE_COL_IS_RECORD_ROW, GNUNET_YES,
1222 GNS_TREESTORE_COL_NOT_DUMMY_ROW, GNUNET_YES,
1223 -1);
1224 }
1225 GNUNET_free (type_str);
1226 GNUNET_free (exp);
1227 GNUNET_free (val);
1228 }
1229
1230 GNUNET_NAMESTORE_zone_iterator_next(zc_ctx->it);
1231}
1232
1233
1234/**
1235 * The zone treeview was realized. Setup the model.
1236 *
1237 * @param widget the widget
1238 * @param user_data unused
1239 */
1240void
1241GNUNET_GNS_GTK_main_treeview_realize_cb (GtkWidget *widget,
1242 gpointer user_data)
1243{
1244 struct GNUNET_GNS_Context *gns = user_data;
1245 struct ZoneIteration_Context *zc_ctx;
1246 GtkTreeIter toplevel;
1247
1248 /* Append a top level row and leave it empty */
1249 gtk_tree_store_insert_with_values(gns->ts, &toplevel, NULL, 0,
1250 GNS_TREESTORE_COL_NAME, _(NEW_NAME_STR),
1251 GNS_TREESTORE_COL_NAME_IS_VISIBLE, TRUE,
1252 GNS_TREESTORE_COL_RECORD_TYPE, 1,
1253 GNS_TREESTORE_COL_IS_RECORD_ROW, GNUNET_NO,
1254 GNS_TREESTORE_COL_NOT_DUMMY_ROW, GNUNET_NO,
1255 -1);
1256
1257 zc_ctx = GNUNET_malloc (sizeof (struct ZoneIteration_Context));
1258 zc_ctx->gns = user_data;
1259 zc_ctx->zone = gns->zone;
1260 zc_ctx->it = GNUNET_NAMESTORE_zone_iteration_start(gns->ns, &gns->zone,
1261 GNUNET_NAMESTORE_RF_NONE,
1262 GNUNET_NAMESTORE_RF_NONE,
1263 &zone_iteration_proc,
1264 zc_ctx);
1265}
1266
1267
1268/* end of gnunet-gns-gtk_zone.c */