aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2011-08-15 14:17:02 +0000
committerChristian Grothoff <christian@grothoff.org>2011-08-15 14:17:02 +0000
commitc50398781a738775dec1ea1332a53ed7f92edf2a (patch)
treebc1a10fa2a1c869fd8d63692fad31217903cb7dd
parent40fb14ed28d5be33a58927c56b70f76215974c16 (diff)
downloadgnunet-gtk-c50398781a738775dec1ea1332a53ed7f92edf2a.tar.gz
gnunet-gtk-c50398781a738775dec1ea1332a53ed7f92edf2a.zip
removing old fs code
-rw-r--r--src/Makefile.am37
-rw-r--r--src/about.c50
-rw-r--r--src/common.c183
-rw-r--r--src/common.h156
-rw-r--r--src/download.c136
-rw-r--r--src/download.h83
-rw-r--r--src/edit_publish_dialog.c771
-rw-r--r--src/edit_publish_dialog.h41
-rw-r--r--src/fs_anonymity_spin_buttons.c73
-rw-r--r--src/fs_event_handler.c2027
-rw-r--r--src/fs_event_handler.h198
-rw-r--r--src/gnunet-gtk.c1119
-rw-r--r--src/main_window_adv_pseudonym.c587
-rw-r--r--src/main_window_create_pseudonym.c64
-rw-r--r--src/main_window_file_download.c130
-rw-r--r--src/main_window_file_publish.c1932
-rw-r--r--src/main_window_file_search.c242
-rw-r--r--src/main_window_open_directory.c147
-rw-r--r--src/main_window_view_toggles.c89
-rw-r--r--src/os_installation.c441
-rw-r--r--src/peerinfo.c90
-rw-r--r--src/peerinfo.h47
22 files changed, 1 insertions, 8642 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 30d1d1f7..9e6f6138 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,37 +1,2 @@
1SUBDIRS = . 1SUBDIRS = . include lib fs setup
2 2
3INCLUDES = \
4 -I$(top_srcdir)/ \
5 @GTK_CFLAGS@ \
6 @GNUNET_CFLAGS@ \
7 @GLADE_CFLAGS@
8
9bin_PROGRAMS = gnunet-gtk
10
11gnunet_gtk_SOURCES = \
12 about.c \
13 common.c common.h \
14 download.c download.h \
15 edit_publish_dialog.c edit_publish_dialog.h \
16 fs_event_handler.c fs_event_handler.h \
17 fs_anonymity_spin_buttons.c \
18 gnunet-gtk.c \
19 main_window_create_pseudonym.c \
20 main_window_file_download.c \
21 main_window_file_publish.c \
22 main_window_file_search.c \
23 main_window_open_directory.c \
24 main_window_adv_pseudonym.c \
25 main_window_view_toggles.c \
26 os_installation.c \
27 peerinfo.c peerinfo.h
28gnunet_gtk_LDADD = \
29 @GTK_LIBS@ \
30 @GLADE_LIBS@ \
31 -lextractor \
32 -lgnunetutil \
33 -lgnunetpeerinfo \
34 -lgnunetfs \
35 $(INTLLIBS)
36gnunet_gtk_LDFLAGS = \
37 -export-dynamic
diff --git a/src/about.c b/src/about.c
deleted file mode 100644
index b3e867ad..00000000
--- a/src/about.c
+++ /dev/null
@@ -1,50 +0,0 @@
1/*
2 This file is part of GNUnet
3 (C) 2005, 2006, 2010 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/about.c
23 * @author Christian Grothoff
24 * @author Igor Wronsky
25 *
26 * This file contains the about dialog.
27 */
28#include "common.h"
29
30/**
31 * This displays an about window
32 */
33void
34GNUNET_GTK_main_menu_help_about_activate_cb (GtkWidget * dummy, gpointer data)
35{
36 GtkBuilder *builder;
37 GtkWidget *ad;
38
39 builder = GNUNET_GTK_get_new_builder ("about.glade");
40 if (builder == NULL)
41 return;
42 ad = GTK_WIDGET (gtk_builder_get_object (builder,
43 "GNUNET_GTK_about_dialog"));
44 gtk_dialog_run (GTK_DIALOG (ad));
45 gtk_widget_destroy (ad);
46 g_object_unref (G_OBJECT (builder));
47}
48
49
50/* end of about.c */
diff --git a/src/common.c b/src/common.c
deleted file mode 100644
index 55dbc0f9..00000000
--- a/src/common.c
+++ /dev/null
@@ -1,183 +0,0 @@
1/*
2 This file is part of GNUnet.
3 (C) 2010 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/common.c
23 * @brief Common functions used in various places
24 * @author Christian Grothoff
25 */
26#include "common.h"
27
28/**
29 * Add meta data to list store.
30 *
31 * @param cls closure (the GtkListStore)
32 * @param plugin_name name of the plugin that produced this value;
33 * special values can be used (i.e. '<zlib>' for zlib being
34 * used in the main libextractor library and yielding
35 * meta data).
36 * @param type libextractor-type describing the meta data
37 * @param format basic format information about data
38 * @param data_mime_type mime-type of data (not of the original file);
39 * can be NULL (if mime-type is not known)
40 * @param data actual meta-data found
41 * @param data_len number of bytes in data
42 * @return 0 to continue (always)
43 */
44int
45GNUNET_GTK_add_meta_data_to_list_store (void *cls,
46 const char *plugin_name,
47 enum EXTRACTOR_MetaType type,
48 enum EXTRACTOR_MetaFormat format,
49 const char *data_mime_type,
50 const char *data,
51 size_t data_len)
52{
53 GtkListStore *ls = GTK_LIST_STORE (cls);
54
55 if ( (format == EXTRACTOR_METAFORMAT_UTF8) ||
56 (format == EXTRACTOR_METAFORMAT_C_STRING) )
57 gtk_list_store_insert_with_values (ls,
58 NULL,
59 G_MAXINT,
60 0, type,
61 1, format,
62 2, EXTRACTOR_metatype_to_string (type),
63 3, data,
64 -1);
65 return 0;
66}
67
68
69/**
70 * Convert the year from the spin button to an expiration
71 * time (on midnight, January 1st of that year).
72 */
73struct GNUNET_TIME_Absolute
74GNUNET_GTK_get_expiration_time (GtkSpinButton *spin)
75{
76 struct GNUNET_TIME_Absolute ret;
77 int year;
78
79 year = gtk_spin_button_get_value_as_int (spin);
80 GNUNET_assert (year >= 0);
81 ret = GNUNET_FS_year_to_time ( (unsigned int) year);
82 GNUNET_break (GNUNET_TIME_absolute_get ().abs_value < ret.abs_value);
83 return ret;
84}
85
86
87void
88GNUNET_GTK_setup_expiration_year_adjustment (GtkBuilder *builder)
89{
90 GtkAdjustment *aj;
91 unsigned int year;
92
93 year = GNUNET_FS_get_current_year ();
94 aj = GTK_ADJUSTMENT (gtk_builder_get_object (builder,
95 "expiration_year_adjustment"));
96 gtk_adjustment_set_value (aj, year + 2);
97 gtk_adjustment_set_lower (aj, year + 1);
98}
99
100
101GdkPixbuf *
102GNUNET_GTK_get_thumbnail_from_meta_data (const struct GNUNET_CONTAINER_MetaData *meta)
103{
104 GdkPixbuf *pixbuf;
105 GdkPixbufLoader *loader;
106 size_t ts;
107 unsigned char *thumb;
108
109 thumb = NULL;
110 ts = GNUNET_CONTAINER_meta_data_get_thumbnail (meta, &thumb);
111 if (ts == 0)
112 return NULL;
113 loader = gdk_pixbuf_loader_new ();
114 gdk_pixbuf_loader_write (loader, (const guchar *) thumb, ts, NULL);
115 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
116 gdk_pixbuf_loader_close (loader, NULL);
117 if (pixbuf != NULL)
118 g_object_ref (pixbuf);
119 g_object_unref (loader);
120 GNUNET_free (thumb);
121 return pixbuf;
122}
123
124
125/**
126 * mmap the given file and run the GNUNET_FS_directory_list_contents
127 * function on it.
128 */
129void
130GNUNET_GTK_mmap_and_scan (const char *filename,
131 GNUNET_FS_DirectoryEntryProcessor dep,
132 void *dep_cls)
133{
134 struct GNUNET_DISK_FileHandle *fh;
135 struct GNUNET_DISK_MapHandle *mh;
136 uint64_t fsize;
137 void * ddata;
138
139 if (GNUNET_OK !=
140 GNUNET_DISK_file_size (filename,
141 &fsize,
142 GNUNET_YES))
143 {
144 GNUNET_break (0);
145 return;
146 }
147 fh = GNUNET_DISK_file_open (filename,
148 GNUNET_DISK_OPEN_READ,
149 GNUNET_DISK_PERM_NONE);
150 if (fh == NULL)
151 {
152 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", filename);
153 return;
154 }
155 ddata = GNUNET_DISK_file_map (fh,
156 &mh,
157 GNUNET_DISK_MAP_TYPE_READ,
158 (size_t) fsize);
159 if (ddata == NULL)
160 {
161 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "mmap", filename);
162 GNUNET_break (GNUNET_OK ==
163 GNUNET_DISK_file_close (fh));
164 return;
165 }
166 if (GNUNET_SYSERR ==
167 GNUNET_FS_directory_list_contents ((size_t) fsize,
168 ddata,
169 0,
170 dep, dep_cls))
171 {
172 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
173 _("Selected file `%s' is not a GNUnet directory!\n"),
174 filename);
175 }
176 GNUNET_break (GNUNET_OK ==
177 GNUNET_DISK_file_unmap (mh));
178 GNUNET_break (GNUNET_OK ==
179 GNUNET_DISK_file_close (fh));
180}
181
182
183/* end of common.c */
diff --git a/src/common.h b/src/common.h
deleted file mode 100644
index 5a14836a..00000000
--- a/src/common.h
+++ /dev/null
@@ -1,156 +0,0 @@
1/*
2 This file is part of GNUnet.
3 (C) 2010 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/common.h
23 * @brief Common includes for all gnunet-gtk source files
24 * @author Christian Grothoff
25 */
26#ifndef COMMON_H
27#define COMMON_H
28
29#ifndef HAVE_USED_CONFIG_H
30#define HAVE_USED_CONFIG_H
31#include "gnunet_gtk_config.h"
32#endif
33#include <gnunet/platform.h>
34#include <gnunet/gnunet_util_lib.h>
35#include <gnunet/gnunet_fs_service.h>
36#include <extractor.h>
37#include <gladeui/glade.h>
38#include <gtk/gtk.h>
39
40
41/**
42 * Get the name of the directory where all of our package
43 * data is stored ($PREFIX/share/)
44 *
45 * @return name of the data directory
46 */
47const char *
48GNUNET_GTK_get_data_dir (void);
49
50/**
51 * @brief get the path to a specific GNUnet installation directory or,
52 * with GNUNET_IPK_SELF_PREFIX, the current running apps installation directory
53 * @author Milan
54 * @return a pointer to the dir path (to be freed by the caller)
55 */
56char *
57GNUNET_GTK_installation_get_path (enum GNUNET_OS_InstallationPathKind dirkind);
58
59
60GdkPixbuf *
61GNUNET_GTK_get_thumbnail_from_meta_data (const struct GNUNET_CONTAINER_MetaData *meta);
62
63/**
64 * Setup the expiration year adjustment to start with the
65 * next year and default to next year plus one.
66 */
67void
68GNUNET_GTK_setup_expiration_year_adjustment (GtkBuilder *builder);
69
70/**
71 * Convert the year from the spin button to an expiration
72 * time (on midnight, January 1st of that year).
73 */
74struct GNUNET_TIME_Absolute
75GNUNET_GTK_get_expiration_time (GtkSpinButton *spin);
76
77
78/**
79 * mmap the given file and run the GNUNET_FS_directory_list_contents
80 * function on it.
81 */
82void
83GNUNET_GTK_mmap_and_scan (const char *filename,
84 GNUNET_FS_DirectoryEntryProcessor dep,
85 void *dep_cls);
86
87
88/**
89 * Create an initialize a new builder based on the
90 * GNUnet-GTK glade file.
91 *
92 * @param filename name of the resource file to load
93 * @return NULL on error
94 */
95GtkBuilder *
96GNUNET_GTK_get_new_builder (const char *filename);
97
98/**
99 * Get an object from the main window.
100 *
101 * @param name name of the object
102 * @return NULL on error
103 */
104GObject *
105GNUNET_GTK_get_main_window_object (const char *name);
106
107
108/**
109 * Get LE plugin list.
110 */
111struct EXTRACTOR_PluginList *
112GNUNET_GTK_get_le_plugins (void);
113
114
115/**
116 * Get cfg.
117 */
118const struct GNUNET_CONFIGURATION_Handle *
119GNUNET_GTK_get_configuration (void);
120
121
122/**
123 * Return handle for file-sharing operations.
124 * @return NULL on error
125 */
126struct GNUNET_FS_Handle *
127GNUNET_GTK_get_fs_handle (void);
128
129
130/**
131 * Add meta data to list store.
132 *
133 * @param cls closure (the GtkListStore)
134 * @param plugin_name name of the plugin that produced this value;
135 * special values can be used (i.e. '<zlib>' for zlib being
136 * used in the main libextractor library and yielding
137 * meta data).
138 * @param type libextractor-type describing the meta data
139 * @param format basic format information about data
140 * @param data_mime_type mime-type of data (not of the original file);
141 * can be NULL (if mime-type is not known)
142 * @param data actual meta-data found
143 * @param data_len number of bytes in data
144 * @return 0 to continue (always)
145 */
146int
147GNUNET_GTK_add_meta_data_to_list_store (void *cls,
148 const char *plugin_name,
149 enum EXTRACTOR_MetaType type,
150 enum EXTRACTOR_MetaFormat format,
151 const char *data_mime_type,
152 const char *data,
153 size_t data_len);
154
155#endif
156/* end of common.h */
diff --git a/src/download.c b/src/download.c
deleted file mode 100644
index d6f70bf7..00000000
--- a/src/download.c
+++ /dev/null
@@ -1,136 +0,0 @@
1/*
2 This file is part of GNUnet.
3 (C) 2010 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/download.c
23 * @brief functions for downloading
24 * @author Christian Grothoff
25 */
26
27#include "download.h"
28#include "fs_event_handler.h"
29
30void
31GNUNET_GTK_open_download_as_dialog (struct DownloadContext *dc)
32{
33 GtkWidget *ad;
34 GtkBuilder *builder;
35 struct GNUNET_FS_Handle *fs;
36 uint64_t len;
37 enum GNUNET_FS_DownloadOptions opt;
38 uint32_t anonymity;
39 struct DownloadEntry *de;
40 GtkWidget *cb;
41
42 builder = GNUNET_GTK_get_new_builder ("download_as.glade");
43 if (builder == NULL)
44 {
45 if (dc->rr != NULL)
46 gtk_tree_row_reference_free (dc->rr);
47 GNUNET_free_non_null (dc->mime);
48 GNUNET_free_non_null (dc->filename);
49 GNUNET_FS_uri_destroy (dc->uri);
50 GNUNET_free (dc);
51 return;
52 }
53 cb = GTK_WIDGET (gtk_builder_get_object (builder,
54 "GNUNET_GTK_save_as_recursive_check_button"));
55 if (GNUNET_FS_meta_data_test_for_directory (dc->meta))
56 gtk_widget_set_sensitive (cb, TRUE);
57 ad = GTK_WIDGET (gtk_builder_get_object (builder,
58 "GNUNET_GTK_save_as_dialog"));
59 if (dc->filename != NULL)
60 {
61 char buf[1024];
62 if (NULL != getcwd (buf, sizeof(buf)))
63 {
64 if (strlen (buf) + strlen (dc->filename) + 2 < sizeof(buf))
65 {
66 strcat (buf, DIR_SEPARATOR_STR);
67 strcat (buf, dc->filename);
68 }
69 gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (ad),
70 buf);
71 }
72 }
73 if (GTK_RESPONSE_OK != gtk_dialog_run (GTK_DIALOG (ad)))
74 {
75 gtk_widget_destroy (ad);
76 g_object_unref (G_OBJECT (builder));
77 if (dc->rr != NULL)
78 gtk_tree_row_reference_free (dc->rr);
79 GNUNET_free_non_null (dc->mime);
80 GNUNET_free_non_null (dc->filename);
81 GNUNET_FS_uri_destroy (dc->uri);
82 GNUNET_free (dc);
83 return;
84 }
85 GNUNET_free_non_null (dc->filename);
86 dc->filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER(ad));
87 dc->is_recursive = (TRUE == gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (cb))) ? GNUNET_YES : GNUNET_NO;
88 fs = GNUNET_GTK_get_fs_handle ();
89 opt = GNUNET_FS_DOWNLOAD_OPTION_NONE;
90 if (dc->is_recursive)
91 opt |= GNUNET_FS_DOWNLOAD_OPTION_RECURSIVE;
92 anonymity = gtk_spin_button_get_value (GTK_SPIN_BUTTON (gtk_builder_get_object (builder,
93 "GNUNET_GTK_save_as_dialog_anonymity_spin_button")));
94 len = GNUNET_FS_uri_chk_get_file_size (dc->uri);
95 gtk_widget_destroy (ad);
96 g_object_unref (G_OBJECT (builder));
97 de = GNUNET_malloc (sizeof (struct DownloadEntry));
98 de->uri = dc->uri;
99 de->meta = dc->meta;
100 if (dc->rr != NULL)
101 {
102 de->rr = dc->rr;
103 de->ts = GTK_TREE_STORE (gtk_tree_row_reference_get_model (dc->rr));
104 }
105 if (dc->sr != NULL)
106 {
107 GNUNET_break (NULL !=
108 GNUNET_FS_download_start_from_search (fs,
109 dc->sr,
110 dc->filename,
111 NULL /* tempname */,
112 0 /* offset */,
113 len,
114 anonymity,
115 opt,
116 de));
117 }
118 else
119 {
120 GNUNET_break (NULL !=
121 GNUNET_FS_download_start (fs,
122 dc->uri,
123 NULL /* meta */,
124 dc->filename,
125 NULL /* tempname */,
126 0 /* offset */,
127 len,
128 anonymity,
129 opt,
130 de,
131 NULL /* parent download ctx */));
132 }
133 GNUNET_free (dc);
134}
135
136/* end of download.c */
diff --git a/src/download.h b/src/download.h
deleted file mode 100644
index e2c8767b..00000000
--- a/src/download.h
+++ /dev/null
@@ -1,83 +0,0 @@
1/*
2 This file is part of GNUnet.
3 (C) 2010 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/download.h
23 * @brief functions for downloading
24 * @author Christian Grothoff
25 */
26
27#ifndef DOWNLOAD_H
28#define DOWNLOAD_H
29#include "common.h"
30
31/**
32 * Information we keep for a download.
33 */
34struct DownloadContext
35{
36 /**
37 * URI for the download.
38 */
39 struct GNUNET_FS_Uri *uri;
40
41 /**
42 * Meta data.
43 */
44 struct GNUNET_CONTAINER_MetaData *meta;
45
46 /**
47 * Mime type.
48 */
49 char *mime;
50
51 /**
52 * Suggested filename, or NULL.
53 */
54 char *filename;
55
56 /**
57 * Row reference (if URI was found by search, or
58 * part of directory, etc.); otherwise NULL (download by URI).
59 */
60 GtkTreeRowReference *rr;
61
62 /**
63 * Associated search result, or NULL.
64 */
65 struct GNUNET_FS_SearchResult *sr;
66
67 /**
68 * Is this a recursive download?
69 */
70 int is_recursive;
71
72 /**
73 * Desired (default) anonymity level.
74 */
75 int anonymity;
76};
77
78
79
80void
81GNUNET_GTK_open_download_as_dialog (struct DownloadContext *dc);
82
83#endif
diff --git a/src/edit_publish_dialog.c b/src/edit_publish_dialog.c
deleted file mode 100644
index 527733b3..00000000
--- a/src/edit_publish_dialog.c
+++ /dev/null
@@ -1,771 +0,0 @@
1/*
2 This file is part of GNUnet
3 (C) 2005, 2006, 2010 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/edit_publish_dialog.c
23 * @author Christian Grothoff
24 */
25#include "common.h"
26#include "edit_publish_dialog.h"
27#include <gnunet/gnunet_util_lib.h>
28
29/**
30 * Builder for the current dialog.
31 */
32static GtkBuilder *builder;
33
34/**
35 * Are we editing metadata for a directory?
36 */
37static int is_directory;
38
39/**
40 * Set to YES if the preview was changed.
41 */
42static int preview_changed;
43
44void
45GNUNET_GTK_edit_file_information_keyword_list_normalize_button_clicked_cb ()
46{
47 GNUNET_break (0);
48}
49
50void
51GNUNET_GTK_edit_file_information_keyword_list_del_button_clicked_cb ()
52{
53 GtkTreeView *tv;
54 GtkTreeSelection *sel;
55 GtkTreeModel *tm;
56 GtkTreeIter iter;
57
58 tv = GTK_TREE_VIEW (gtk_builder_get_object (builder,
59 "GNUNET_GTK_edit_file_information_keyword_list_tree_view"));
60 sel = gtk_tree_view_get_selection (tv);
61 if (TRUE != gtk_tree_selection_get_selected (sel, &tm, &iter))
62 {
63 GNUNET_break (0);
64 return;
65 }
66 gtk_list_store_remove (GTK_LIST_STORE (tm),
67 &iter);
68}
69
70void
71GNUNET_GTK_edit_file_information_keyword_list_add_button_clicked_cb ()
72{
73 const char *keyword;
74 GtkEntry *entry;
75 GtkListStore *ls;
76 GtkTreeIter iter;
77
78 ls = GTK_LIST_STORE (gtk_builder_get_object (builder,
79 "GNUNET_GTK_keyword_list_store"));
80 entry = GTK_ENTRY (gtk_builder_get_object (builder,
81 "GNUNET_GTK_edit_file_information_keyword_entry"));
82 keyword = gtk_entry_get_text (entry);
83 if (strlen (keyword) > 0)
84 gtk_list_store_insert_with_values (ls, &iter, G_MAXINT, 0, keyword, -1);
85 gtk_entry_set_text (entry, "");
86}
87
88
89void
90GNUNET_GTK_edit_file_information_keyword_entry_changed_cb ()
91{
92 const char *keyword;
93 GtkEntry *entry;
94 GtkWidget *button;
95
96 button = GTK_WIDGET (gtk_builder_get_object (builder,
97 "GNUNET_GTK_edit_file_information_keyword_list_add_button"));
98 entry = GTK_ENTRY (gtk_builder_get_object (builder,
99 "GNUNET_GTK_edit_file_information_keyword_entry"));
100 keyword = gtk_entry_get_text (entry);
101 gtk_widget_set_sensitive (button,
102 (strlen (keyword) > 0) ? TRUE : FALSE);
103}
104
105
106static void
107metadata_selection_changed_cb (GtkTreeSelection *ts,
108 gpointer user_data)
109{
110 GtkTreeView *tv;
111 GtkTreeSelection *sel;
112 GtkWidget *button;
113
114 tv = GTK_TREE_VIEW (gtk_builder_get_object (builder,
115 "GNUNET_GTK_edit_file_information_metadata_tree_view"));
116 sel = gtk_tree_view_get_selection (tv);
117 button = GTK_WIDGET (gtk_builder_get_object (builder,
118 "GNUNET_GTK_edit_file_information_metadata_delete_button"));
119 gtk_widget_set_sensitive (button,
120 gtk_tree_selection_get_selected (sel, NULL, NULL));
121}
122
123
124static void
125keyword_selection_changed_cb (GtkTreeSelection *ts,
126 gpointer user_data)
127{
128 GtkTreeView *tv;
129 GtkTreeSelection *sel;
130 GtkWidget *button;
131
132 tv = GTK_TREE_VIEW (gtk_builder_get_object (builder,
133 "GNUNET_GTK_edit_file_information_keyword_list_tree_view"));
134 sel = gtk_tree_view_get_selection (tv);
135 button = GTK_WIDGET (gtk_builder_get_object (builder,
136 "GNUNET_GTK_edit_file_information_keyword_list_del_button"));
137
138 gtk_widget_set_sensitive (button,
139 gtk_tree_selection_get_selected (sel, NULL, NULL));
140 button = GTK_WIDGET (gtk_builder_get_object (builder,
141 "GNUNET_GTK_edit_file_information_keyword_list_normalize_button"));
142 gtk_widget_set_sensitive (button,
143 gtk_tree_selection_get_selected (sel, NULL, NULL));
144}
145
146
147void
148GNUNET_GTK_edit_file_information_metadata_value_entry_changed_cb ()
149{
150 GtkTreeView *tv;
151 GtkTreeSelection *sel;
152 const char *value;
153 GtkEntry *entry;
154 GtkWidget *button;
155
156 entry = GTK_ENTRY (gtk_builder_get_object (builder,
157 "GNUNET_GTK_edit_file_information_metadata_value_entry"));
158 value = gtk_entry_get_text (entry);
159 tv = GTK_TREE_VIEW (gtk_builder_get_object (builder,
160 "GNUNET_GTK_edit_file_information_metadata_type_tree_view"));
161 sel = gtk_tree_view_get_selection (tv);
162 button = GTK_WIDGET (gtk_builder_get_object (builder,
163 "GNUNET_GTK_edit_file_information_metadata_add_button"));
164 gtk_widget_set_sensitive (button,
165 (strlen (value) > 0)
166 ? gtk_tree_selection_get_selected (sel, NULL, NULL)
167 : FALSE);
168}
169
170
171void
172GNUNET_GTK_edit_file_information_keyword_entry_activate_cb ()
173{
174 GNUNET_GTK_edit_file_information_keyword_list_add_button_clicked_cb ();
175}
176
177
178void
179GNUNET_GTK_edit_file_information_metadata_preview_file_chooser_button_file_set_cb (GtkFileChooserButton *widget,
180 gpointer user_data)
181{
182 gchar *fn;
183 GtkImage *image;
184
185 fn = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget));
186 image = GTK_IMAGE (gtk_builder_get_object (builder,
187 "GNUNET_GTK_edit_file_information_metadata_preview_image"));
188 gtk_image_set_from_file (image, fn);
189 preview_changed = GNUNET_YES;
190}
191
192
193void
194GNUNET_GTK_edit_file_information_metadata_delete_button_clicked_cb()
195{
196 GtkTreeView *tv;
197 GtkTreeSelection *sel;
198 GtkTreeModel *tm;
199 GtkTreeIter iter;
200
201 tv = GTK_TREE_VIEW (gtk_builder_get_object (builder,
202 "GNUNET_GTK_edit_file_information_metadata_tree_view"));
203 sel = gtk_tree_view_get_selection (tv);
204 if (TRUE != gtk_tree_selection_get_selected (sel, &tm, &iter))
205 {
206 GNUNET_break (0);
207 return;
208 }
209 gtk_list_store_remove (GTK_LIST_STORE (tm),
210 &iter);
211}
212
213
214void
215GNUNET_GTK_edit_file_information_metadata_add_button_clicked_cb ()
216{
217 const char *value;
218 char *avalue;
219 const char *ivalue;
220 GtkEntry *entry;
221 GtkListStore *ls;
222 GtkTreeModel *tm;
223 GtkTreeView *tv;
224 GtkTreeSelection *sel;
225 GtkTreeIter iter;
226 guint type;
227 size_t slen;
228 char *pos;
229
230 entry = GTK_ENTRY (gtk_builder_get_object (builder,
231 "GNUNET_GTK_edit_file_information_metadata_value_entry"));
232 value = gtk_entry_get_text (entry);
233 if ((value == NULL) || (strlen (value) == 0))
234 {
235 GNUNET_break (0);
236 return;
237 }
238 tv = GTK_TREE_VIEW (gtk_builder_get_object (builder,
239 "GNUNET_GTK_edit_file_information_metadata_type_tree_view"));
240 tm = gtk_tree_view_get_model (tv);
241 sel = gtk_tree_view_get_selection (tv);
242 if (TRUE != gtk_tree_selection_get_selected (sel,
243 &tm,
244 &iter))
245 {
246 GNUNET_break (0);
247 return;
248 }
249 gtk_tree_model_get (tm,
250 &iter,
251 1, &type, -1);
252 ls = GTK_LIST_STORE (gtk_builder_get_object (builder,
253 "GNUNET_GTK_meta_data_list_store"));
254 if ( (type == EXTRACTOR_METATYPE_FILENAME) &&
255 (value[strlen(value)-1] != '/') &&
256 (is_directory) )
257 {
258 GNUNET_asprintf (&avalue,
259 "%s/",
260 value);
261 /* if user typed '\' instead of '/', change it! */
262 slen = strlen (avalue);
263 while ( (slen > 1) &&
264 (avalue[slen-2] == '\\') )
265 {
266 avalue[slen-2] = '/';
267 avalue[slen-1] = '\0';
268 slen--;
269 }
270 while (NULL != (pos = strstr (avalue, "\\")))
271 *pos = '/';
272 /* remove '../' everywhere */
273 while (NULL != (pos = strstr (avalue, "../")))
274 {
275 pos[0] = '_';
276 pos[1] = '_';
277 pos[2] = '_';
278 }
279 ivalue = avalue;
280 }
281 else
282 {
283 ivalue = value;
284 avalue = NULL;
285 }
286
287 gtk_list_store_insert_with_values (ls, &iter, G_MAXINT,
288 0, type,
289 1, (guint) EXTRACTOR_METAFORMAT_UTF8,
290 2, EXTRACTOR_metatype_to_string (type),
291 3, ivalue,
292 -1);
293 GNUNET_free_non_null (avalue);
294 gtk_entry_set_text (GTK_ENTRY (entry), "");
295}
296
297
298/**
299 * Add each of the keywords to the keyword list store.
300 *
301 * @param cls closure
302 * @param keyword the keyword
303 * @param is_mandatory is the keyword mandatory (in a search)
304 * @return GNUNET_OK to continue to iterate
305 */
306static int
307add_keyword (void *cls,
308 const char *keyword,
309 int is_mandatory)
310{
311 GtkListStore *ls;
312 GtkTreeIter iter;
313
314 ls = GTK_LIST_STORE (gtk_builder_get_object (builder,
315 "GNUNET_GTK_keyword_list_store"));
316 gtk_list_store_insert_with_values (ls, &iter,
317 G_MAXINT,
318 0, keyword,
319 -1);
320 return GNUNET_OK;
321}
322
323
324/**
325 * Add the given meta data to the model (or make it the preview
326 * image if it is an image).
327 *
328 * @param cls closure, NULL
329 * @param plugin_name name of the plugin that produced this value;
330 * special values can be used (i.e. '<zlib>' for zlib being
331 * used in the main libextractor library and yielding
332 * meta data).
333 * @param type libextractor-type describing the meta data
334 * @param format basic format information about data
335 * @param data_mime_type mime-type of data (not of the original file);
336 * can be NULL (if mime-type is not known)
337 * @param data actual meta-data found
338 * @param data_len number of bytes in data
339 * @return 0 to continue extracting
340 */
341static int
342add_meta_item (void *cls,
343 const char *plugin_name,
344 enum EXTRACTOR_MetaType type,
345 enum EXTRACTOR_MetaFormat format,
346 const char *data_mime_type,
347 const char *data,
348 size_t data_len)
349{
350 GtkListStore *ls;
351 GtkTreeIter iter;
352
353 switch (format)
354 {
355 case EXTRACTOR_METAFORMAT_UTF8:
356 case EXTRACTOR_METAFORMAT_C_STRING:
357 ls = GTK_LIST_STORE (gtk_builder_get_object (builder,
358 "GNUNET_GTK_meta_data_list_store"));
359 gtk_list_store_insert_with_values (ls, &iter,
360 G_MAXINT,
361 0, (guint) type,
362 1, (guint) format,
363 2, EXTRACTOR_metatype_to_string (type),
364 3, data,
365 -1);
366 break;
367 case EXTRACTOR_METAFORMAT_UNKNOWN:
368 break;
369 case EXTRACTOR_METAFORMAT_BINARY:
370 break;
371 default:
372 GNUNET_break (0);
373 }
374 return 0;
375}
376
377
378/**
379 * Function called to extract the information from FI.
380 *
381 * @param cls closure
382 * @param fi the entry in the publish-structure
383 * @param length length of the file or directory
384 * @param meta metadata for the file or directory (can be modified)
385 * @param uri pointer to the keywords that will be used for this entry (can be modified)
386 * @param bo block options
387 * @param do_index should we index (can be modified)
388 * @param client_info pointer to client context set upon creation (can be modified)
389 * @return GNUNET_SYSERR (aborts after first call)
390 */
391static int
392file_information_extract (void *cls,
393 struct GNUNET_FS_FileInformation *fi,
394 uint64_t length,
395 struct GNUNET_CONTAINER_MetaData *meta,
396 struct GNUNET_FS_Uri **uri,
397 struct GNUNET_FS_BlockOptions *bo,
398 int *do_index,
399 void **client_info)
400{
401 GtkImage *img;
402 GdkPixbuf *pixbuf;
403 struct tm *t;
404 int year;
405 time_t tp;
406
407 if (NULL != *uri)
408 GNUNET_FS_uri_ksk_get_keywords (*uri, &add_keyword, NULL);
409 if (NULL != meta)
410 {
411 GNUNET_CONTAINER_meta_data_iterate (meta,
412 &add_meta_item,
413 NULL);
414 pixbuf = GNUNET_GTK_get_thumbnail_from_meta_data (meta);
415 if (pixbuf != NULL)
416 {
417 img = GTK_IMAGE (gtk_builder_get_object (builder,
418 "GNUNET_GTK_edit_file_information_metadata_preview_image"));
419 gtk_image_set_from_pixbuf (img,
420 pixbuf);
421 }
422 }
423 tp = bo->expiration_time.abs_value / 1000; /* ms to seconds */
424 t = gmtime (&tp);
425 if (t == NULL)
426 year = 0;
427 else
428 year = t->tm_year + 1900;
429 gtk_spin_button_set_value (GTK_SPIN_BUTTON (gtk_builder_get_object (builder,
430 "GNUNET_GTK_edit_file_information_expiration_year_spin_button")),
431 year);
432 gtk_spin_button_set_value (GTK_SPIN_BUTTON (gtk_builder_get_object (builder,
433 "GNUNET_GTK_edit_file_information_anonymity_spin_button")),
434 bo->anonymity_level);
435 gtk_spin_button_set_value (GTK_SPIN_BUTTON (gtk_builder_get_object (builder,
436 "GNUNET_GTK_edit_file_information_priority_spin_button")),
437 bo->content_priority);
438 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (gtk_builder_get_object (builder,
439 "GNUNET_GTK_edit_file_information_index_check_button")),
440 *do_index);
441 return GNUNET_SYSERR; /* only visit top-level item */
442}
443
444
445/**
446 * Copy binary meta data from to the new container and also
447 * preserve all entries that were not changed.
448 *
449 * @param cls closure, new meta data container
450 * @param plugin_name name of the plugin that produced this value;
451 * special values can be used (i.e. '<zlib>' for zlib being
452 * used in the main libextractor library and yielding
453 * meta data).
454 * @param type libextractor-type describing the meta data
455 * @param format basic format information about data
456 * @param data_mime_type mime-type of data (not of the original file);
457 * can be NULL (if mime-type is not known)
458 * @param data actual meta-data found
459 * @param data_len number of bytes in data
460 * @return 0 to continue extracting
461 */
462static int
463preserve_meta_items (void *cls,
464 const char *plugin_name,
465 enum EXTRACTOR_MetaType type,
466 enum EXTRACTOR_MetaFormat format,
467 const char *data_mime_type,
468 const char *data,
469 size_t data_len)
470{
471 struct GNUNET_CONTAINER_MetaData *md = cls;
472 GtkTreeModel *tm;
473 GtkTreeIter iter;
474 gchar *value;
475 guint ntype;
476 guint nformat;
477 int keep;
478
479 keep = GNUNET_NO;
480 switch (format)
481 {
482 case EXTRACTOR_METAFORMAT_UTF8:
483 case EXTRACTOR_METAFORMAT_C_STRING:
484 tm = GTK_TREE_MODEL (gtk_builder_get_object (builder,
485 "GNUNET_GTK_meta_data_list_store"));
486 if (TRUE ==
487 gtk_tree_model_get_iter_first (tm, &iter))
488 {
489 do
490 {
491 gtk_tree_model_get (tm, &iter,
492 0, &ntype,
493 1, &nformat,
494 3, &value,
495 -1);
496 if ( (ntype == type) &&
497 (nformat == format) &&
498 (0 == strcmp (value, data)) )
499 {
500 gtk_list_store_remove (GTK_LIST_STORE (tm), &iter);
501 keep = GNUNET_YES;
502 g_free (value);
503 break;
504 }
505 g_free (value);
506 }
507 while (TRUE == gtk_tree_model_iter_next (tm, &iter));
508 }
509 break;
510 case EXTRACTOR_METAFORMAT_UNKNOWN:
511 break;
512 case EXTRACTOR_METAFORMAT_BINARY:
513 if (preview_changed == GNUNET_NO)
514 keep = GNUNET_YES;
515 break;
516 default:
517 GNUNET_break (0);
518 break;
519 }
520 if (GNUNET_YES == keep)
521 GNUNET_break (GNUNET_OK ==
522 GNUNET_CONTAINER_meta_data_insert (md,
523 plugin_name, type, format,
524 data_mime_type, data, data_len));
525 return 0;
526}
527
528
529/**
530 * Function called to update the information in FI.
531 *
532 * @param cls closure (short_fn to update)
533 * @param fi the entry in the publish-structure
534 * @param length length of the file or directory
535 * @param meta metadata for the file or directory (can be modified)
536 * @param uri pointer to the keywords that will be used for this entry (can be modified)
537 * @param bo block options (can be modified)
538 * @param do_index should we index (can be modified)
539 * @param client_info pointer to client context set upon creation (can be modified)
540 * @return GNUNET_SYSERR (aborts after first call)
541 */
542static int
543file_information_update (void *cls,
544 struct GNUNET_FS_FileInformation *fi,
545 uint64_t length,
546 struct GNUNET_CONTAINER_MetaData *meta,
547 struct GNUNET_FS_Uri **uri,
548 struct GNUNET_FS_BlockOptions *bo,
549 int *do_index,
550 void **client_info)
551{
552 char **short_fn = cls;
553 struct GNUNET_CONTAINER_MetaData *nm;
554 GtkTreeModel *tm;
555 GtkTreeIter iter;
556 struct GNUNET_FS_Uri *nxt;
557 struct GNUNET_FS_Uri *mrg;
558 gchar *value;
559 guint ntype;
560 guint nformat;
561 GtkSpinButton *sb;
562 gchar *fn;
563 char *data;
564 gsize data_size;
565 const char *mime;
566 GFile *f;
567 GFileInfo *finfo;
568
569 bo->anonymity_level = gtk_spin_button_get_value (GTK_SPIN_BUTTON (gtk_builder_get_object (builder,
570 "GNUNET_GTK_edit_file_information_anonymity_spin_button")));
571 bo->content_priority = gtk_spin_button_get_value (GTK_SPIN_BUTTON (gtk_builder_get_object (builder,
572 "GNUNET_GTK_edit_file_information_priority_spin_button")));
573 *do_index = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (gtk_builder_get_object (builder,
574 "GNUNET_GTK_edit_file_information_index_check_button")));
575 sb =GTK_SPIN_BUTTON (gtk_builder_get_object (builder,
576 "GNUNET_GTK_edit_file_information_expiration_year_spin_button"));
577 bo->expiration_time = GNUNET_GTK_get_expiration_time (sb);
578 /* update URI */
579 if (NULL != (*uri))
580 GNUNET_FS_uri_destroy (*uri);
581 *uri = NULL;
582 nxt = NULL;
583 mrg = NULL;
584
585 tm = GTK_TREE_MODEL (gtk_builder_get_object (builder,
586 "GNUNET_GTK_keyword_list_store"));
587 if (TRUE ==
588 gtk_tree_model_get_iter_first (tm, &iter))
589 {
590 do
591 {
592 gtk_tree_model_get (tm, &iter,
593 0, &value,
594 -1);
595 nxt = GNUNET_FS_uri_ksk_create_from_args (1, (const char**) &value);
596 mrg = GNUNET_FS_uri_ksk_merge (nxt, *uri);
597 GNUNET_FS_uri_destroy (nxt);
598 if (NULL != *uri)
599 GNUNET_FS_uri_destroy (*uri);
600 *uri = mrg;
601 g_free (value);
602 }
603 while (TRUE == gtk_tree_model_iter_next (tm, &iter));
604 }
605
606 /* update meta */
607 nm = GNUNET_CONTAINER_meta_data_create ();
608 GNUNET_CONTAINER_meta_data_iterate (meta,
609 &preserve_meta_items,
610 nm);
611
612 GNUNET_CONTAINER_meta_data_clear (meta);
613 tm = GTK_TREE_MODEL (gtk_builder_get_object (builder,
614 "GNUNET_GTK_meta_data_list_store"));
615 if (TRUE ==
616 gtk_tree_model_get_iter_first (tm, &iter))
617 {
618 do
619 {
620 gtk_tree_model_get (tm, &iter,
621 0, &ntype,
622 1, &nformat,
623 3, &value,
624 -1);
625 GNUNET_CONTAINER_meta_data_insert (nm,
626 "<user>",
627 ntype,
628 nformat,
629 "text/plain",
630 value,
631 strlen (value)+1);
632 g_free (value);
633 }
634 while (TRUE == gtk_tree_model_iter_next (tm, &iter));
635 }
636 GNUNET_CONTAINER_meta_data_merge (meta, nm);
637 if (preview_changed == GNUNET_YES)
638 {
639 fn = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (gtk_builder_get_object (builder,
640 "GNUNET_GTK_edit_file_information_metadata_preview_file_chooser_button")));
641 f = g_file_new_for_path (fn);
642 finfo = g_file_query_info (f, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE, 0, NULL, NULL);
643 if (FALSE == g_file_load_contents (f, NULL, &data, &data_size, NULL, NULL))
644 {
645 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
646 _("Could not load preview `%s' into memory\n"),
647 fn);
648 }
649 else
650 {
651 mime = g_file_info_get_attribute_string (finfo,
652 G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE);
653 GNUNET_CONTAINER_meta_data_insert (meta,
654 "<user>",
655 EXTRACTOR_METATYPE_THUMBNAIL,
656 EXTRACTOR_METAFORMAT_BINARY,
657 mime,
658 data,
659 data_size);
660 }
661 g_object_unref (finfo);
662 g_object_unref (f);
663 }
664 GNUNET_CONTAINER_meta_data_destroy (nm);
665
666 /* update short_fn */
667 GNUNET_free_non_null (*short_fn);
668 *short_fn = GNUNET_CONTAINER_meta_data_get_first_by_types (meta,
669 EXTRACTOR_METATYPE_FILENAME,
670 -1);
671 /* FIXME: update expiration time? (not yet in dialog!) */
672 return GNUNET_SYSERR; /* only visit top-level item */
673}
674
675
676/**
677 * Open the dialog to edit file information data.
678 */
679void
680GNUNET_GTK_edit_publish_dialog (int *do_index,
681 char **short_fn,
682 guint *anonymity_level,
683 guint *priority,
684 struct GNUNET_FS_FileInformation *fip)
685{
686 GtkWidget *ad;
687 GtkListStore *ls;
688 GtkTreeIter iter;
689 guint type;
690 guint max_type;
691 GtkTreeView *tv;
692 GtkTreeSelection *sel;
693
694 GNUNET_assert (builder == NULL);
695 builder = GNUNET_GTK_get_new_builder ("publish_edit_dialog.glade");
696 if (builder == NULL)
697 {
698 GNUNET_break (0);
699 return;
700 }
701 preview_changed = GNUNET_NO;
702 GNUNET_GTK_setup_expiration_year_adjustment (builder);
703 if (GNUNET_FS_file_information_is_directory (fip))
704 {
705 /* indexing does not apply to directories */
706 gtk_widget_hide (GTK_WIDGET (gtk_builder_get_object (builder,
707 "GNUNET_GTK_edit_file_information_index_check_button")));
708 gtk_widget_hide (GTK_WIDGET (gtk_builder_get_object (builder,
709 "GNUNET_GTK_edit_file_information_index_label")));
710
711 }
712
713 ad = GTK_WIDGET (gtk_builder_get_object (builder,
714 "GNUNET_GTK_edit_file_information_dialog"));
715 ls = GTK_LIST_STORE (gtk_builder_get_object (builder,
716 "GNUNET_GTK_metatype_list_store"));
717 max_type = EXTRACTOR_metatype_get_max ();
718 type = 1;
719 while (type < max_type - 1)
720 {
721 gtk_list_store_insert_with_values (ls, &iter, G_MAXINT,
722 0, EXTRACTOR_metatype_to_string (type),
723 1, type,
724 2, EXTRACTOR_metatype_to_description (type),
725 -1);
726 type++;
727 }
728
729 GNUNET_FS_file_information_inspect (fip,
730 &file_information_extract,
731 NULL);
732 tv = GTK_TREE_VIEW (gtk_builder_get_object (builder,
733 "GNUNET_GTK_edit_file_information_metadata_type_tree_view"));
734 sel = gtk_tree_view_get_selection (tv);
735 g_signal_connect(G_OBJECT(sel), "changed",
736 G_CALLBACK(GNUNET_GTK_edit_file_information_metadata_value_entry_changed_cb), NULL);
737
738 tv = GTK_TREE_VIEW (gtk_builder_get_object (builder,
739 "GNUNET_GTK_edit_file_information_metadata_tree_view"));
740 sel = gtk_tree_view_get_selection (tv);
741 g_signal_connect(G_OBJECT(sel), "changed",
742 G_CALLBACK(metadata_selection_changed_cb), NULL);
743
744 tv = GTK_TREE_VIEW (gtk_builder_get_object (builder,
745 "GNUNET_GTK_edit_file_information_keyword_list_tree_view"));
746 sel = gtk_tree_view_get_selection (tv);
747 g_signal_connect(G_OBJECT(sel), "changed",
748 G_CALLBACK(keyword_selection_changed_cb), NULL);
749 gtk_window_set_title (GTK_WINDOW (ad), *short_fn);
750 if (GTK_RESPONSE_OK != gtk_dialog_run (GTK_DIALOG (ad)))
751 {
752 gtk_widget_destroy (ad);
753 g_object_unref (G_OBJECT (builder));
754 builder = NULL;
755 return;
756 }
757 GNUNET_FS_file_information_inspect (fip,
758 &file_information_update,
759 short_fn);
760 *anonymity_level = gtk_spin_button_get_value (GTK_SPIN_BUTTON (gtk_builder_get_object (builder,
761 "GNUNET_GTK_edit_file_information_anonymity_spin_button")));
762 *priority = gtk_spin_button_get_value (GTK_SPIN_BUTTON (gtk_builder_get_object (builder,
763 "GNUNET_GTK_edit_file_information_priority_spin_button")));
764 *do_index = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (gtk_builder_get_object (builder,
765 "GNUNET_GTK_edit_file_information_index_check_button")));
766 gtk_widget_destroy (ad);
767 g_object_unref (G_OBJECT (builder));
768 builder = NULL;
769}
770
771/* end of edit_publish_dialog.c */
diff --git a/src/edit_publish_dialog.h b/src/edit_publish_dialog.h
deleted file mode 100644
index c13f6abe..00000000
--- a/src/edit_publish_dialog.h
+++ /dev/null
@@ -1,41 +0,0 @@
1/*
2 This file is part of GNUnet
3 (C) 2005, 2006, 2010 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/edit_publish_dialog.h
23 * @author Christian Grothoff
24 */
25#ifndef EDIT_PUBLISH_DIALOG_H
26#define EDIT_PUBLISH_DIALOG_H
27
28#include "common.h"
29#include <gnunet/gnunet_util_lib.h>
30#include <gnunet/gnunet_fs_service.h>
31
32
33void
34GNUNET_GTK_edit_publish_dialog (int *do_index,
35 char **short_fn,
36 guint *anonymity_level,
37 guint *priority,
38 struct GNUNET_FS_FileInformation *fip);
39
40#endif
41/* end of edit_publish_dialog.h */
diff --git a/src/fs_anonymity_spin_buttons.c b/src/fs_anonymity_spin_buttons.c
deleted file mode 100644
index fa4b4eeb..00000000
--- a/src/fs_anonymity_spin_buttons.c
+++ /dev/null
@@ -1,73 +0,0 @@
1/*
2 This file is part of GNUnet
3 (C) 2005, 2006, 2010 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/fs_anonymtiy_spin_buttons.c
23 * @author Christian Grothoff
24 *
25 * This file contains callbacks to turn spin buttons red when the
26 * value reaches zero.
27 */
28#include "common.h"
29
30
31/**
32 * Spin button is changed, update its colour.
33 */
34void
35GNUNET_GTK_anonymity_spin_button_value_changed_cb (GtkWidget *w,
36 gpointer data)
37{
38 GtkSpinButton *spin;
39 gint val;
40 GdkColor bcolor;
41 GdkColor fcolor;
42
43 spin = GTK_SPIN_BUTTON (w);
44 if (spin == NULL)
45 {
46 GNUNET_break (0);
47 return;
48 }
49 val = gtk_spin_button_get_value_as_int (spin);
50 if (val == 0)
51 {
52 if ((TRUE == gdk_color_parse ("red",
53 &bcolor)) &&
54 (TRUE == gdk_colormap_alloc_color (gdk_colormap_get_system (),
55 &bcolor, FALSE, TRUE)) &&
56 (TRUE == gdk_color_parse ("black",
57 &fcolor)) &&
58 (TRUE == gdk_colormap_alloc_color (gdk_colormap_get_system (),
59 &fcolor, FALSE, TRUE)))
60 {
61 gtk_widget_modify_base (w, GTK_STATE_NORMAL, &bcolor);
62 gtk_widget_modify_text (w, GTK_STATE_NORMAL, &fcolor);
63 }
64 }
65 else
66 {
67 gtk_widget_modify_base (w, GTK_STATE_NORMAL, NULL);
68 gtk_widget_modify_text (w, GTK_STATE_NORMAL, NULL);
69 }
70}
71
72
73/* end of fs_anonymtiy_spin_buttons.c */
diff --git a/src/fs_event_handler.c b/src/fs_event_handler.c
deleted file mode 100644
index b044c86d..00000000
--- a/src/fs_event_handler.c
+++ /dev/null
@@ -1,2027 +0,0 @@
1/*
2 This file is part of GNUnet.
3 (C) 2010 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/fs_event_handler.c
23 * @brief Main event handler for file-sharing
24 * @author Christian Grothoff
25 */
26#include "common.h"
27#include "download.h"
28#include "fs_event_handler.h"
29#include <string.h>
30
31static struct SearchTab *search_tab_head;
32
33static struct SearchTab *search_tab_tail;
34
35struct PublishTab
36{
37 /**
38 * This is a doubly-linked list.
39 */
40 struct PublishTab *next;
41
42 /**
43 * This is a doubly-linked list.
44 */
45 struct PublishTab *prev;
46
47 GtkWidget *frame;
48
49 GtkBuilder *builder;
50
51 /**
52 * Associated (top-level) FS publish operation.
53 */
54 struct GNUNET_FS_PublishContext *pc;
55
56 GtkTreeStore *ts;
57};
58
59
60struct PublishEntry
61{
62 /**
63 * Associated FS publish operation.
64 */
65 struct GNUNET_FS_PublishContext *pc;
66
67 /**
68 * Tab storing this entry.
69 */
70 struct PublishTab *tab;
71
72 /**
73 * Where in the tab is this entry?
74 */
75 GtkTreeRowReference *rr;
76
77 /**
78 * URI of the file (set after completion).
79 */
80 struct GNUNET_FS_Uri *uri;
81
82 int is_top;
83};
84
85
86struct SearchResult
87{
88 /**
89 * Where in the tab is this result?
90 */
91 GtkTreeRowReference *rr;
92
93 /**
94 * Tab storing this result.
95 */
96 struct SearchTab *tab;
97
98 /**
99 * Search result for top-level results and
100 * namespace-update results.
101 */
102 struct GNUNET_FS_SearchResult *result;
103
104 /**
105 * Associated download, or NULL for none.
106 */
107 struct DownloadEntry *download;
108};
109
110
111
112static struct PublishTab *publish_tab_head;
113
114static struct PublishTab *publish_tab_tail;
115
116
117static struct DownloadEntry *
118change_download_colour (struct DownloadEntry *de,
119 const char *colour)
120{
121 GtkTreeIter iter;
122 GtkTreePath *path;
123
124 path = gtk_tree_row_reference_get_path (de->rr);
125 if (TRUE != gtk_tree_model_get_iter (GTK_TREE_MODEL (de->ts),
126 &iter, path))
127 {
128 GNUNET_break (0);
129 gtk_tree_path_free (path);
130 return de;
131 }
132 gtk_tree_path_free (path);
133 gtk_tree_store_set (de->ts, &iter,
134 8, colour,
135 -1);
136 return de;
137}
138
139
140static struct PublishEntry *
141change_publish_colour (struct PublishEntry *pe,
142 const char *colour)
143{
144 GtkTreeIter iter;
145 GtkTreePath *path;
146
147 if (pe == NULL)
148 {
149 GNUNET_break (0);
150 return NULL;
151 }
152 path = gtk_tree_row_reference_get_path (pe->rr);
153 if (TRUE != gtk_tree_model_get_iter (GTK_TREE_MODEL (pe->tab->ts),
154 &iter, path))
155 {
156 GNUNET_break (0);
157 gtk_tree_path_free (path);
158 return pe;
159 }
160 gtk_tree_path_free (path);
161 gtk_tree_store_set (pe->tab->ts, &iter,
162 2, colour,
163 -1);
164 return pe;
165}
166
167
168static void
169stop_download (struct DownloadEntry *de,
170 int is_suspend)
171{
172 change_download_colour (de, "white");
173 gtk_tree_row_reference_free (de->rr);
174 if (is_suspend == GNUNET_NO)
175 GNUNET_FS_download_stop (de->dc, GNUNET_YES);
176 GNUNET_FS_uri_destroy (de->uri);
177 GNUNET_CONTAINER_meta_data_destroy (de->meta);
178 GNUNET_free (de);
179}
180
181
182
183struct AddDirectoryEntryContext
184{
185
186 struct DownloadEntry *de;
187
188 /**
189 * Row reference of parent (the directory).
190 */
191 GtkTreeRowReference *prr;
192
193 int check_duplicates;
194
195};
196
197
198/**
199 * Function used to process entries in a directory.
200 *
201 * @param cls closure, our 'struct AddDirectoryEntryContext*'
202 * @param filename name of the file in the directory
203 * @param uri URI of the file
204 * @param metadata metadata for the file; metadata for
205 * the directory if everything else is NULL/zero
206 * @param length length of the available data for the file
207 * (of type size_t since data must certainly fit
208 * into memory; if files are larger than size_t
209 * permits, then they will certainly not be
210 * embedded with the directory itself).
211 * @param data data available for the file (length bytes)
212 */
213static void
214add_directory_entry (void *cls,
215 const char *filename,
216 const struct GNUNET_FS_Uri *uri,
217 const struct GNUNET_CONTAINER_MetaData *meta,
218 size_t length,
219 const void *data)
220{
221 struct AddDirectoryEntryContext *ade = cls;
222 GtkTreeIter iter;
223 GtkTreeIter piter;
224 GtkTreePath *path;
225 GtkTreeModel *tm;
226 struct GNUNET_FS_Uri *xuri;
227
228 if (uri == NULL)
229 {
230 /* directory meta data itself */
231 /* FIXME: consider merging it in... */
232 return;
233 }
234 if (ade->check_duplicates == GNUNET_YES)
235 {
236 path = gtk_tree_row_reference_get_path (ade->prr);
237 tm = gtk_tree_row_reference_get_model (ade->prr);
238 if (TRUE != gtk_tree_model_get_iter (tm,
239 &piter, path))
240 {
241 GNUNET_break (0);
242 gtk_tree_path_free (path);
243 return;
244 }
245 gtk_tree_path_free (path);
246 if (TRUE == gtk_tree_model_iter_children (tm,
247 &iter,
248 &piter))
249 {
250 do
251 {
252 gtk_tree_model_get (tm,
253 &iter,
254 1, &xuri,
255 -1);
256 if (GNUNET_YES ==
257 GNUNET_FS_uri_test_equal (xuri, uri))
258 return; /* already present */
259 }
260 while (TRUE == gtk_tree_model_iter_next (tm, &iter));
261 }
262 }
263 GNUNET_GTK_add_search_result (ade->de->tab,
264 &iter,
265 ade->prr,
266 uri,
267 meta,
268 NULL,
269 0);
270}
271
272
273static struct DownloadEntry *
274mark_download_progress (struct DownloadEntry *de,
275 uint64_t size,
276 uint64_t completed,
277 const void *block_data,
278 uint64_t offset,
279 uint64_t block_size,
280 unsigned int depth)
281{
282 struct AddDirectoryEntryContext ade;
283 GtkTreeIter iter;
284 GtkTreePath *path;
285
286 path = gtk_tree_row_reference_get_path (de->rr);
287 if (TRUE != gtk_tree_model_get_iter (GTK_TREE_MODEL (de->ts),
288 &iter, path))
289 {
290 GNUNET_break (0);
291 gtk_tree_path_free (path);
292 return de;
293 }
294 gtk_tree_path_free (path);
295 gtk_tree_store_set (de->ts, &iter,
296 4, (guint) ((size > 0) ? (100 * completed / size) : 100) /* progress */,
297 -1);
298 if ( (depth == 0) &&
299 (block_size > 0) &&
300 (GNUNET_YES == GNUNET_FS_meta_data_test_for_directory (de->meta)) )
301 {
302 ade.de = de;
303 ade.prr = de->rr;
304 ade.check_duplicates = GNUNET_NO;
305 if (GNUNET_SYSERR ==
306 GNUNET_FS_directory_list_contents ((size_t) block_size,
307 block_data,
308 offset,
309 &add_directory_entry,
310 &ade))
311 {
312 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
313 _("Metadata wrongly claims that this is a GNUnet directory!\n"));
314 }
315 }
316 return de;
317}
318
319
320static struct DownloadEntry *
321mark_download_error (struct DownloadEntry *de,
322 const char *emsg)
323{
324 GtkTreeIter iter;
325 GtkTreePath *path;
326
327 de = change_download_colour (de,
328 "red");
329 de->is_done = GNUNET_YES;
330 path = gtk_tree_row_reference_get_path (de->rr);
331 if (TRUE != gtk_tree_model_get_iter (GTK_TREE_MODEL (de->tab->ts),
332 &iter, path))
333 {
334 GNUNET_break (0);
335 gtk_tree_path_free (path);
336 return de;
337 }
338 gtk_tree_path_free (path);
339 gtk_tree_store_set (de->tab->ts, &iter,
340 4, 0,
341 7, emsg,
342 -1);
343 return de;
344}
345
346
347static struct DownloadEntry *
348mark_download_completed (struct DownloadEntry *de,
349 uint64_t size,
350 const char *filename)
351{
352 struct AddDirectoryEntryContext ade;
353
354 de->is_done = GNUNET_YES;
355 (void) mark_download_progress (de, size, size, NULL, 0, 0, 0);
356 if ( (GNUNET_YES == GNUNET_FS_meta_data_test_for_directory (de->meta)) &&
357 (filename != NULL) )
358 {
359 ade.de = de;
360 ade.prr = de->rr;
361 ade.check_duplicates = GNUNET_NO;
362 GNUNET_GTK_mmap_and_scan (filename,
363 &add_directory_entry,
364 &ade);
365 }
366 (void) change_download_colour (de, "green");
367 return de;
368}
369
370
371static struct PublishEntry *
372mark_publish_progress (struct PublishEntry *pe,
373 uint64_t size,
374 uint64_t completed)
375{
376 GtkTreeIter iter;
377 GtkTreePath *path;
378
379 path = gtk_tree_row_reference_get_path (pe->rr);
380 if (TRUE != gtk_tree_model_get_iter (GTK_TREE_MODEL (pe->tab->ts),
381 &iter, path))
382 {
383 GNUNET_break (0);
384 gtk_tree_path_free (path);
385 return pe;
386 }
387 gtk_tree_path_free (path);
388 gtk_tree_store_set (pe->tab->ts, &iter,
389 3, (guint) ((size > 0) ? (100 * completed / size) : 100) /* progress */,
390 -1);
391 return pe;
392}
393
394
395/**
396 * Move (aka copy) all of the children of 'src_iter' from the 'src_model'
397 * to become children of 'dst_iter' in the 'dst_model'.
398 *
399 * The models are both 'GNUNET_GTK_file_sharing_result_tree_store' models.
400 *
401 * Note that we also need to update the 'struct SearchResult'
402 * and (if it exists) the respective 'struct DownloadEntry'
403 * to refer to the new model.
404 */
405static void
406move_children (GtkTreeModel *src_model,
407 GtkTreeIter *src_iter,
408 GtkTreeModel *dst_model,
409 GtkTreeIter *dst_iter)
410{
411 GtkTreeIter src_child;
412 GtkTreeIter dst_child;
413 GtkTreePath *path;
414 struct GNUNET_CONTAINER_MetaData *meta;
415 struct GNUNET_FS_Uri *uri;
416 guint64 filesize;
417 GdkPixbuf *preview;
418 guint percent_progress;
419 guint percent_availability;
420 gchar *filename;
421 gchar *uri_as_string;
422 gchar *status_colour;
423 struct SearchResult *search_result;
424 gchar *mimetype;
425 guint applicability_rank;
426 guint availability_certainty;
427 gint availability_rank;
428
429 if (TRUE == gtk_tree_model_iter_children (src_model,
430 &src_child,
431 src_iter))
432 {
433 do
434 {
435 gtk_tree_model_get (src_model,
436 &src_child,
437 0, &meta,
438 1, &uri,
439 2, &filesize,
440 3, &preview,
441 4, &percent_progress,
442 5, &percent_availability,
443 6, &filename,
444 7, &uri_as_string,
445 8, &status_colour,
446 9, &search_result,
447 10, &mimetype,
448 11, &applicability_rank,
449 12, &availability_certainty,
450 13, &availability_rank,
451 -1);
452 gtk_tree_store_insert_with_values (GTK_TREE_STORE (dst_model),
453 &dst_child,
454 dst_iter,
455 G_MAXINT,
456 0, meta,
457 1, uri,
458 2, filesize,
459 3, preview,
460 4, percent_progress,
461 5, percent_availability,
462 6, filename,
463 7, uri_as_string,
464 8, status_colour,
465 9, search_result,
466 10, mimetype,
467 11, applicability_rank,
468 12, availability_certainty,
469 13, availability_rank,
470 -1);
471 g_free (filename);
472 g_free (uri_as_string);
473 g_free (status_colour);
474 g_free (mimetype);
475 if (preview != NULL)
476 g_object_unref (preview);
477 gtk_tree_row_reference_free (search_result->rr);
478 path = gtk_tree_model_get_path (dst_model,
479 &dst_child);
480 search_result->rr = gtk_tree_row_reference_new (dst_model,
481 path);
482 gtk_tree_path_free (path);
483 if (search_result->download != NULL)
484 {
485 search_result->download->ts = GTK_TREE_STORE (dst_model);
486 gtk_tree_row_reference_free (search_result->download->rr);
487 search_result->download->rr = gtk_tree_row_reference_copy (search_result->rr);
488 }
489 move_children (src_model,
490 &src_child,
491 dst_model,
492 &dst_child);
493 }
494 while (TRUE == gtk_tree_model_iter_next (src_model,
495 &src_child));
496 }
497}
498
499
500/**
501 * Delete the entire given subtree from the model.
502 * Does not free anything inside of the respective
503 * model's fields (since they have been moved).
504 */
505static void
506delete_stale_subtree (GtkTreeModel *model,
507 GtkTreeIter *iter)
508{
509 GtkTreeIter child;
510
511 while (TRUE == gtk_tree_model_iter_children (model,
512 &child,
513 iter))
514 delete_stale_subtree (model, &child);
515 gtk_tree_store_remove (GTK_TREE_STORE (model),
516 iter);
517}
518
519
520/**
521 * Handle the case where an active download lost its
522 * search parent by moving it to the URI tab.
523 */
524static struct DownloadEntry *
525download_lost_parent (struct DownloadEntry *de,
526 uint64_t size,
527 uint64_t completed,
528 int is_active)
529{
530 GtkTreeIter iter;
531 GtkTreePath *path;
532 struct SearchTab *tab;
533 GtkTreeRowReference *rr_old;
534 GtkTreeModel *tm_old;
535 GtkTreeIter iter_old;
536
537 rr_old = de->rr;
538 de->sr = NULL;
539 tab = GNUNET_GTK_add_to_uri_tab (&iter,
540 NULL,
541 de->meta,
542 de->uri);
543 de->ts = tab->ts;
544 path = gtk_tree_model_get_path (GTK_TREE_MODEL (de->ts),
545 &iter);
546 de->rr = gtk_tree_row_reference_new (GTK_TREE_MODEL (de->ts),
547 path);
548 gtk_tree_path_free (path);
549 mark_download_progress (de, size, completed,
550 NULL, 0, 0, 0);
551 tm_old = gtk_tree_row_reference_get_model (rr_old);
552 path = gtk_tree_row_reference_get_path (rr_old);
553 gtk_tree_row_reference_free (rr_old);
554 gtk_tree_model_get_iter (tm_old,
555 &iter_old,
556 path);
557 gtk_tree_path_free (path);
558 move_children (tm_old,
559 &iter_old,
560 GTK_TREE_MODEL (de->ts),
561 &iter);
562 delete_stale_subtree (tm_old,
563 &iter_old);
564 if (size > completed)
565 {
566 if (is_active)
567 change_download_colour (de, "yellow");
568 else
569 change_download_colour (de, "blue");
570 }
571 else
572 {
573 change_download_colour (de, "green");
574 }
575 return de;
576}
577
578
579/**
580 * Setup a new download entry.
581 *
582 * @param de existing download entry for the download, or NULL
583 * @param pde parent download entry, or NULL
584 * @param sr search result, or NULL
585 * @param dc download context (for stopping)
586 * @param uri the URI
587 * @param meta metadata
588 * @param size total size
589 * @param completed current progress
590 */
591static struct DownloadEntry *
592setup_download (struct DownloadEntry *de,
593 struct DownloadEntry *pde,
594 struct SearchResult *sr,
595 struct GNUNET_FS_DownloadContext *dc,
596 const struct GNUNET_FS_Uri *uri,
597 const struct GNUNET_CONTAINER_MetaData *meta,
598 uint64_t size,
599 uint64_t completed)
600{
601 GtkTreeIter iter;
602 GtkTreePath *path;
603
604 if (de == NULL)
605 {
606 de = GNUNET_malloc (sizeof (struct DownloadEntry));
607 GNUNET_assert (sr->download == NULL);
608 sr->download = de;
609 de->sr = sr;
610 de->dc = dc;
611 de->uri = GNUNET_FS_uri_dup (uri);
612 }
613 de->pde = pde;
614 if ( (meta != NULL) &&
615 (de->meta == NULL) )
616 de->meta = GNUNET_CONTAINER_meta_data_duplicate (meta);
617 if (sr != NULL)
618 {
619 de->rr = gtk_tree_row_reference_copy (sr->rr);
620 de->ts = sr->tab->ts;
621 de->tab = sr->tab;
622 }
623 else if (de->rr == NULL)
624 {
625 de->tab = GNUNET_GTK_add_to_uri_tab (&iter,
626 NULL,
627 meta,
628 uri);
629 de->ts = de->tab->ts;
630 path = gtk_tree_model_get_path (GTK_TREE_MODEL (de->ts),
631 &iter);
632 de->rr = gtk_tree_row_reference_new (GTK_TREE_MODEL (de->ts),
633 path);
634 gtk_tree_path_free (path);
635 }
636 path = gtk_tree_row_reference_get_path (de->rr);
637 if (TRUE != gtk_tree_model_get_iter (GTK_TREE_MODEL (de->ts),
638 &iter, path))
639 {
640 GNUNET_break (0);
641 gtk_tree_path_free (path);
642 return de;
643 }
644 gtk_tree_path_free (path);
645 gtk_tree_store_set (de->ts, &iter,
646 4, (guint) ((size > 0) ? (100 * completed / size) : 100) /* progress */,
647 8, "blue" /* status colour: pending */,
648 -1);
649 return de;
650}
651
652
653/**
654 * Tell FS to start a download. Begins by opening the
655 * "save as" window.
656 */
657static void
658start_download (GtkTreeView *tree_view,
659 GtkTreePath *path,
660 GtkTreeViewColumn *column,
661 gpointer user_data)
662{
663 struct SearchTab *tab = user_data;
664 GtkTreeModel *tm;
665 GtkTreeIter iter;
666 struct GNUNET_FS_Uri *uri;
667 struct GNUNET_CONTAINER_MetaData *meta;
668 struct SearchResult *sr;
669 gchar *mime;
670 struct DownloadContext *dlc;
671
672 GNUNET_assert (tab != NULL);
673 tm = gtk_tree_view_get_model (tree_view);
674 if (TRUE != gtk_tree_model_get_iter (tm, &iter, path))
675 {
676 GNUNET_break (0);
677 return;
678 }
679 gtk_tree_model_get (tm, &iter,
680 0, &meta,
681 1, &uri,
682 9, &sr,
683 10, &mime,
684 -1);
685 dlc = GNUNET_malloc (sizeof (struct DownloadContext));
686 dlc->uri = GNUNET_FS_uri_dup (uri);
687 dlc->mime = (NULL != mime) ? GNUNET_strdup (mime) : NULL;
688 dlc->filename = GNUNET_FS_meta_data_suggest_filename (meta);
689 dlc->meta = GNUNET_CONTAINER_meta_data_duplicate (meta);
690 dlc->rr = gtk_tree_row_reference_new (tm, path);
691 dlc->sr = sr->result;
692 dlc->anonymity = -1;
693 GNUNET_GTK_open_download_as_dialog (dlc);
694 g_free (mime);
695}
696
697
698
699/**
700 * Row reference for the current search context menu.
701 */
702static GtkTreeRowReference *current_context_row_reference;
703
704/**
705 * Search tab used for the current search context menu.
706 */
707static struct SearchTab *current_context_search_tab;
708
709/**
710 * Download was selected in the current search context menu.
711 */
712static void
713start_download_ctx_menu (gpointer user_data,
714 guint unused,
715 GtkWidget *widget)
716{
717 GtkTreePath *path;
718 GtkTreeView *tv;
719
720 if (current_context_row_reference == NULL)
721 {
722 GNUNET_break (0);
723 return;
724 }
725 path = gtk_tree_row_reference_get_path (current_context_row_reference);
726 gtk_tree_row_reference_free (current_context_row_reference);
727 current_context_row_reference = NULL;
728 tv = GTK_TREE_VIEW (gtk_builder_get_object (current_context_search_tab->builder,
729 "_search_result_frame"));
730 start_download (tv, path, NULL, current_context_search_tab);
731 gtk_tree_path_free (path);
732 current_context_search_tab = NULL;
733}
734
735
736/**
737 * Download was selected in the current search context menu.
738 */
739static void
740abort_download_ctx_menu (gpointer user_data,
741 guint unused,
742 GtkWidget *widget)
743{
744 struct DownloadEntry *de = user_data;
745
746 GNUNET_assert (de->dc != NULL);
747 GNUNET_FS_download_stop (de->dc,
748 GNUNET_YES);
749 current_context_search_tab = NULL;
750}
751
752
753/**
754 * Copy current URI to clipboard.
755 */
756static void
757copy_uri_to_clipboard_ctx_menu (gpointer user_data,
758 guint unused,
759 GtkWidget *widget)
760{
761 GtkTreePath *path;
762 GtkTreeView *tv;
763 GtkTreeModel *tm;
764 GtkTreeIter iter;
765 struct GNUNET_FS_Uri *uri;
766 char *uris;
767 GtkClipboard *cb;
768
769 if (current_context_row_reference == NULL)
770 {
771 GNUNET_break (0);
772 return;
773 }
774 path = gtk_tree_row_reference_get_path (current_context_row_reference);
775 gtk_tree_row_reference_free (current_context_row_reference);
776 current_context_row_reference = NULL;
777 tv = GTK_TREE_VIEW (gtk_builder_get_object (current_context_search_tab->builder,
778 "_search_result_frame"));
779 tm = gtk_tree_view_get_model (tv);
780 if (TRUE != gtk_tree_model_get_iter (tm, &iter, path))
781 {
782 GNUNET_break (0);
783 gtk_tree_path_free (path);
784 return;
785 }
786 gtk_tree_model_get (tm, &iter,
787 1, &uri, -1);
788 gtk_tree_path_free (path);
789 current_context_search_tab = NULL;
790 if (uri == NULL)
791 {
792 GNUNET_break (0);
793 return;
794 }
795 uris = GNUNET_FS_uri_to_string (uri);
796 cb = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
797 gtk_clipboard_set_text (cb,
798 uris,
799 -1);
800 gtk_clipboard_store (cb);
801 GNUNET_free (uris);
802}
803
804
805/**
806 * We got a right-click on the search result list. Display the context
807 * menu.
808 */
809static int
810search_list_on_menu(GtkWidget *widget,
811 GdkEvent *event,
812 gpointer user_data)
813{
814 GdkEventButton *event_button;
815 struct SearchTab *tab = user_data;
816 GtkTreeView *tv;
817 GtkMenu *menu;
818 GtkWidget *child;
819 GtkTreePath *path;
820 GtkTreeModel *tm;
821 GtkTreeIter iter;
822 struct SearchResult *sr;
823
824 tv = GTK_TREE_VIEW (widget);
825 if (event->type == GDK_BUTTON_PRESS)
826 {
827 event_button = (GdkEventButton *) event;
828 if (event_button->button == 3)
829 {
830 current_context_search_tab = tab;
831 if (current_context_row_reference != NULL)
832 {
833 gtk_tree_row_reference_free (current_context_row_reference);
834 current_context_row_reference = NULL;
835 }
836 path = NULL;
837 if (FALSE == gtk_tree_view_get_path_at_pos (tv,
838 event_button->x,
839 event_button->y,
840 &path, NULL, NULL, NULL))
841 {
842 /* nothing selected */
843 current_context_search_tab = NULL;
844 return FALSE;
845 }
846 tm = gtk_tree_view_get_model (tv);
847 gtk_tree_model_get_iter (tm, &iter, path);
848 gtk_tree_model_get (tm, &iter,
849 9, &sr,
850 -1);
851 current_context_row_reference = gtk_tree_row_reference_new (tm,
852 path);
853 gtk_tree_path_free (path);
854
855 /*
856 FIXME: have additional options, depending on status:
857 - view full meta data (in new window)
858 - copy URI to clipboard
859 - start recursive download
860 - abort active download (!)
861 => need to know download status before creating menu!
862 */
863 menu = GTK_MENU (gtk_menu_new ());
864 if (sr->download == NULL)
865 {
866 child = gtk_menu_item_new_with_label (_("_Download"));
867 g_signal_connect (child,
868 "activate",
869 G_CALLBACK (start_download_ctx_menu),
870 NULL);
871 gtk_label_set_use_underline (GTK_LABEL
872 (gtk_bin_get_child (GTK_BIN (child))),
873 TRUE);
874 gtk_widget_show (child);
875 }
876 else
877 {
878 child = gtk_menu_item_new_with_label (_("_Abort download"));
879 g_signal_connect (child,
880 "activate",
881 G_CALLBACK (abort_download_ctx_menu),
882 sr->download);
883 gtk_label_set_use_underline (GTK_LABEL
884 (gtk_bin_get_child (GTK_BIN (child))),
885 TRUE);
886 gtk_widget_show (child);
887
888 }
889
890 child = gtk_menu_item_new_with_label (_("_Copy URI to Clipboard"));
891 g_signal_connect (child,
892 "activate",
893 G_CALLBACK (copy_uri_to_clipboard_ctx_menu),
894 NULL);
895 gtk_label_set_use_underline (GTK_LABEL
896 (gtk_bin_get_child (GTK_BIN (child))),
897 TRUE);
898 gtk_widget_show (child);
899
900
901
902 gtk_menu_shell_append (GTK_MENU_SHELL (menu), child);
903 gtk_menu_popup (menu, NULL, NULL, NULL, NULL,
904 event_button->button,
905 event_button->time);
906 }
907 }
908 return FALSE;
909}
910
911
912/**
913 * Selected row has changed, update preview and metadata
914 * areas.
915 */
916static void
917update_meta_data_views (GtkTreeView *tv,
918 gpointer user_data)
919{
920 struct SearchTab *tab = user_data;
921 GtkImage *image;
922 GtkListStore *ms;
923 GtkTreeSelection *sel;
924 GtkTreeModel *model;
925 GtkTreeIter iter;
926 struct GNUNET_CONTAINER_MetaData *meta;
927 GdkPixbuf *pixbuf;
928
929 GNUNET_assert (tab->query_txt != NULL);
930 image = GTK_IMAGE (GNUNET_GTK_get_main_window_object ("GNUNET_GTK_main_window_preview_image"));
931 ms = GTK_LIST_STORE (GNUNET_GTK_get_main_window_object ("GNUNET_GTK_meta_data_list_store"));
932
933 sel = gtk_tree_view_get_selection (tv);
934 gtk_list_store_clear (ms);
935 if (TRUE != gtk_tree_selection_get_selected (sel,
936 &model,
937 &iter))
938 {
939 gtk_image_clear (image);
940 return;
941 }
942 meta = NULL;
943 pixbuf = NULL;
944 gtk_tree_model_get (model,
945 &iter,
946 0, &meta,
947 3, &pixbuf,
948 -1);
949 if (pixbuf != NULL)
950 {
951 gtk_image_set_from_pixbuf (image, pixbuf);
952 g_object_unref (G_OBJECT (pixbuf));
953 }
954 if (meta != NULL)
955 {
956 GNUNET_CONTAINER_meta_data_iterate (meta,
957 &GNUNET_GTK_add_meta_data_to_list_store,
958 ms);
959 }
960}
961
962
963/**
964 * Update the label for a search
965 */
966static void
967update_search_label (struct SearchTab *tab)
968{
969 char *name;
970
971 while (tab->parent != NULL)
972 tab = tab->parent->tab;
973 if (tab->num_results > 0)
974 GNUNET_asprintf (&name,
975 "%.*s%s (%u)",
976 20,
977 tab->query_txt,
978 strlen (tab->query_txt) > 20 ? "..." : "",
979 tab->num_results);
980 else
981 GNUNET_asprintf (&name,
982 "%.*s%s",
983 20,
984 tab->query_txt,
985 strlen (tab->query_txt) > 20 ? "..." : "");
986 gtk_label_set_text (tab->label, name);
987 GNUNET_free (name);
988}
989
990
991/**
992 * Close a search tab and free associated state.
993 */
994static void
995close_search_tab (struct SearchTab *tab)
996{
997 GtkNotebook *notebook;
998 int index;
999 int i;
1000
1001 if (tab->parent != NULL)
1002 {
1003 /* not a top-level search, do not close tab here! */
1004 GNUNET_free (tab);
1005 return;
1006 }
1007
1008 notebook = GTK_NOTEBOOK (GNUNET_GTK_get_main_window_object ("GNUNET_GTK_main_window_notebook"));
1009 index = -1;
1010 for (i = gtk_notebook_get_n_pages (notebook) - 1; i >= 0; i--)
1011 if (tab->frame == gtk_notebook_get_nth_page (notebook, i))
1012 index = i;
1013 gtk_notebook_remove_page (notebook, index);
1014 g_object_unref (tab->builder);
1015 GNUNET_free (tab->query_txt);
1016 GNUNET_CONTAINER_DLL_remove (search_tab_head,
1017 search_tab_tail,
1018 tab);
1019 GNUNET_free (tab);
1020}
1021
1022
1023/**
1024 * Close a publish tab and free associated state.
1025 */
1026static struct PublishEntry *
1027handle_publish_completed (struct PublishEntry *ent,
1028 const struct GNUNET_FS_Uri *uri)
1029{
1030 ent->uri = GNUNET_FS_uri_dup (uri);
1031 return change_publish_colour (ent,
1032 "green");
1033}
1034
1035
1036
1037/**
1038 * Handle error.
1039 */
1040static struct PublishEntry *
1041handle_publish_error (struct PublishEntry *ent,
1042 const char *emsg)
1043{
1044 GNUNET_break (0);
1045 return change_publish_colour (ent,
1046 "red");
1047}
1048
1049
1050/**
1051 * Close a publish tab and free associated state.
1052 */
1053static void
1054close_publish_tab (struct PublishEntry *ent)
1055{
1056 struct PublishTab *tab;
1057 GtkNotebook *notebook;
1058 int index;
1059 int i;
1060
1061 if (ent == NULL)
1062 {
1063 GNUNET_break (0);
1064 return;
1065 }
1066 gtk_tree_row_reference_free (ent->rr);
1067 if (GNUNET_YES != ent->is_top)
1068 {
1069 GNUNET_free (ent);
1070 return;
1071 }
1072 tab = ent->tab;
1073 if (ent->uri != NULL)
1074 GNUNET_FS_uri_destroy (ent->uri);
1075 GNUNET_free (ent);
1076 notebook = GTK_NOTEBOOK (GNUNET_GTK_get_main_window_object ("GNUNET_GTK_main_window_notebook"));
1077 index = -1;
1078 for (i = gtk_notebook_get_n_pages (notebook) - 1; i >= 0; i--)
1079 if (tab->frame == gtk_notebook_get_nth_page (notebook, i))
1080 index = i;
1081 gtk_notebook_remove_page (notebook, index);
1082 g_object_unref (tab->builder);
1083 GNUNET_CONTAINER_DLL_remove (publish_tab_head,
1084 publish_tab_tail,
1085 tab);
1086 GNUNET_free (tab);
1087}
1088
1089
1090/**
1091 * Tell FS to stop a search.
1092 */
1093static void
1094stop_search (GtkButton *button,
1095 gpointer user_data)
1096{
1097 struct SearchTab *tab = user_data;
1098 if (tab->sc != NULL)
1099 {
1100 GNUNET_FS_search_stop (tab->sc);
1101 tab->sc = NULL;
1102 }
1103}
1104
1105
1106/**
1107 * Stop completed downloads (or those that failed). Should
1108 * iterate over the underlying tree store and stop all
1109 * completed entries. Furthermore, if the resulting tree
1110 * store is empty and has no search associated with it,
1111 * the tab should be closed.
1112 */
1113static void
1114clear_downloads (GtkButton *button,
1115 gpointer user_data)
1116{
1117 struct SearchTab *tab = user_data;
1118 struct SearchResult *sr;
1119 GtkTreeModel *tm;
1120 GtkTreeIter iter;
1121
1122 tm = GTK_TREE_MODEL (tab->ts);
1123 if (TRUE != gtk_tree_model_get_iter_first (tm, &iter))
1124 return;
1125 do
1126 {
1127 gtk_tree_model_get (tm, &iter,
1128 9, &sr,
1129 -1);
1130 if ( (sr->download != NULL) &&
1131 (sr->download->is_done == GNUNET_YES) )
1132 GNUNET_FS_download_stop (sr->download->dc,
1133 GNUNET_YES);
1134 }
1135 while (TRUE == gtk_tree_model_iter_next (tm, &iter));
1136}
1137
1138
1139
1140/**
1141 * Tell FS to pause a search.
1142 */
1143static void
1144pause_search (GtkButton *button,
1145 gpointer user_data)
1146{
1147 struct SearchTab *tab = user_data;
1148 if (tab->sc != NULL)
1149 {
1150 GNUNET_FS_search_pause (tab->sc);
1151 gtk_widget_show (tab->play_button);
1152 gtk_widget_hide (tab->pause_button);
1153 }
1154}
1155
1156
1157/**
1158 * Tell FS to resume a search.
1159 */
1160static void
1161continue_search (GtkButton *button,
1162 gpointer user_data)
1163{
1164 struct SearchTab *tab = user_data;
1165 if (tab->sc != NULL)
1166 {
1167 GNUNET_FS_search_continue (tab->sc);
1168 gtk_widget_show (tab->pause_button);
1169 gtk_widget_hide (tab->play_button);
1170 }
1171}
1172
1173
1174/**
1175 * Setup a new search tab.
1176 *
1177 * @param sc context with FS for the search
1178 * @param query the query
1179 * @param anonymity anonymity level
1180 */
1181static struct SearchTab *
1182setup_search (struct GNUNET_FS_SearchContext *sc,
1183 const struct GNUNET_FS_Uri *query)
1184{
1185 struct SearchTab *tab;
1186 GtkTreeView *tv;
1187 GtkNotebook *notebook;
1188 GtkWindow *sf;
1189 gint pages;
1190
1191 tab = GNUNET_malloc (sizeof (struct SearchTab));
1192 GNUNET_CONTAINER_DLL_insert (search_tab_head,
1193 search_tab_tail,
1194 tab);
1195 tab->sc = sc;
1196 if (query == NULL)
1197 {
1198 tab->query_txt = GNUNET_strdup ("*");
1199 }
1200 else
1201 {
1202 if (GNUNET_FS_uri_test_ksk (query))
1203 tab->query_txt = GNUNET_FS_uri_ksk_to_string_fancy (query);
1204 else
1205 tab->query_txt = GNUNET_FS_uri_to_string (query);
1206 }
1207 tab->builder = GNUNET_GTK_get_new_builder ("search_tab.glade");
1208 tab->ts = GTK_TREE_STORE (gtk_builder_get_object (tab->builder,
1209 "GNUNET_GTK_file_sharing_result_tree_store"));
1210 /* load frame */
1211 sf = GTK_WINDOW (gtk_builder_get_object (tab->builder,
1212 "_search_result_frame_window"));
1213 tab->frame = gtk_bin_get_child (GTK_BIN (sf));
1214 gtk_widget_ref (tab->frame);
1215 gtk_container_remove (GTK_CONTAINER (sf), tab->frame);
1216 gtk_widget_destroy (GTK_WIDGET (sf));
1217
1218 /* load tab_label */
1219 sf = GTK_WINDOW (gtk_builder_get_object (tab->builder,
1220 "_search_result_label_window"));
1221 tab->tab_label = gtk_bin_get_child (GTK_BIN (sf));
1222 gtk_widget_ref (tab->tab_label);
1223 gtk_container_remove (GTK_CONTAINER (sf), tab->tab_label);
1224 gtk_widget_destroy (GTK_WIDGET (sf));
1225
1226 /* get refs to widgets */
1227 tab->label = GTK_LABEL (gtk_builder_get_object (tab->builder,
1228 "_search_result_label_window_label"));
1229
1230 tab->close_button = GTK_WIDGET (gtk_builder_get_object (tab->builder,
1231 "_search_result_label_close_button"));
1232 g_signal_connect(G_OBJECT(tab->close_button), "clicked",
1233 G_CALLBACK(stop_search), tab);
1234 tab->clear_button = GTK_WIDGET (gtk_builder_get_object (tab->builder,
1235 "_search_result_label_clear_button"));
1236 g_signal_connect(G_OBJECT(tab->clear_button), "clicked",
1237 G_CALLBACK(clear_downloads), tab);
1238 tab->play_button = GTK_WIDGET (gtk_builder_get_object (tab->builder,
1239 "_search_result_label_play_button"));
1240 g_signal_connect(G_OBJECT(tab->play_button), "clicked",
1241 G_CALLBACK(continue_search), tab);
1242 tab->pause_button = GTK_WIDGET (gtk_builder_get_object (tab->builder,
1243 "_search_result_label_pause_button"));
1244 g_signal_connect(G_OBJECT(tab->pause_button), "clicked",
1245 G_CALLBACK(pause_search), tab);
1246 /* patch text */
1247 update_search_label (tab);
1248
1249 /* add signal handlers */
1250 tv = GTK_TREE_VIEW (gtk_builder_get_object (tab->builder,
1251 "_search_result_frame"));
1252 g_signal_connect(G_OBJECT(tv), "row-activated",
1253 G_CALLBACK(start_download), tab);
1254 g_signal_connect(G_OBJECT(tv), "cursor-changed",
1255 G_CALLBACK(update_meta_data_views), tab);
1256 g_signal_connect (G_OBJECT(tv),
1257 "button_press_event",
1258 G_CALLBACK(search_list_on_menu),
1259 tab);
1260
1261
1262 /* make visible */
1263 notebook = GTK_NOTEBOOK (GNUNET_GTK_get_main_window_object ("GNUNET_GTK_main_window_notebook"));
1264 pages = gtk_notebook_get_n_pages (notebook);
1265 gtk_notebook_insert_page (notebook,
1266 tab->frame,
1267 tab->tab_label,
1268 pages - 1);
1269 gtk_notebook_set_current_page (notebook,
1270 pages - 1);
1271 gtk_widget_show (GTK_WIDGET (notebook));
1272 return tab;
1273}
1274
1275
1276/**
1277 * Setup an inner search.
1278 *
1279 * @param sc context with FS for the search
1280 * @param parent parent search tab
1281 * @param anonymity anonymity level
1282 */
1283static struct SearchTab *
1284setup_inner_search (struct GNUNET_FS_SearchContext *sc,
1285 struct SearchResult *parent)
1286{
1287 struct SearchTab *ret;
1288
1289 ret = GNUNET_malloc (sizeof (struct SearchTab));
1290 ret->parent = parent;
1291 ret->sc = sc;
1292 ret->query_txt = parent->tab->query_txt;
1293 ret->builder = parent->tab->builder;
1294 ret->frame = parent->tab->frame;
1295 ret->tab_label = parent->tab->tab_label;
1296 ret->close_button = parent->tab->close_button;
1297 ret->clear_button = parent->tab->clear_button;
1298 ret->play_button = parent->tab->play_button;
1299 ret->label = parent->tab->label;
1300
1301 return ret;
1302}
1303
1304
1305
1306/**
1307 * Add a search result to the given search tab.
1308 *
1309 * @param tab search tab to extend
1310 * @param iter set to position where search result is added
1311 * @param parent_rr reference to parent entry in search tab
1312 * @param uri uri to add
1313 * @param meta metadata of the entry
1314 * @param result associated FS search result (can be NULL)
1315 * @param applicability_rank how relevant is the result
1316 * @return entry for the search result
1317 */
1318struct SearchResult *
1319GNUNET_GTK_add_search_result (struct SearchTab *tab,
1320 GtkTreeIter *iter,
1321 GtkTreeRowReference *parent_rr,
1322 const struct GNUNET_FS_Uri *uri,
1323 const struct GNUNET_CONTAINER_MetaData *meta,
1324 struct GNUNET_FS_SearchResult *result,
1325 uint32_t applicability_rank)
1326{
1327 struct SearchResult *sr;
1328 GtkTreePath *tp;
1329 const char *status_colour;
1330 char *desc;
1331 char *mime;
1332 char *uris;
1333 GdkPixbuf *pixbuf;
1334 GtkTreeIter *pitr;
1335 GtkTreeIter pmem;
1336 GtkTreePath *path;
1337 GtkTreeModel *tm;
1338 GtkTreeStore *ts;
1339 uint64_t fsize;
1340
1341 if ( (uri != NULL) &&
1342 (!GNUNET_FS_uri_test_loc (uri)) &&
1343 (!GNUNET_FS_uri_test_chk (uri)) )
1344 {
1345 fsize = 0;
1346 mime = GNUNET_strdup ("GNUnet namespace");
1347 status_colour = "lightgreen";
1348 }
1349 else if (uri != NULL)
1350 {
1351 fsize = GNUNET_FS_uri_chk_get_file_size (uri);
1352 mime = GNUNET_CONTAINER_meta_data_get_first_by_types (meta,
1353 EXTRACTOR_METATYPE_MIMETYPE,
1354 EXTRACTOR_METATYPE_FORMAT,
1355 -1);
1356 status_colour = "white";
1357 }
1358 else
1359 {
1360 fsize = 0;
1361 status_colour = "gray";
1362 mime = NULL;
1363 }
1364 desc = GNUNET_CONTAINER_meta_data_get_first_by_types (meta,
1365 EXTRACTOR_METATYPE_PACKAGE_NAME,
1366 EXTRACTOR_METATYPE_TITLE,
1367 EXTRACTOR_METATYPE_BOOK_TITLE,
1368 EXTRACTOR_METATYPE_FILENAME,
1369 EXTRACTOR_METATYPE_DESCRIPTION,
1370 EXTRACTOR_METATYPE_SUMMARY,
1371 EXTRACTOR_METATYPE_ALBUM,
1372 EXTRACTOR_METATYPE_COMMENT,
1373 EXTRACTOR_METATYPE_SUBJECT,
1374 EXTRACTOR_METATYPE_KEYWORDS,
1375 -1);
1376 if (desc == NULL)
1377 desc = GNUNET_strdup (_("no description supplied"));
1378 if (uri == NULL)
1379 uris = GNUNET_strdup (_("no URI"));
1380 else
1381 uris = GNUNET_FS_uri_to_string (uri);
1382
1383 pixbuf = GNUNET_GTK_get_thumbnail_from_meta_data (meta);
1384 sr = GNUNET_malloc (sizeof (struct SearchResult));
1385 sr->result = result;
1386 sr->tab = tab;
1387 if (parent_rr != NULL)
1388 {
1389 /* get piter from parent */
1390 path = gtk_tree_row_reference_get_path (parent_rr);
1391 tm = gtk_tree_row_reference_get_model (parent_rr);
1392 if (TRUE != gtk_tree_model_get_iter (GTK_TREE_MODEL (tm),
1393 &pmem, path))
1394 {
1395 GNUNET_break (0);
1396 gtk_tree_path_free (path);
1397 /* desperate measure: make top-level entry */
1398 pitr = NULL;
1399 }
1400 else
1401 {
1402 pitr = &pmem;
1403 }
1404 ts = GTK_TREE_STORE (tm);
1405 }
1406 else
1407 {
1408 /* top-level result */
1409 pitr = NULL;
1410 ts = tab->ts;
1411 }
1412 gtk_tree_store_insert_with_values (ts,
1413 iter,
1414 pitr,
1415 G_MAXINT,
1416 0, GNUNET_CONTAINER_meta_data_duplicate (meta),
1417 1, (uri == NULL) ? NULL : GNUNET_FS_uri_dup (uri),
1418 2, (uri == NULL) ? 0 : fsize,
1419 3, pixbuf /* preview */,
1420 4, 0 /* percent progress */,
1421 5, 0 /* percent availability */,
1422 6, desc /* filename/description */,
1423 7, uris,
1424 8, status_colour,
1425 9, sr,
1426 10, mime,
1427 11, applicability_rank,
1428 12, 0 /* avail-cert */,
1429 13, 0 /* avail-rank */,
1430 -1);
1431 if (tab != NULL)
1432 {
1433 while (tab->parent != NULL)
1434 tab = tab->parent->tab;
1435 tab->num_results++;
1436 }
1437 if (pixbuf != NULL)
1438 g_object_unref (pixbuf);
1439 GNUNET_free (uris);
1440 GNUNET_free (desc);
1441 GNUNET_free_non_null (mime);
1442 tp = gtk_tree_model_get_path (GTK_TREE_MODEL (ts),
1443 iter);
1444 sr->rr = gtk_tree_row_reference_new (GTK_TREE_MODEL (ts),
1445 tp);
1446 gtk_tree_path_free (tp);
1447 return sr;
1448}
1449
1450
1451static struct SearchResult *
1452process_search_result (void *cls,
1453 struct SearchResult *parent,
1454 const struct GNUNET_FS_Uri *uri,
1455 const struct GNUNET_CONTAINER_MetaData *meta,
1456 struct GNUNET_FS_SearchResult *result,
1457 uint32_t applicability_rank)
1458{
1459 struct SearchTab *tab = cls;
1460 struct SearchResult *sr;
1461 GtkTreeIter iter;
1462
1463 sr = GNUNET_GTK_add_search_result (tab, &iter,
1464 (parent != NULL) ? parent->rr : NULL,
1465 uri,
1466 meta, result, applicability_rank);
1467 update_search_label (tab);
1468 return sr;
1469}
1470
1471
1472/**
1473 * Setup a new top-level entry in the URI tab. If necessary, create
1474 * the URI tab first.
1475 *
1476 * @param iter set to the new entry
1477 * @param srp set to search result
1478 * @param meta metadata for the new entry
1479 * @param uri URI for the new entry
1480 * @return NULL on error, otherwise tree store matching iter
1481 */
1482struct SearchTab *
1483GNUNET_GTK_add_to_uri_tab (GtkTreeIter *iter,
1484 struct SearchResult **srp,
1485 const struct GNUNET_CONTAINER_MetaData *meta,
1486 const struct GNUNET_FS_Uri *uri)
1487{
1488 struct SearchTab *utab;
1489 struct SearchResult *sr;
1490 GtkNotebook *notebook;
1491 gint page;
1492
1493 utab = search_tab_head;
1494 while (utab != NULL)
1495 {
1496 if (utab->sc == NULL)
1497 break;
1498 utab = utab->next;
1499 }
1500 if (utab == NULL)
1501 {
1502 utab = setup_search (NULL, NULL);
1503 gtk_widget_set_visible (utab->close_button,
1504 FALSE);
1505 gtk_widget_set_visible (utab->pause_button,
1506 FALSE);
1507 }
1508 else
1509 {
1510 /* make 'utab' the current page */
1511 notebook = GTK_NOTEBOOK (GNUNET_GTK_get_main_window_object ("GNUNET_GTK_main_window_notebook"));
1512 for (page=0;page<gtk_notebook_get_n_pages (notebook);page++)
1513 if (utab->frame ==
1514 gtk_notebook_get_nth_page (notebook,
1515 page))
1516 {
1517 gtk_notebook_set_current_page (notebook,
1518 page);
1519 break;
1520 }
1521 }
1522 sr = GNUNET_GTK_add_search_result (utab, iter,
1523 NULL, uri, meta,
1524 NULL, 0);
1525
1526 if (NULL != srp)
1527 *srp = sr;
1528 return utab;
1529}
1530
1531
1532static struct SearchTab *
1533handle_search_error (struct SearchTab *sr,
1534 const char *emsg)
1535{
1536 /* FIXME: implement error handler */
1537 GNUNET_break (0);
1538 return sr;
1539}
1540
1541
1542static struct SearchResult *
1543update_search_result (struct SearchResult *sr,
1544 const struct GNUNET_CONTAINER_MetaData *meta,
1545 int32_t availability_rank,
1546 uint32_t availability_certainty,
1547 uint32_t applicability_rank)
1548{
1549 GtkTreeIter iter;
1550 struct GNUNET_CONTAINER_MetaData *ometa;
1551 GtkTreeView *tv;
1552 GtkTreePath *tp;
1553 GtkTreeStore *ts;
1554 GtkTreeModel *tm;
1555 char *desc;
1556 char *mime;
1557 GdkPixbuf *pixbuf;
1558 guint percent_avail;
1559 GtkNotebook *notebook;
1560 gint page;
1561
1562 if (sr == NULL)
1563 return NULL;
1564 desc = GNUNET_CONTAINER_meta_data_get_first_by_types (meta,
1565 EXTRACTOR_METATYPE_PACKAGE_NAME,
1566 EXTRACTOR_METATYPE_TITLE,
1567 EXTRACTOR_METATYPE_BOOK_TITLE,
1568 EXTRACTOR_METATYPE_FILENAME,
1569 EXTRACTOR_METATYPE_DESCRIPTION,
1570 EXTRACTOR_METATYPE_SUMMARY,
1571 EXTRACTOR_METATYPE_ALBUM,
1572 EXTRACTOR_METATYPE_COMMENT,
1573 EXTRACTOR_METATYPE_SUBJECT,
1574 EXTRACTOR_METATYPE_KEYWORDS,
1575 -1);
1576 if (desc == NULL)
1577 desc = GNUNET_strdup (_("no description supplied"));
1578 mime = GNUNET_CONTAINER_meta_data_get_first_by_types (meta,
1579 EXTRACTOR_METATYPE_MIMETYPE,
1580 EXTRACTOR_METATYPE_FORMAT,
1581 -1);
1582 pixbuf = GNUNET_GTK_get_thumbnail_from_meta_data (meta);
1583 tp = gtk_tree_row_reference_get_path (sr->rr);
1584 tm = gtk_tree_row_reference_get_model (sr->rr);
1585 ts = GTK_TREE_STORE (tm);
1586 gtk_tree_model_get_iter (tm, &iter, tp);
1587 gtk_tree_path_free (tp);
1588 gtk_tree_model_get (tm,
1589 &iter,
1590 0, &ometa,
1591 -1);
1592 if (meta != NULL)
1593 GNUNET_CONTAINER_meta_data_destroy (ometa);
1594 if (availability_certainty > 0)
1595 percent_avail = (availability_certainty + availability_rank) * 50 / availability_certainty;
1596 else
1597 percent_avail = 0;
1598 gtk_tree_store_set (ts,
1599 &iter,
1600 0, GNUNET_CONTAINER_meta_data_duplicate (meta),
1601 3, pixbuf /* preview */,
1602 5, (guint) percent_avail /* percent availability */,
1603 6, desc /* filename/description */,
1604 10, mime,
1605 11, (guint) applicability_rank,
1606 12, (guint) availability_certainty,
1607 13, (gint) availability_rank,
1608 -1);
1609 if (pixbuf != NULL)
1610 g_object_unref (pixbuf);
1611 GNUNET_free (desc);
1612 GNUNET_free_non_null (mime);
1613
1614 notebook = GTK_NOTEBOOK (GNUNET_GTK_get_main_window_object ("GNUNET_GTK_main_window_notebook"));
1615 page = gtk_notebook_get_current_page (notebook);
1616 if (gtk_notebook_get_nth_page (notebook,
1617 page) == sr->tab->frame)
1618 {
1619 tv = GTK_TREE_VIEW (gtk_builder_get_object (sr->tab->builder,
1620 "_search_result_frame"));
1621
1622 update_meta_data_views (tv,
1623 sr->tab);
1624 }
1625 return sr;
1626}
1627
1628
1629static void
1630free_search_result (struct SearchResult *sr)
1631{
1632 GtkTreePath *tp;
1633 GtkTreeModel *tm;
1634 GtkTreeIter iter;
1635 struct GNUNET_FS_Uri *uri;
1636 struct GNUNET_CONTAINER_MetaData *meta;
1637
1638 if (sr == NULL)
1639 {
1640 GNUNET_break (0);
1641 return;
1642 }
1643 tp = gtk_tree_row_reference_get_path (sr->rr);
1644 tm = gtk_tree_row_reference_get_model (sr->rr);
1645 gtk_tree_model_get_iter (tm, &iter, tp);
1646 gtk_tree_path_free (tp);
1647 gtk_tree_model_get (tm,
1648 &iter,
1649 0, &meta,
1650 1, &uri,
1651 -1);
1652 if (uri != NULL)
1653 GNUNET_FS_uri_destroy (uri);
1654 if (meta != NULL)
1655 GNUNET_CONTAINER_meta_data_destroy (meta);
1656 gtk_tree_row_reference_free (sr->rr);
1657 gtk_tree_store_remove (GTK_TREE_STORE (tm),
1658 &iter);
1659 GNUNET_free (sr);
1660}
1661
1662
1663/**
1664 * Tell FS to stop publishing.
1665 */
1666static void
1667stop_publishing (GtkButton *button,
1668 gpointer user_data)
1669{
1670 struct PublishTab *tab = user_data;
1671 struct GNUNET_FS_PublishContext *pc;
1672
1673 if (NULL != (pc = tab->pc))
1674 {
1675 tab->pc = NULL;
1676 GNUNET_FS_publish_stop (pc);
1677 }
1678}
1679
1680
1681static struct PublishEntry *
1682setup_publish (struct GNUNET_FS_PublishContext *pc,
1683 const char *fn,
1684 uint64_t fsize,
1685 struct PublishEntry *parent)
1686{
1687 struct PublishTab *tab;
1688 struct PublishEntry *ent;
1689 GtkTreeIter *pitrptr;
1690 GtkTreeIter iter;
1691 GtkTreeIter piter;
1692 GtkTreePath *path;
1693 GtkWindow *df;
1694 GtkWidget *tab_label;
1695 GtkLabel *fn_label;
1696 GtkWidget *close_button;
1697 GtkNotebook *notebook;
1698 gint pages;
1699 char *size_fancy;
1700
1701 if (NULL == parent)
1702 {
1703 /* create new tab */
1704 tab = GNUNET_malloc (sizeof (struct PublishTab));
1705 tab->pc = pc;
1706 GNUNET_CONTAINER_DLL_insert (publish_tab_head,
1707 publish_tab_tail,
1708 tab);
1709 tab->builder = GNUNET_GTK_get_new_builder ("publish_tab.glade");
1710 df = GTK_WINDOW (gtk_builder_get_object (tab->builder,
1711 "_publish_frame_window"));
1712 tab->frame = gtk_bin_get_child (GTK_BIN (df));
1713 gtk_widget_ref (tab->frame);
1714 gtk_container_remove (GTK_CONTAINER (df), tab->frame);
1715 gtk_widget_destroy (GTK_WIDGET (df));
1716
1717 /* load tab_label */
1718 df = GTK_WINDOW (gtk_builder_get_object (tab->builder,
1719 "_publish_label_window"));
1720 tab_label = gtk_bin_get_child (GTK_BIN (df));
1721 gtk_widget_ref (tab_label);
1722 gtk_container_remove (GTK_CONTAINER (df), tab_label);
1723 gtk_widget_destroy (GTK_WIDGET (df));
1724
1725 /* get refs to widgets */
1726 fn_label = GTK_LABEL (gtk_builder_get_object (tab->builder,
1727 "_publish_label_window_label"));
1728 gtk_label_set_text (fn_label, fn);
1729 close_button = GTK_WIDGET (gtk_builder_get_object (tab->builder,
1730 "_publish_label_close_button"));
1731 g_signal_connect(G_OBJECT(close_button), "clicked",
1732 G_CALLBACK(stop_publishing), tab);
1733 /* make visible */
1734 notebook = GTK_NOTEBOOK (GNUNET_GTK_get_main_window_object ("GNUNET_GTK_main_window_notebook"));
1735 pages = gtk_notebook_get_n_pages (notebook);
1736 gtk_notebook_insert_page (notebook,
1737 tab->frame,
1738 tab_label,
1739 pages - 1);
1740 gtk_widget_show (GTK_WIDGET (notebook));
1741 tab->ts = GTK_TREE_STORE (gtk_builder_get_object (tab->builder,
1742 "_publish_frame_tree_store"));
1743 pitrptr = NULL;
1744 }
1745 else
1746 {
1747 /* create new iter from parent */
1748 tab = parent->tab;
1749 path = gtk_tree_row_reference_get_path (parent->rr);
1750 if (TRUE != gtk_tree_model_get_iter (GTK_TREE_MODEL (tab->ts),
1751 &piter, path))
1752 {
1753 GNUNET_break (0);
1754 return NULL;
1755 }
1756 pitrptr = &piter;
1757 }
1758 size_fancy = GNUNET_STRINGS_byte_size_fancy (fsize);
1759 gtk_tree_store_insert_with_values (tab->ts,
1760 &iter,
1761 pitrptr,
1762 G_MAXINT,
1763 0, fn,
1764 1, size_fancy,
1765 2, "white",
1766 3, (guint) 0 /* progress */,
1767 -1);
1768 GNUNET_free (size_fancy);
1769 ent = GNUNET_malloc (sizeof (struct PublishEntry));
1770 ent->is_top = (parent == NULL) ? GNUNET_YES : GNUNET_NO;
1771 ent->tab = tab;
1772 path = gtk_tree_model_get_path (GTK_TREE_MODEL (tab->ts), &iter);
1773 ent->rr = gtk_tree_row_reference_new (GTK_TREE_MODEL (tab->ts),
1774 path);
1775 gtk_tree_path_free (path);
1776 ent->pc = pc;
1777 return ent;
1778}
1779
1780
1781/**
1782 * Notification of FS to a client about the progress of an
1783 * operation. Callbacks of this type will be used for uploads,
1784 * downloads and searches. Some of the arguments depend a bit
1785 * in their meaning on the context in which the callback is used.
1786 *
1787 * @param cls closure
1788 * @param info details about the event, specifying the event type
1789 * and various bits about the event
1790 * @return client-context (for the next progress call
1791 * for this operation; should be set to NULL for
1792 * SUSPEND and STOPPED events). The value returned
1793 * will be passed to future callbacks in the respective
1794 * field in the GNUNET_FS_ProgressInfo struct.
1795 */
1796void*
1797GNUNET_GTK_fs_event_handler (void *cls,
1798 const struct GNUNET_FS_ProgressInfo *info)
1799{
1800 void *ret;
1801
1802 switch (info->status)
1803 {
1804 case GNUNET_FS_STATUS_PUBLISH_START:
1805 return setup_publish (info->value.publish.pc,
1806 info->value.publish.filename,
1807 info->value.publish.size,
1808 info->value.publish.pctx);
1809 case GNUNET_FS_STATUS_PUBLISH_RESUME:
1810 ret = setup_publish (info->value.publish.pc,
1811 info->value.publish.filename,
1812 info->value.publish.size,
1813 info->value.publish.pctx);
1814 if (ret == NULL)
1815 return ret;
1816 if (info->value.publish.specifics.resume.message != NULL)
1817 {
1818 ret = handle_publish_error (ret,
1819 info->value.publish.specifics.resume.message);
1820 }
1821 else if (info->value.publish.specifics.resume.chk_uri != NULL)
1822 {
1823 ret = handle_publish_completed (ret,
1824 info->value.publish.specifics.resume.chk_uri);
1825 }
1826 return ret;
1827 case GNUNET_FS_STATUS_PUBLISH_SUSPEND:
1828 close_publish_tab (info->value.publish.cctx);
1829 return NULL;
1830 case GNUNET_FS_STATUS_PUBLISH_PROGRESS:
1831 return mark_publish_progress (info->value.publish.cctx,
1832 info->value.publish.size,
1833 info->value.publish.completed);
1834 case GNUNET_FS_STATUS_PUBLISH_ERROR:
1835 return handle_publish_error (info->value.publish.cctx,
1836 info->value.publish.specifics.error.message);
1837 case GNUNET_FS_STATUS_PUBLISH_COMPLETED:
1838 return handle_publish_completed (info->value.publish.cctx,
1839 info->value.publish.specifics.completed.chk_uri);
1840 case GNUNET_FS_STATUS_PUBLISH_STOPPED:
1841 close_publish_tab (info->value.publish.cctx);
1842 return NULL;
1843 case GNUNET_FS_STATUS_DOWNLOAD_START:
1844 return setup_download (info->value.download.cctx,
1845 info->value.download.pctx,
1846 info->value.download.sctx,
1847 info->value.download.dc,
1848 info->value.download.uri,
1849 info->value.download.specifics.start.meta,
1850 info->value.download.size,
1851 info->value.download.completed);
1852 case GNUNET_FS_STATUS_DOWNLOAD_RESUME:
1853 ret = setup_download (info->value.download.cctx,
1854 info->value.download.pctx,
1855 info->value.download.sctx,
1856 info->value.download.dc,
1857 info->value.download.uri,
1858 info->value.download.specifics.resume.meta,
1859 info->value.download.size,
1860 info->value.download.completed);
1861 if (info->value.download.specifics.resume.message != NULL)
1862 {
1863 ret = mark_download_error (ret,
1864 info->value.download.specifics.resume.message);
1865 }
1866 return ret;
1867 case GNUNET_FS_STATUS_DOWNLOAD_SUSPEND:
1868 stop_download (info->value.download.cctx, GNUNET_YES);
1869 return NULL;
1870 case GNUNET_FS_STATUS_DOWNLOAD_PROGRESS:
1871 return mark_download_progress (info->value.download.cctx,
1872 info->value.download.size,
1873 info->value.download.completed,
1874 info->value.download.specifics.progress.data,
1875 info->value.download.specifics.progress.offset,
1876 info->value.download.specifics.progress.data_len,
1877 info->value.download.specifics.progress.depth);
1878 case GNUNET_FS_STATUS_DOWNLOAD_ERROR:
1879 return mark_download_error (info->value.download.cctx,
1880 info->value.download.specifics.error.message);
1881 case GNUNET_FS_STATUS_DOWNLOAD_COMPLETED:
1882 return mark_download_completed (info->value.download.cctx,
1883 info->value.download.size,
1884 info->value.download.filename);
1885 case GNUNET_FS_STATUS_DOWNLOAD_STOPPED:
1886 stop_download (info->value.download.cctx, GNUNET_NO);
1887 return NULL;
1888 case GNUNET_FS_STATUS_DOWNLOAD_ACTIVE:
1889 return change_download_colour (info->value.download.cctx,
1890 "yellow");
1891 case GNUNET_FS_STATUS_DOWNLOAD_INACTIVE:
1892 return change_download_colour (info->value.download.cctx,
1893 "blue");
1894 case GNUNET_FS_STATUS_DOWNLOAD_LOST_PARENT:
1895 return download_lost_parent (info->value.download.cctx,
1896 info->value.download.size,
1897 info->value.download.completed,
1898 info->value.download.is_active);
1899 case GNUNET_FS_STATUS_SEARCH_START:
1900 if (info->value.search.pctx != NULL)
1901 return setup_inner_search (info->value.search.sc,
1902 info->value.search.pctx);
1903 return setup_search (info->value.search.sc,
1904 info->value.search.query);
1905 case GNUNET_FS_STATUS_SEARCH_RESUME:
1906 ret = setup_search (info->value.search.sc,
1907 info->value.search.query);
1908 if (info->value.search.specifics.resume.message)
1909 ret = handle_search_error (ret,
1910 info->value.search.specifics.resume.message);
1911 return ret;
1912 case GNUNET_FS_STATUS_SEARCH_RESUME_RESULT:
1913 ret = process_search_result (info->value.search.cctx,
1914 info->value.search.pctx,
1915 info->value.search.specifics.resume_result.uri,
1916 info->value.search.specifics.resume_result.meta,
1917 info->value.search.specifics.resume_result.result,
1918 info->value.search.specifics.resume_result.applicability_rank);
1919 return update_search_result (ret,
1920 info->value.search.specifics.resume_result.meta,
1921 info->value.search.specifics.resume_result.applicability_rank,
1922 info->value.search.specifics.resume_result.availability_certainty,
1923 info->value.search.specifics.resume_result.availability_rank);
1924 case GNUNET_FS_STATUS_SEARCH_SUSPEND:
1925 close_search_tab (info->value.search.cctx);
1926 return NULL;
1927 case GNUNET_FS_STATUS_SEARCH_RESULT:
1928 return process_search_result (info->value.search.cctx,
1929 info->value.search.pctx,
1930 info->value.search.specifics.result.uri,
1931 info->value.search.specifics.result.meta,
1932 info->value.search.specifics.result.result,
1933 info->value.search.specifics.result.applicability_rank);
1934 case GNUNET_FS_STATUS_SEARCH_RESULT_NAMESPACE:
1935 GNUNET_break (0);
1936 break;
1937 case GNUNET_FS_STATUS_SEARCH_UPDATE:
1938 return update_search_result (info->value.search.specifics.update.cctx,
1939 info->value.search.specifics.update.meta,
1940 info->value.search.specifics.update.applicability_rank,
1941 info->value.search.specifics.update.availability_certainty,
1942 info->value.search.specifics.update.availability_rank);
1943 case GNUNET_FS_STATUS_SEARCH_ERROR:
1944 return handle_search_error (info->value.search.cctx,
1945 info->value.search.specifics.error.message);
1946 case GNUNET_FS_STATUS_SEARCH_PAUSED:
1947 return info->value.search.cctx;
1948 case GNUNET_FS_STATUS_SEARCH_CONTINUED:
1949 return info->value.search.cctx;
1950 case GNUNET_FS_STATUS_SEARCH_RESULT_STOPPED:
1951 free_search_result (info->value.search.specifics.result_suspend.cctx);
1952 return NULL;
1953 case GNUNET_FS_STATUS_SEARCH_RESULT_SUSPEND:
1954 free_search_result (info->value.search.specifics.result_suspend.cctx);
1955 return NULL;
1956 case GNUNET_FS_STATUS_SEARCH_STOPPED:
1957 close_search_tab (info->value.search.cctx);
1958 return NULL;
1959 case GNUNET_FS_STATUS_UNINDEX_START:
1960 GNUNET_break (0);
1961 break;
1962 case GNUNET_FS_STATUS_UNINDEX_RESUME:
1963 GNUNET_break (0);
1964 break;
1965 case GNUNET_FS_STATUS_UNINDEX_SUSPEND:
1966 GNUNET_break (0);
1967 break;
1968 case GNUNET_FS_STATUS_UNINDEX_PROGRESS:
1969 GNUNET_break (0);
1970 break;
1971 case GNUNET_FS_STATUS_UNINDEX_ERROR:
1972 GNUNET_break (0);
1973 break;
1974 case GNUNET_FS_STATUS_UNINDEX_COMPLETED:
1975 GNUNET_break (0);
1976 break;
1977 case GNUNET_FS_STATUS_UNINDEX_STOPPED:
1978 GNUNET_break (0);
1979 break;
1980 default:
1981 GNUNET_break (0);
1982 break;
1983 }
1984 return NULL;
1985}
1986
1987
1988/**
1989 * Page switched in main notebook, update thumbnail and
1990 * metadata views.
1991 */
1992void
1993GNUNET_GTK_main_window_notebook_switch_page_cb (GtkWidget * dummy,
1994 gpointer data)
1995{
1996 GtkNotebook *notebook;
1997 gint page;
1998 GtkWidget *w;
1999 struct SearchTab *tab;
2000 GtkImage *image;
2001 GtkListStore *ms;
2002 GtkTreeView *tv;
2003
2004 notebook = GTK_NOTEBOOK (GNUNET_GTK_get_main_window_object ("GNUNET_GTK_main_window_notebook"));
2005 page = gtk_notebook_get_current_page (notebook);
2006 w = gtk_notebook_get_nth_page (notebook, page);
2007 tab = search_tab_head;
2008 while (tab != NULL)
2009 {
2010 if (tab->frame == w)
2011 {
2012 tv = GTK_TREE_VIEW (gtk_builder_get_object (tab->builder,
2013 "_search_result_frame"));
2014 update_meta_data_views (tv, tab);
2015 return;
2016 }
2017 tab = tab->next;
2018 }
2019 image = GTK_IMAGE (GNUNET_GTK_get_main_window_object ("GNUNET_GTK_main_window_preview_image"));
2020 gtk_image_clear (image);
2021 ms = GTK_LIST_STORE (GNUNET_GTK_get_main_window_object ("GNUNET_GTK_meta_data_list_store"));
2022 gtk_list_store_clear (ms);
2023}
2024
2025
2026
2027/* end of fs_event_handler.c */
diff --git a/src/fs_event_handler.h b/src/fs_event_handler.h
deleted file mode 100644
index a86ff339..00000000
--- a/src/fs_event_handler.h
+++ /dev/null
@@ -1,198 +0,0 @@
1/*
2 This file is part of GNUnet.
3 (C) 2010 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/fs_event_handler.h
23 * @brief Main event handler for file-sharing
24 * @author Christian Grothoff
25 */
26#include "common.h"
27
28
29struct SearchResult;
30
31
32/**
33 * Context we keep for a search tab.
34 */
35struct SearchTab
36{
37 /**
38 * This is a doubly-linked list.
39 */
40 struct SearchTab *next;
41
42 /**
43 * This is a doubly-linked list.
44 */
45 struct SearchTab *prev;
46
47 /**
48 * Set in case this is an inner search, otherwise NULL.
49 */
50 struct SearchResult *parent;
51
52 /**
53 * Handle for this search with FS library.
54 */
55 struct GNUNET_FS_SearchContext *sc;
56
57 char *query_txt;
58
59 GtkBuilder *builder;
60
61 GtkWidget *frame;
62
63 GtkWidget *tab_label;
64
65 GtkWidget *close_button;
66
67 GtkWidget *clear_button;
68
69 GtkWidget *play_button;
70
71 GtkWidget *pause_button;
72
73 GtkLabel *label;
74
75 GtkTreeStore *ts;
76
77 unsigned int num_results;
78
79};
80
81
82struct DownloadEntry
83{
84
85 /**
86 * Download entry of the parent (for recursive downloads),
87 * NULL if we are either a top-level download (from URI,
88 * from opened directory, orphaned from search or direct
89 * search result).
90 */
91 struct DownloadEntry *pde;
92
93 /**
94 * Associated search result, or NULL if we don't belong
95 * to a search directly (download entry).
96 */
97 struct SearchResult *sr;
98
99 /**
100 * FS handle to control the download.
101 */
102 struct GNUNET_FS_DownloadContext *dc;
103
104 /**
105 * URI for the download.
106 */
107 struct GNUNET_FS_Uri *uri;
108
109 /**
110 * Meta data for the download.
111 */
112 struct GNUNET_CONTAINER_MetaData *meta;
113
114 /**
115 * Where in the tree view is this download being displayed.
116 */
117 GtkTreeRowReference *rr;
118
119 /**
120 * Tree store where we are stored.
121 */
122 GtkTreeStore *ts;
123
124 /**
125 * Tab where this download is currently on display.
126 */
127 struct SearchTab *tab;
128
129 /**
130 * Has the download completed (or errored)?
131 */
132 int is_done;
133
134};
135
136
137
138
139/**
140 * Setup a new top-level entry in the URI tab. If necessary, create
141 * the URI tab first.
142 *
143 * @param iter set to the new entry
144 * @param srp set to search result
145 * @param meta metadata for the new entry
146 * @param uri URI for the new entry
147 * @return NULL on error, otherwise search tab with the new entry
148 */
149struct SearchTab *
150GNUNET_GTK_add_to_uri_tab (GtkTreeIter *iter,
151 struct SearchResult **sr,
152 const struct GNUNET_CONTAINER_MetaData *meta,
153 const struct GNUNET_FS_Uri *uri);
154
155
156
157/**
158 * Add a search result to the given search tab.
159 *
160 * @param tab search tab to extend
161 * @param iter set to position where search result is added
162 * @param parent_rr reference to parent entry in search tab
163 * @param uri uri to add
164 * @param meta metadata of the entry
165 * @param result associated FS search result (can be NULL)
166 * @param applicability_rank how relevant is the result
167 * @return entry for the search result
168 */
169struct SearchResult *
170GNUNET_GTK_add_search_result (struct SearchTab *tab,
171 GtkTreeIter *iter,
172 GtkTreeRowReference *parent_rr,
173 const struct GNUNET_FS_Uri *uri,
174 const struct GNUNET_CONTAINER_MetaData *meta,
175 struct GNUNET_FS_SearchResult *result,
176 uint32_t applicability_rank);
177
178
179/**
180 * Notification of FS to a client about the progress of an
181 * operation. Callbacks of this type will be used for uploads,
182 * downloads and searches. Some of the arguments depend a bit
183 * in their meaning on the context in which the callback is used.
184 *
185 * @param cls closure
186 * @param info details about the event, specifying the event type
187 * and various bits about the event
188 * @return client-context (for the next progress call
189 * for this operation; should be set to NULL for
190 * SUSPEND and STOPPED events). The value returned
191 * will be passed to future callbacks in the respective
192 * field in the GNUNET_FS_ProgressInfo struct.
193 */
194void* GNUNET_GTK_fs_event_handler (void *cls,
195 const struct GNUNET_FS_ProgressInfo *info);
196
197
198/* end of fs_event_handler.h */
diff --git a/src/gnunet-gtk.c b/src/gnunet-gtk.c
deleted file mode 100644
index 252faa31..00000000
--- a/src/gnunet-gtk.c
+++ /dev/null
@@ -1,1119 +0,0 @@
1/*
2 This file is part of GNUnet.
3 (C) 2010 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/gnunet-gtk.c
23 * @brief Main function of gnunet-gtk
24 * @author Christian Grothoff
25 */
26#include "common.h"
27#include "fs_event_handler.h"
28#if ENABLE_NLS
29#include <locale.h>
30#endif
31#include "peerinfo.h"
32
33/**
34 * Should gnunet-gtk start in tray mode?
35 */
36static int tray_only;
37
38/**
39 * Our tray icon.
40 */
41static GtkStatusIcon *tray_icon;
42
43/**
44 * Initialize GNU gettext for message translation.
45 */
46static void
47setup_nls ()
48{
49#if ENABLE_NLS
50 char *path;
51
52 setlocale (LC_ALL, "");
53 GNUNET_asprintf (&path,
54 "%s/%s/locale/",
55 GNUNET_GTK_get_data_dir (),
56 PACKAGE_NAME);
57 bindtextdomain ("gnunet-gtk", path);
58 textdomain ("gnunet-gtk");
59 bind_textdomain_codeset ("GNUnet", "UTF-8");
60 bind_textdomain_codeset ("gnunet-gtk", "UTF-8");
61 GNUNET_free (path);
62#else
63 fprintf (stderr,
64 "WARNING: gnunet-gtk was compiled without i18n support (did CFLAGS contain -Werror?).\n");
65#endif
66}
67
68
69/**
70 * Main context for our event loop.
71 */
72struct MainContext
73{
74
75 /**
76 * Main loop.
77 */
78 GMainLoop *gml;
79
80 /**
81 * GTK's main context.
82 */
83 GMainContext *gmc;
84
85 /**
86 * Recycled array of polling descriptors.
87 */
88 GPollFD *cached_poll_array;
89
90
91 /**
92 * Read set.
93 */
94 struct GNUNET_NETWORK_FDSet *rs;
95
96 /**
97 * Write set.
98 */
99 struct GNUNET_NETWORK_FDSet *ws;
100
101 /**
102 * Builder for the main window.
103 */
104 GtkBuilder *builder;
105
106 /**
107 * Our configuration.
108 */
109 const struct GNUNET_CONFIGURATION_Handle *cfg;
110
111 /**
112 * Handle for file-sharing operations.
113 */
114 struct GNUNET_FS_Handle *fs;
115
116 /**
117 * List of plugins for meta data extraction.
118 */
119 struct EXTRACTOR_PluginList *plugins;
120
121 /**
122 * Context for peerinfo notifications.
123 */
124 struct GNUNET_PEERINFO_NotifyContext *pnc;
125
126 /**
127 * Size of the 'cached_poll_array'.
128 */
129 guint cached_poll_array_size;
130
131 /**
132 * Return value from last g_main_context_query call.
133 */
134 guint poll_array_active;
135
136 /**
137 * Maximum GTK priority.
138 */
139 gint max_priority;
140
141#if WINDOWS
142 /**
143 * Array to hold pipe handles during a select() call
144 */
145 struct GNUNET_DISK_FileHandle **read_array;
146
147 /**
148 * Allocated length of read_array
149 */
150 int read_array_length;
151
152 /**
153 * Event to fire when a socket is ready for reading
154 */
155 HANDLE hEventRead;
156
157 /**
158 * Event to fire when a socket is ready for writing
159 */
160 HANDLE hEventWrite;
161
162 /**
163 * Event to fire when a socket had an error
164 */
165 HANDLE hEventException;
166
167 /**
168 * Event that is permanently enabled and is used to signal a pipe
169 * that is ready for writing (asynchronous pipes are always writable)
170 */
171 HANDLE hEventPipeWrite;
172
173 /**
174 * Event that is permanently enabled and is used to signal a pipe
175 * that is ready for reading (used to wake up early on a pipe that
176 * is known to be readable)
177 */
178 HANDLE hEventReadReady;
179
180 /**
181 * A list to hold file handles that are ready for reading
182 */
183 struct GNUNET_CONTAINER_SList *handles_read;
184
185 /**
186 * A list to hold file handles that are ready for writing
187 */
188 struct GNUNET_CONTAINER_SList *handles_write;
189
190 /**
191 * A list to hold file handles that are broken
192 */
193 struct GNUNET_CONTAINER_SList *handles_except;
194#endif
195};
196
197static void
198gnunet_gtk_dispatch_task (void *cls,
199 const struct GNUNET_SCHEDULER_TaskContext *tc)
200{
201 struct MainContext *mc = (struct MainContext *) cls;
202 g_main_context_dispatch (mc->gmc);
203}
204
205#ifndef FD_COPY
206#define FD_COPY(s, d) (memcpy ((d), (s), sizeof (fd_set)))
207#endif
208
209int
210gnunet_gtk_select (void *cls,
211 struct GNUNET_NETWORK_FDSet *rfds,
212 struct GNUNET_NETWORK_FDSet *wfds,
213 struct GNUNET_NETWORK_FDSet *efds,
214 const struct GNUNET_TIME_Relative timeout)
215{
216 struct MainContext *mc = (struct MainContext *) cls;
217 int max_nfds;
218 gint poll_result;
219
220 GPollFD *gfds;
221 gint delay;
222
223 guint i;
224 guint fd_counter = 0;
225
226 guint allocated_nfds, need_gfds;
227
228 fd_set aread, awrite, aexcept;
229 int pre_ret = 0;
230 int result = 0;
231 int socks = 0;
232 int sock_read = 0, sock_write = 0, sock_err = 0;
233
234#if WINDOWS
235 int always_ready_write_fd = -1;
236
237 int select_ret = 0;
238
239 int read_handles = 0;
240 DWORD waitstatus;
241#endif
242
243 FD_ZERO (&aread);
244 FD_ZERO (&awrite);
245 FD_ZERO (&aexcept);
246 if (rfds)
247 FD_COPY (&rfds->sds, &aread);
248 if (wfds)
249 FD_COPY (&wfds->sds, &awrite);
250 if (efds)
251 FD_COPY (&efds->sds, &aexcept);
252
253#if WINDOWS
254 ResetEvent (mc->hEventRead);
255 ResetEvent (mc->hEventWrite);
256 ResetEvent (mc->hEventException);
257
258 GNUNET_CONTAINER_slist_clear (mc->handles_read);
259 GNUNET_CONTAINER_slist_clear (mc->handles_write);
260 GNUNET_CONTAINER_slist_clear (mc->handles_except);
261#endif
262
263 if (TRUE != g_main_loop_is_running (mc->gml))
264 return GNUNET_NETWORK_socket_select (rfds, wfds, efds, timeout);
265
266 if (rfds != NULL)
267 max_nfds = rfds->nsds;
268 else
269 max_nfds = -1;
270 if (wfds != NULL && max_nfds < wfds->nsds)
271 max_nfds = wfds->nsds;
272 if (efds != NULL && max_nfds < efds->nsds)
273 max_nfds = efds->nsds;
274
275 allocated_nfds = mc->cached_poll_array_size;
276 gfds = mc->cached_poll_array;
277 if (allocated_nfds == 0)
278 {
279 /* TODO: get some statistics, find the maximum number of fds ever
280 * polled during normal gnunet-gtk operation, and set this to that number.
281 */
282 mc->cached_poll_array = gfds = g_new (GPollFD, 30);
283 mc->cached_poll_array_size = allocated_nfds = 30;
284 }
285
286 while (1)
287 {
288 fd_counter = 0;
289#if !WINDOWS
290 gboolean need_realloc = FALSE;
291 for (i = 0; !need_realloc && i < max_nfds; i += 1)
292 {
293 int isset[3];
294
295 isset[0] = (rfds == NULL) ? 0 : FD_ISSET (i, &rfds->sds);
296 isset[1] = (wfds == NULL) ? 0 : FD_ISSET (i, &wfds->sds);
297 isset[2] = (efds == NULL) ? 0 : FD_ISSET (i, &efds->sds);
298 if (!isset[0] && !isset[1] && !isset[2])
299 continue;
300 if (fd_counter >= allocated_nfds)
301 {
302 need_realloc = TRUE;
303 break;
304 }
305 gfds[fd_counter].fd = i;
306 gfds[fd_counter].events = (isset[0] ? G_IO_IN | G_IO_HUP | G_IO_ERR : 0)
307 | (isset[1] ? G_IO_OUT | G_IO_ERR : 0) | (isset[2] ? G_IO_ERR : 0);
308 fd_counter += 1;
309 }
310 if (need_realloc)
311 {
312 mc->cached_poll_array = gfds = g_renew (GPollFD, gfds, mc->cached_poll_array_size * 2);
313 mc->cached_poll_array_size = allocated_nfds = mc->cached_poll_array_size * 2;
314 fd_counter = 0;
315 need_realloc = FALSE;
316 }
317 else
318 break;
319#else
320 struct GNUNET_CONTAINER_SList_Iterator *t;
321 /* We might overshoot a little, but that won't hurt very much */
322 int need_nfds = (rfds->sds.fd_count + rfds->sds.fd_count + rfds->sds.fd_count > 0 ? 3 : 0)
323 + (rfds == NULL ? 0 : GNUNET_CONTAINER_slist_count (rfds->handles))
324 + (wfds == NULL ? 0 : 1)
325 + 1;
326 if (need_nfds >= allocated_nfds)
327 {
328 /* Since there are also gmainloop's own fds, just need_nfds won't be
329 * enough, so make it twice as long.
330 */
331 mc->cached_poll_array = gfds = g_renew (GPollFD, gfds, need_nfds * 2);
332 mc->cached_poll_array_size = allocated_nfds = need_nfds * 2;
333 }
334 if (mc->read_array_length < GNUNET_CONTAINER_slist_count (rfds->handles))
335 {
336 mc->read_array = GNUNET_realloc (mc->read_array, GNUNET_CONTAINER_slist_count (rfds->handles) * sizeof (struct GNUNET_DISK_FileHandle *));
337 mc->read_array_length = GNUNET_CONTAINER_slist_count (rfds->handles);
338 }
339 if (rfds != NULL)
340 {
341 for (t = GNUNET_CONTAINER_slist_begin (rfds->handles), i = 0;
342 GNUNET_CONTAINER_slist_end (t) != GNUNET_YES;
343 GNUNET_CONTAINER_slist_next (t), i += 1)
344 {
345 struct GNUNET_DISK_FileHandle *fh;
346 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (t, NULL);
347 if (fh->type == GNUNET_PIPE)
348 {
349 if (!ReadFile (fh->h, NULL, 0, NULL, fh->oOverlapRead))
350 {
351 DWORD error_code = GetLastError();
352 if (error_code == ERROR_IO_PENDING)
353 {
354#if DEBUG_NETWORK
355 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding the pipe's 0x%x overlapped event to the array as %d\n", fh->h, nhandles);
356#endif
357 gfds[fd_counter].fd = (intptr_t) fh->oOverlapRead->hEvent;
358 /* On W32 .events makes no sense - g_poll will just OR its
359 * contents into .revents when the .fd event fires.
360 * So we'll use it in the way that suits us the best.
361 */
362 gfds[fd_counter].events = G_IO_IN;
363 fd_counter += 1;
364 mc->read_array[read_handles] = fh;
365 read_handles += 1;
366 }
367 else
368 {
369 gfds[fd_counter].fd = (intptr_t) mc->hEventReadReady;
370 gfds[fd_counter].events = G_IO_HUP;
371 fd_counter += 1;
372 mc->read_array[read_handles] = fh;
373 read_handles += 1;
374 }
375 }
376 else
377 {
378#if DEBUG_NETWORK
379 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding the read ready event to the array as %d\n", nhandles);
380#endif
381 gfds[fd_counter].fd = (intptr_t) mc->hEventReadReady;
382 gfds[fd_counter].events = G_IO_IN;
383 fd_counter += 1;
384 mc->read_array[read_handles] = fh;
385 read_handles += 1;
386 }
387 }
388 else
389 {
390 GNUNET_CONTAINER_slist_add (mc->handles_read,
391 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
392 fh, sizeof (struct GNUNET_DISK_FileHandle));
393 pre_ret += 1;
394 }
395 }
396 }
397 if (wfds != NULL && GNUNET_CONTAINER_slist_count (wfds->handles) > 0)
398 {
399 gfds[fd_counter].fd = (intptr_t) mc->hEventPipeWrite;
400 gfds[fd_counter].events = G_IO_OUT;
401 always_ready_write_fd = fd_counter;
402 fd_counter += 1;
403 }
404 if (efds != NULL)
405 {
406 for (t = GNUNET_CONTAINER_slist_begin (efds->handles), i = 0;
407 GNUNET_CONTAINER_slist_end (t) != GNUNET_YES;
408 GNUNET_CONTAINER_slist_next (t), i += 1)
409 {
410 struct GNUNET_DISK_FileHandle *fh;
411 DWORD dwBytes;
412 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (t, NULL);
413 if (fh->type == GNUNET_PIPE)
414 {
415 if (!PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
416 {
417 GNUNET_CONTAINER_slist_add (mc->handles_except,
418 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
419 fh, sizeof (struct GNUNET_DISK_FileHandle));
420 pre_ret += 1;
421 }
422 }
423 }
424 }
425 GNUNET_CONTAINER_slist_iter_destroy (t);
426
427 if (rfds != NULL && rfds->sds.fd_count > 0)
428 {
429#if DEBUG_NETWORK
430 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding the socket read event to the array as %d\n", fd_counter);
431#endif
432 gfds[fd_counter].fd = (intptr_t) mc->hEventRead;
433 gfds[fd_counter].events = G_IO_IN;
434 for (i = 0; i < rfds->sds.fd_count; i++)
435 WSAEventSelect (rfds->sds.fd_array[i], mc->hEventRead, FD_ACCEPT | FD_READ | FD_CLOSE);
436 fd_counter += 1;
437 sock_read = rfds->sds.fd_count;
438 }
439 if (wfds != NULL && wfds->sds.fd_count > 0)
440 {
441 int wakeup = 0;
442#if DEBUG_NETWORK
443 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding the socket write event to the array as %d\n", fd_counter);
444#endif
445 gfds[fd_counter].fd = (intptr_t) mc->hEventWrite;
446 gfds[fd_counter].events = G_IO_OUT;
447 for (i = 0; i < wfds->sds.fd_count; i++)
448 {
449 DWORD error;
450 int status;
451 status = send (wfds->sds.fd_array[i], NULL, 0, 0);
452 error = GetLastError ();
453#if DEBUG_NETWORK
454 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "pre-send to the socket %d returned %d (%u)\n", i, status, error);
455#endif
456 if (status == 0 || (error != WSAEWOULDBLOCK && error != WSAENOTCONN))
457 wakeup = 1;
458 WSAEventSelect (wfds->sds.fd_array[i], mc->hEventWrite, FD_WRITE | FD_CONNECT | FD_CLOSE);
459 }
460 if (wakeup)
461 SetEvent (mc->hEventWrite);
462 fd_counter += 1;
463 sock_write = wfds->sds.fd_count;
464 }
465 if (efds != NULL && efds->sds.fd_count > 0)
466 {
467#if DEBUG_NETWORK
468 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding the socket error event to the array as %d\n", fd_counter);
469#endif
470 gfds[fd_counter].fd = (intptr_t) mc->hEventException;
471 gfds[fd_counter].events = G_IO_ERR;
472 for (i = 0; i < efds->sds.fd_count; i++)
473 WSAEventSelect (efds->sds.fd_array[i], mc->hEventException, FD_OOB | FD_CLOSE);
474 fd_counter += 1;
475 sock_err = efds->sds.fd_count;
476 }
477 break;
478#endif
479 }
480 socks = sock_read + sock_write + sock_err;
481
482 g_main_context_prepare (mc->gmc, &mc->max_priority);
483 while (allocated_nfds < (need_gfds = g_main_context_query (mc->gmc,
484 mc->max_priority, &delay, &gfds[fd_counter], allocated_nfds - fd_counter)))
485 {
486 mc->cached_poll_array = gfds = g_renew (GPollFD, gfds, allocated_nfds - fd_counter + need_gfds);
487 mc->cached_poll_array_size = allocated_nfds = allocated_nfds - fd_counter + need_gfds;
488 }
489 mc->poll_array_active = fd_counter + need_gfds;
490
491 if (timeout.rel_value != GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
492 {
493 if (delay >= 0)
494 delay = MIN(timeout.rel_value / GNUNET_TIME_UNIT_MILLISECONDS.rel_value, delay);
495 else
496 delay = timeout.rel_value / GNUNET_TIME_UNIT_MILLISECONDS.rel_value;
497 }
498
499 if (pre_ret > 0)
500 {
501#if DEBUG_NETWORK
502 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "pre_ret is %d, setting delay to 0\n", pre_ret);
503#endif
504 delay = 0;
505 }
506
507#if DEBUG_NETWORK
508 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "We have %d of our FDs and %d of GMC ones, going to wait %6dms\n", fd_counter, need_gfds, delay);
509#endif
510
511 poll_result = g_poll (gfds, fd_counter + need_gfds, delay);
512
513#if DEBUG_NETWORK
514 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "g_poll returned : %d\n", poll_result);
515#endif
516
517 /* Take care of GUI events.
518 * Dispatching the events here will eventually crash the scheduler, must do this
519 * from within a task (currently we're not in a task, but in a select() call, remember)
520 * Startup reason is used to pass the scheduler sanity check.
521 */
522 if (TRUE == g_main_context_check (mc->gmc, mc->max_priority, &gfds[fd_counter], need_gfds))
523 GNUNET_SCHEDULER_add_continuation (gnunet_gtk_dispatch_task, mc, GNUNET_SCHEDULER_REASON_STARTUP);
524
525#if !WINDOWS
526 if (rfds)
527 GNUNET_NETWORK_fdset_zero (rfds);
528 if (wfds)
529 GNUNET_NETWORK_fdset_zero (wfds);
530 if (efds)
531 GNUNET_NETWORK_fdset_zero (efds);
532 for (i = 0; i < fd_counter; i++)
533 {
534 int set[3];
535 if ((set[0] = FD_ISSET (gfds[i].fd, &aread)))
536 FD_SET (gfds[i].fd, &rfds->sds);
537 if ((set[1] = FD_ISSET (gfds[i].fd, &awrite)))
538 FD_SET (gfds[i].fd, &wfds->sds);
539 if ((set[2] = FD_ISSET (gfds[i].fd, &aexcept)))
540 FD_SET (gfds[i].fd, &efds->sds);
541 if (set[0] || set[1] || set[2])
542 result += 1;
543 }
544#else
545 if (socks > 0)
546 {
547 struct timeval tvslice;
548 tvslice.tv_sec = 0;
549 tvslice.tv_usec = 0;
550 select_ret = select (max_nfds, &aread, &awrite, &aexcept, &tvslice);
551 if (select_ret == -1)
552 select_ret = 0;
553#if DEBUG_NETWORK
554 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "select() returned %d\n", select_ret);
555#endif
556 }
557 if (always_ready_write_fd >= 0 && gfds[always_ready_write_fd].revents & G_IO_OUT)
558 {
559 GNUNET_CONTAINER_slist_append (mc->handles_write, wfds->handles);
560 result += GNUNET_CONTAINER_slist_count (mc->handles_write);
561#if DEBUG_NETWORK
562 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Added write pipe\n");
563#endif
564 }
565 for (i = 0; i < read_handles; i++)
566 {
567 DWORD error;
568 BOOL bret;
569 if (!(gfds[i].revents & (G_IO_IN | G_IO_HUP | G_IO_ERR)))
570 continue;
571 SetLastError (0);
572 waitstatus = 0;
573 bret = PeekNamedPipe (mc->read_array[i]->h, NULL, 0, NULL, &waitstatus, NULL);
574 error = GetLastError ();
575#if DEBUG_NETWORK
576 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peek at read pipe %d (0x%x) returned %d (%d bytes available) GLE %u\n", i, mc->read_array[i]->h, bret, waitstatus, error);
577#endif
578 if (bret == 0 || (gfds[i].revents & G_IO_ERR))
579 {
580 if (efds != NULL)
581 {
582 struct GNUNET_CONTAINER_SList_Iterator *t;
583 for (t = GNUNET_CONTAINER_slist_begin (efds->handles), i = 0;
584 GNUNET_CONTAINER_slist_end (t) != GNUNET_YES;
585 GNUNET_CONTAINER_slist_next (t), i += 1)
586 {
587 struct GNUNET_DISK_FileHandle *fh;
588 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (t, NULL);
589 if (fh == mc->read_array[i])
590 {
591 GNUNET_CONTAINER_slist_add (mc->handles_except,
592 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
593 fh, sizeof (struct GNUNET_DISK_FileHandle));
594 break;
595 }
596 }
597 GNUNET_CONTAINER_slist_iter_destroy (t);
598 }
599 }
600 else if (waitstatus <= 0)
601 continue;
602 GNUNET_CONTAINER_slist_add (mc->handles_read,
603 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
604 mc->read_array[i], sizeof (struct GNUNET_DISK_FileHandle));
605 result += 1;
606#if DEBUG_NETWORK
607 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe 0x%x (0x%x)\n", mc->read_array[i], mc->read_array[i]->h);
608#endif
609 }
610 waitstatus = WaitForSingleObject (mc->hEventWrite, 0);
611#if DEBUG_NETWORK
612 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Wait for the write event returned %d\n", waitstatus);
613#endif
614 if (waitstatus == WAIT_OBJECT_0)
615 {
616 for (i = 0; i < wfds->sds.fd_count; i++)
617 {
618 DWORD error;
619 int status;
620 int so_error = 0;
621 int sizeof_so_error = sizeof (so_error);
622 int gso_result = getsockopt (wfds->sds.fd_array[i], SOL_SOCKET, SO_ERROR, (char *) &so_error, &sizeof_so_error);
623 status = send (wfds->sds.fd_array[i], NULL, 0, 0);
624 error = GetLastError ();
625#if DEBUG_NETWORK
626 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "send to the socket %d returned %d (%u)\n", i, status, error);
627#endif
628 if (status == 0
629 || (error != WSAEWOULDBLOCK && error != WSAENOTCONN)
630 || (status == -1 && gso_result == 0 && error == WSAENOTCONN && so_error == WSAECONNREFUSED))
631 {
632 FD_SET (wfds->sds.fd_array[i], &awrite);
633 result += 1;
634 }
635 }
636 }
637 if (rfds)
638 {
639 struct GNUNET_CONTAINER_SList_Iterator *t;
640 for (i = 0; i < rfds->sds.fd_count; i++)
641 WSAEventSelect (rfds->sds.fd_array[i], mc->hEventRead, 0);
642 for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
643 GNUNET_CONTAINER_slist_end (t) != GNUNET_YES;
644 GNUNET_CONTAINER_slist_next (t))
645 {
646 struct GNUNET_DISK_FileHandle *fh;
647 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (t, NULL);
648 if (fh->type == GNUNET_PIPE)
649 CancelIo (fh->h);
650 }
651 GNUNET_CONTAINER_slist_iter_destroy (t);
652 GNUNET_NETWORK_fdset_zero (rfds);
653 if (select_ret != -1 && socks > 0)
654 GNUNET_NETWORK_fdset_copy_native (rfds, &aread, select_ret);
655 GNUNET_CONTAINER_slist_append (rfds->handles, mc->handles_read);
656 }
657 if (wfds)
658 {
659 for (i = 0; i < wfds->sds.fd_count; i++)
660 WSAEventSelect (wfds->sds.fd_array[i], mc->hEventWrite, 0);
661 GNUNET_NETWORK_fdset_zero (wfds);
662 if (select_ret != -1 && socks > 0)
663 GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, select_ret);
664 GNUNET_CONTAINER_slist_append (wfds->handles, mc->handles_write);
665 }
666 if (efds)
667 {
668 for (i = 0; i < efds->sds.fd_count; i++)
669 WSAEventSelect (efds->sds.fd_array[i], mc->hEventException, 0);
670 GNUNET_NETWORK_fdset_zero (efds);
671 if (select_ret != -1 && socks > 0)
672 GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, select_ret);
673 GNUNET_CONTAINER_slist_append (efds->handles, mc->handles_except);
674 result += GNUNET_CONTAINER_slist_count (mc->handles_except);
675 }
676 if (fd_counter > 0)
677 /* This is not accurate (select_ret counts write-ready sockets,
678 * and result does as well. Anything out there actually cares
679 * about this?
680 */
681 return select_ret + result;
682 else
683 return 0;
684#endif
685 return result;
686}
687
688
689
690/**
691 * Get the name of the directory where all of our package
692 * data is stored ($PREFIX/share/)
693 *
694 * @return name of the data directory
695 */
696const char *
697GNUNET_GTK_get_data_dir ()
698{
699 static char *dd;
700
701 if (dd == NULL)
702 dd = GNUNET_GTK_installation_get_path (GNUNET_OS_IPK_DATADIR);
703 return dd;
704}
705
706
707/**
708 * Free resources of the given context.
709 *
710 * @param context what to free, can be NULL
711 */
712static void
713free_context (struct MainContext *context)
714{
715 if (context == NULL)
716 return;
717 g_free (context->cached_poll_array);
718 GNUNET_NETWORK_fdset_destroy (context->rs);
719 GNUNET_NETWORK_fdset_destroy (context->ws);
720 gtk_widget_destroy (GTK_WIDGET (gtk_builder_get_object (context->builder,
721 "GNUNET_GTK_main_window")));
722 g_object_unref (G_OBJECT (context->builder));
723 g_main_loop_unref (context->gml);
724 GNUNET_free (context);
725}
726
727/**
728 * Main context (global so we can free it on exit and use
729 * it for termination).
730 */
731static struct MainContext *mc;
732
733
734/**
735 * Task run on shutdown.
736 */
737static void
738shutdown_task (void *cls,
739 const struct GNUNET_SCHEDULER_TaskContext *tc)
740{
741 if (mc->fs != NULL)
742 {
743 GNUNET_FS_stop (mc->fs);
744 mc->fs = NULL;
745 }
746 EXTRACTOR_plugin_remove_all (mc->plugins);
747 mc->plugins = NULL;
748 if (mc->pnc != NULL)
749 {
750 GNUNET_PEERINFO_notify_cancel (mc->pnc);
751 mc->pnc = NULL;
752 }
753}
754
755
756/**
757 * Return handle for file-sharing operations.
758 * @return NULL on error
759 */
760struct GNUNET_FS_Handle *
761GNUNET_GTK_get_fs_handle ()
762{
763 return mc->fs;
764}
765
766
767/**
768 * Get LE plugin list.
769 */
770struct EXTRACTOR_PluginList *
771GNUNET_GTK_get_le_plugins ()
772{
773 return mc->plugins;
774}
775
776/**
777 * Get cfg.
778 */
779const struct GNUNET_CONFIGURATION_Handle *
780GNUNET_GTK_get_configuration (void)
781{
782 return mc->cfg;
783}
784
785
786/**
787 * Callback invoked if the application is supposed to exit.
788 */
789void
790GNUNET_GTK_quit_cb (GtkObject *object,
791 gpointer user_data)
792{
793 if (tray_icon != NULL)
794 {
795 g_object_unref (G_OBJECT (tray_icon));
796 tray_icon = NULL;
797 }
798 g_main_loop_quit (mc->gml);
799 GNUNET_SCHEDULER_add_now (&shutdown_task,
800 NULL);
801}
802
803
804/**
805 * Create an initialize a new builder based on the
806 * GNUnet-GTK glade file.
807 *
808 * @param filename name of the resource file to load
809 * @return NULL on error
810 */
811GtkBuilder *
812GNUNET_GTK_get_new_builder (const char *filename)
813{
814 char *glade_path;
815 GtkBuilder *ret;
816 GError *error;
817
818 ret = gtk_builder_new ();
819 gtk_builder_set_translation_domain (ret, "gnunet-gtk");
820 GNUNET_asprintf (&glade_path,
821 "%s%s",
822 GNUNET_GTK_get_data_dir (),
823 filename);
824 error = NULL;
825 if (0 == gtk_builder_add_from_file (ret, glade_path, &error))
826 {
827 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
828 _("Failed to load `%s': %s\n"),
829 glade_path,
830 error->message);
831 g_error_free (error);
832 GNUNET_free (glade_path);
833 return NULL;
834 }
835 gtk_builder_connect_signals (ret, NULL);
836 GNUNET_free (glade_path);
837 return ret;
838}
839
840
841/**
842 * We got a click on our tray icon. Toggle visibility of the main
843 * window.
844 */
845static void
846tray_icon_on_click(GtkStatusIcon *status_icon,
847 gpointer user_data)
848{
849 GtkWindow *main_window;
850
851 main_window = GTK_WINDOW (gtk_builder_get_object (mc->builder,
852 "GNUNET_GTK_main_window"));
853 if (gtk_window_is_active (main_window))
854 gtk_widget_hide (GTK_WIDGET (main_window));
855 else
856 gtk_window_present (main_window);
857}
858
859
860/**
861 * We got a right-click on the tray icon. Display the context
862 * menu (which should have a 'quit' button).
863 */
864static int
865tray_icon_on_menu(GtkWidget *widget,
866 GdkEvent *event,
867 gpointer user_data)
868{
869 GtkMenu *tray_menu;
870 GdkEventButton *event_button;
871 GtkBuilder *builder;
872
873 if (event->type == GDK_BUTTON_PRESS)
874 {
875 event_button = (GdkEventButton *) event;
876 if (event_button->button == 3)
877 {
878 builder = GNUNET_GTK_get_new_builder ("status_bar_menu.glade");
879 tray_menu = GTK_MENU (gtk_builder_get_object (builder,
880 "GNUNET_GTK_status_bar_popup_menu"));
881 gtk_menu_popup (tray_menu, NULL, NULL, NULL, NULL,
882 event_button->button, event_button->time);
883 g_object_unref (builder);
884 }
885 }
886 return FALSE;
887}
888
889
890/**
891 * Create our tray icon.
892 */
893static GtkStatusIcon *
894create_tray_icon() {
895 GtkStatusIcon *tray_icon;
896
897 tray_icon = gtk_status_icon_new();
898 g_signal_connect(G_OBJECT(tray_icon), "activate",
899 G_CALLBACK(tray_icon_on_click), NULL);
900 g_signal_connect (G_OBJECT(tray_icon),
901 "button_press_event",
902 G_CALLBACK(tray_icon_on_menu),
903 tray_icon);
904 gtk_status_icon_set_from_icon_name (tray_icon,
905 "gnunet-gtk");
906 gtk_status_icon_set_tooltip(tray_icon,
907 "gnunet-gtk");
908 gtk_status_icon_set_visible(tray_icon, TRUE);
909 return tray_icon;
910}
911
912
913/**
914 * Initialize GTK search path for icons.
915 */
916static void
917set_icon_search_path ()
918{
919 char *buf;
920
921 buf = GNUNET_GTK_installation_get_path (GNUNET_OS_IPK_ICONDIR);
922 gtk_icon_theme_append_search_path (gtk_icon_theme_get_default (), buf);
923 GNUNET_free (buf);
924}
925
926
927/**
928 * Search selected in 'file' menu. (from main_window_file_search.c)
929 */
930void
931GNUNET_GTK_main_menu_file_search_activate_cb (GtkWidget * dummy,
932 gpointer data);
933
934
935/**
936 * Add the tab with the 'new' icon for starting a search.
937 */
938static void
939add_new_tab ()
940{
941 GtkNotebook *notebook;
942 GtkWindow *sf;
943 gint pages;
944 GtkBuilder *builder;
945 GtkWidget *label;
946 GtkWidget *frame;
947
948 builder = GNUNET_GTK_get_new_builder ("main_tab_new_frame.glade");
949
950 /* load frame */
951 sf = GTK_WINDOW (gtk_builder_get_object (builder,
952 "_main_tab_new_frame"));
953 label = gtk_bin_get_child (GTK_BIN (sf));
954 gtk_widget_ref (label);
955 gtk_container_remove (GTK_CONTAINER (sf), label);
956 gtk_widget_destroy (GTK_WIDGET (sf));
957 g_object_unref (builder);
958 g_signal_connect(G_OBJECT(label), "clicked",
959 G_CALLBACK(GNUNET_GTK_main_menu_file_search_activate_cb), NULL);
960
961 notebook = GTK_NOTEBOOK (GNUNET_GTK_get_main_window_object ("GNUNET_GTK_main_window_notebook"));
962 pages = gtk_notebook_get_n_pages (notebook);
963 frame = gtk_label_new ("");
964 gtk_widget_show (frame);
965 gtk_notebook_append_page (notebook,
966 frame,
967 label);
968 gtk_notebook_set_current_page (notebook,
969 pages);
970 gtk_widget_show (GTK_WIDGET (notebook));
971}
972
973
974/**
975 * Actual main function run right after GNUnet's scheduler
976 * is initialized. Initializes up GTK and Glade.
977 */
978static void
979run (void *cls,
980 char *const *args,
981 const char *cfgfile,
982 const struct GNUNET_CONFIGURATION_Handle *cfg)
983{
984 int argc;
985 GtkWidget *main_window;
986
987 /* command-line processing */
988 argc = 0;
989 while (args[argc] != NULL) argc++;
990 gtk_init (&argc, (char ***) &args);
991 set_icon_search_path ();
992 setup_nls (cfg);
993
994 /* setup main context */
995 mc = GNUNET_malloc (sizeof (struct MainContext));
996 mc->builder = GNUNET_GTK_get_new_builder ("main-window.glade");
997 mc->rs = GNUNET_NETWORK_fdset_create ();
998 mc->ws = GNUNET_NETWORK_fdset_create ();
999 mc->gml = g_main_loop_new (NULL, TRUE);
1000 mc->gmc = g_main_loop_get_context (mc->gml);
1001 mc->cfg = cfg;
1002 if (mc->builder == NULL)
1003 return;
1004
1005#if WINDOWS
1006 mc->hEventRead = CreateEvent (NULL, TRUE, FALSE, NULL);
1007 mc->hEventReadReady = CreateEvent (NULL, TRUE, TRUE, NULL);
1008 mc->hEventWrite = CreateEvent (NULL, TRUE, FALSE, NULL);
1009 mc->hEventException = CreateEvent (NULL, TRUE, FALSE, NULL);
1010
1011 mc->hEventPipeWrite = CreateEvent (NULL, TRUE, TRUE, NULL);
1012
1013 mc->handles_read = GNUNET_CONTAINER_slist_create ();
1014 mc->handles_write = GNUNET_CONTAINER_slist_create ();
1015 mc->handles_except = GNUNET_CONTAINER_slist_create ();
1016 mc->read_array = NULL;
1017 mc->read_array_length = 0;
1018#endif
1019
1020 /* setup tray icon */
1021 tray_icon = create_tray_icon();
1022
1023 /* setup main window */
1024 main_window = GTK_WIDGET (gtk_builder_get_object (mc->builder,
1025 "GNUNET_GTK_main_window"));
1026 gtk_window_maximize (GTK_WINDOW (main_window));
1027
1028 /* initialize file-sharing */
1029 mc->plugins = EXTRACTOR_plugin_add_defaults (EXTRACTOR_OPTION_DEFAULT_POLICY);
1030 mc->fs = GNUNET_FS_start (cfg,
1031 "gnunet-gtk",
1032 &GNUNET_GTK_fs_event_handler,
1033 NULL,
1034 GNUNET_FS_FLAGS_NONE /* fixme later for persistence/probes */,
1035 /* set other options here later! */
1036 GNUNET_FS_OPTIONS_END);
1037 if (mc->fs != NULL)
1038 {
1039 add_new_tab ();
1040 }
1041 else
1042 {
1043 gtk_widget_hide (GTK_WIDGET (gtk_builder_get_object (mc->builder,
1044 "GNUNET_GTK_main_menu_file_create_pseudonym")));
1045 gtk_widget_hide (GTK_WIDGET (gtk_builder_get_object (mc->builder,
1046 "GNUNET_GTK_main_menu_file_advertise_pseudonym")));
1047 gtk_widget_hide (GTK_WIDGET (gtk_builder_get_object (mc->builder,
1048 "GNUNET_GTK_main_menu_file_publish")));
1049 gtk_widget_hide (GTK_WIDGET (gtk_builder_get_object (mc->builder,
1050 "GNUNET_GTK_main_menu_file_search")));
1051 gtk_widget_hide (GTK_WIDGET (gtk_builder_get_object (mc->builder,
1052 "GNUNET_GTK_main_menu_file_download_uri")));
1053 gtk_widget_hide (GTK_WIDGET (gtk_builder_get_object (mc->builder,
1054 "GNUNET_GTK_main_menu_file_open_gnunet_directory")));
1055 /* FIXME: set warning in status bar... */
1056 }
1057 mc->pnc = GNUNET_PEERINFO_notify (cfg,
1058 &GNUNET_GTK_peerinfo_processor,
1059 NULL);
1060 if (mc->pnc == NULL)
1061 {
1062 gtk_widget_hide (GTK_WIDGET (gtk_builder_get_object (mc->builder,
1063 "GNUNET_GTK_main_window_peerinfo_treeview")));
1064 gtk_widget_hide (GTK_WIDGET (gtk_builder_get_object (mc->builder,
1065 "GNUNET_GTK_main_menu_view_neighbours")));
1066 /* FIXME: set warning in status bar... */
1067 }
1068 /* make GUI visible */
1069 if (!tray_only)
1070 {
1071 gtk_widget_show (main_window);
1072 gtk_window_present (GTK_WINDOW (main_window));
1073 }
1074 /* start the event loop */
1075 GNUNET_assert (TRUE == g_main_context_acquire (mc->gmc));
1076 GNUNET_SCHEDULER_set_select (gnunet_gtk_select, mc);
1077}
1078
1079
1080/**
1081 * Get an object from the main window.
1082 *
1083 * @param name name of the object
1084 * @return NULL on error
1085 */
1086GObject *
1087GNUNET_GTK_get_main_window_object (const char *name)
1088{
1089 return gtk_builder_get_object (mc->builder, name);
1090}
1091
1092int
1093main (int argc, char *const *argv)
1094{
1095 static struct GNUNET_GETOPT_CommandLineOption options[] = {
1096 {'t', "tray", NULL,
1097 gettext_noop ("start in tray mode"), 0,
1098 &GNUNET_GETOPT_set_one, &tray_only},
1099 GNUNET_GETOPT_OPTION_END
1100 };
1101
1102 if (GNUNET_OK !=
1103 GNUNET_PROGRAM_run (argc, argv,
1104 "gnunet-gtk",
1105 "GTK GUI for GNUnet",
1106 options,
1107 &run, NULL))
1108 {
1109 free_context (mc);
1110 mc = NULL;
1111 return 1;
1112 }
1113 free_context (mc);
1114 mc = NULL;
1115 return 0;
1116}
1117
1118
1119/* end of gnunet-gtk.c */
diff --git a/src/main_window_adv_pseudonym.c b/src/main_window_adv_pseudonym.c
deleted file mode 100644
index 7a139332..00000000
--- a/src/main_window_adv_pseudonym.c
+++ /dev/null
@@ -1,587 +0,0 @@
1/*
2 This file is part of GNUnet
3 (C) 2005, 2006, 2010 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/main_window_adv_pseudonym.c
23 * @author Christian Grothoff
24 */
25#include "common.h"
26
27static GtkBuilder *builder;
28
29
30/**
31 * Canonicalize spelling of currently selected keyword.
32 */
33void
34GNUNET_GTK_advertise_pseudonym_keyword_list_normalize_button_clicked_cb ()
35{
36 GtkTreeView *tv;
37 GtkTreeSelection *sel;
38 GtkTreeModel *tm;
39 GtkTreeIter iter;
40 gchar *value;
41 struct GNUNET_FS_Uri *uri;
42 struct GNUNET_FS_Uri *nuri;
43 char *nvalue;
44 char *emsg;
45
46 tv = GTK_TREE_VIEW (gtk_builder_get_object (builder,
47 "GNUNET_GTK_advertise_pseudonym_keyword_list_tree_view"));
48 sel = gtk_tree_view_get_selection (tv);
49 if (TRUE != gtk_tree_selection_get_selected (sel, &tm, &iter))
50 {
51 GNUNET_break (0);
52 return;
53 }
54 gtk_tree_model_get (tm, &iter,
55 0, &value,
56 -1);
57 emsg = NULL;
58 uri = GNUNET_FS_uri_ksk_create (value, &emsg);
59 if (uri == NULL)
60 {
61 GNUNET_break (0);
62 GNUNET_free (emsg);
63 g_free (value);
64 return;
65 }
66 nuri = GNUNET_FS_uri_ksk_canonicalize (uri);
67 nvalue = GNUNET_FS_uri_ksk_to_string_fancy (nuri);
68 gtk_list_store_set (GTK_LIST_STORE (tm), &iter,
69 0, nvalue,
70 -1);
71 GNUNET_FS_uri_destroy (nuri);
72 GNUNET_FS_uri_destroy (uri);
73 GNUNET_free (nvalue);
74 g_free (value);
75}
76
77
78/**
79 * Remove the currently selected keyword from the list.
80 */
81void
82GNUNET_GTK_advertise_pseudonym_keyword_list_del_button_clicked_cb ()
83{
84 GtkTreeView *tv;
85 GtkTreeSelection *sel;
86 GtkTreeModel *tm;
87 GtkTreeIter iter;
88
89 tv = GTK_TREE_VIEW (gtk_builder_get_object (builder,
90 "GNUNET_GTK_advertise_pseudonym_keyword_list_tree_view"));
91 sel = gtk_tree_view_get_selection (tv);
92 if (TRUE != gtk_tree_selection_get_selected (sel, &tm, &iter))
93 {
94 GNUNET_break (0);
95 return;
96 }
97 gtk_list_store_remove (GTK_LIST_STORE (tm),
98 &iter);
99}
100
101
102/**
103 * Add keyword from entry line to keyword list.
104 */
105void
106GNUNET_GTK_advertise_pseudonym_keyword_list_add_button_clicked_cb ()
107{
108 const char *keyword;
109 GtkEntry *entry;
110 GtkListStore *ls;
111 GtkTreeIter iter;
112
113 ls = GTK_LIST_STORE (gtk_builder_get_object (builder,
114 "GNUNET_GTK_keyword_list_store"));
115 entry = GTK_ENTRY (gtk_builder_get_object (builder,
116 "GNUNET_GTK_advertise_pseudonym_keyword_entry"));
117 keyword = gtk_entry_get_text (entry);
118 if (strlen (keyword) > 0)
119 gtk_list_store_insert_with_values (ls, &iter, G_MAXINT, 0, keyword, -1);
120 gtk_entry_set_text (entry, "");
121}
122
123
124/**
125 * Update sensitivity of keyword add button.
126 */
127void
128GNUNET_GTK_advertise_pseudonym_keyword_entry_changed_cb ()
129{
130 const char *keyword;
131 GtkEntry *entry;
132 GtkWidget *button;
133
134 button = GTK_WIDGET (gtk_builder_get_object (builder,
135 "GNUNET_GTK_advertise_pseudonym_keyword_list_add_button"));
136 entry = GTK_ENTRY (gtk_builder_get_object (builder,
137 "GNUNET_GTK_advertise_pseudonym_keyword_entry"));
138 keyword = gtk_entry_get_text (entry);
139 gtk_widget_set_sensitive (button,
140 (strlen (keyword) > 0) ? TRUE : FALSE);
141}
142
143/**
144 * Update sensitivity of metadata delete button.
145 */
146static void
147metadata_selection_changed_cb (GtkTreeSelection *ts,
148 gpointer user_data)
149{
150 GtkTreeView *tv;
151 GtkTreeSelection *sel;
152 GtkWidget *button;
153
154 tv = GTK_TREE_VIEW (gtk_builder_get_object (builder,
155 "GNUNET_GTK_advertise_pseudonym_metadata_tree_view"));
156 sel = gtk_tree_view_get_selection (tv);
157 button = GTK_WIDGET (gtk_builder_get_object (builder,
158 "GNUNET_GTK_advertise_pseudonym_metadata_delete_button"));
159 gtk_widget_set_sensitive (button,
160 gtk_tree_selection_get_selected (sel, NULL, NULL));
161}
162
163
164/**
165 * Update sensitivity of keyword delete and normalize button.
166 */
167static void
168keyword_selection_changed_cb (GtkTreeSelection *ts,
169 gpointer user_data)
170{
171 GtkTreeView *tv;
172 GtkTreeSelection *sel;
173 GtkWidget *button;
174
175 tv = GTK_TREE_VIEW (gtk_builder_get_object (builder,
176 "GNUNET_GTK_advertise_pseudonym_keyword_list_tree_view"));
177 sel = gtk_tree_view_get_selection (tv);
178 button = GTK_WIDGET (gtk_builder_get_object (builder,
179 "GNUNET_GTK_advertise_pseudonym_keyword_list_del_button"));
180
181 gtk_widget_set_sensitive (button,
182 gtk_tree_selection_get_selected (sel, NULL, NULL));
183 button = GTK_WIDGET (gtk_builder_get_object (builder,
184 "GNUNET_GTK_advertise_pseudonym_keyword_list_normalize_button"));
185 gtk_widget_set_sensitive (button,
186 gtk_tree_selection_get_selected (sel, NULL, NULL));
187}
188
189
190/**
191 * Update sensitivity of metadata add button.
192 */
193void
194GNUNET_GTK_advertise_pseudonym_metadata_value_entry_changed_cb ()
195{
196 GtkTreeView *tv;
197 GtkTreeSelection *sel;
198 const char *value;
199 GtkEntry *entry;
200 GtkWidget *button;
201
202 entry = GTK_ENTRY (gtk_builder_get_object (builder,
203 "GNUNET_GTK_advertise_pseudonym_metadata_value_entry"));
204 value = gtk_entry_get_text (entry);
205 tv = GTK_TREE_VIEW (gtk_builder_get_object (builder,
206 "GNUNET_GTK_advertise_pseudonym_metadata_type_tree_view"));
207 sel = gtk_tree_view_get_selection (tv);
208 button = GTK_WIDGET (gtk_builder_get_object (builder,
209 "GNUNET_GTK_advertise_pseudonym_metadata_add_button"));
210 gtk_widget_set_sensitive (button,
211 (strlen (value) > 0)
212 ? gtk_tree_selection_get_selected (sel, NULL, NULL)
213 : FALSE);
214}
215
216
217/**
218 * Add keyword to keyword list.
219 */
220void
221GNUNET_GTK_advertise_pseudonym_keyword_entry_activate_cb ()
222{
223 GNUNET_GTK_advertise_pseudonym_keyword_list_add_button_clicked_cb ();
224}
225
226
227void
228GNUNET_GTK_advertise_pseudonym_metadata_preview_file_chooser_button_file_set_cb ()
229{
230 GNUNET_break (0);
231}
232
233/**
234 * Delete currently selected item from meta data list.
235 */
236void
237GNUNET_GTK_advertise_pseudonym_metadata_delete_button_clicked_cb()
238{
239 GtkTreeView *tv;
240 GtkTreeSelection *sel;
241 GtkTreeModel *tm;
242 GtkTreeIter iter;
243
244 tv = GTK_TREE_VIEW (gtk_builder_get_object (builder,
245 "GNUNET_GTK_advertise_pseudonym_metadata_tree_view"));
246 sel = gtk_tree_view_get_selection (tv);
247 if (TRUE != gtk_tree_selection_get_selected (sel, &tm, &iter))
248 {
249 GNUNET_break (0);
250 return;
251 }
252 gtk_list_store_remove (GTK_LIST_STORE (tm),
253 &iter);
254}
255
256
257/**
258 * Add metadata to metadata list.
259 */
260void
261GNUNET_GTK_advertise_pseudonym_metadata_add_button_clicked_cb ()
262{
263 const char *value;
264 char *avalue;
265 const char *ivalue;
266 GtkEntry *entry;
267 GtkListStore *ls;
268 GtkTreeModel *tm;
269 GtkTreeView *tv;
270 GtkTreeSelection *sel;
271 GtkTreeIter iter;
272 guint type;
273 size_t slen;
274 char *pos;
275
276 entry = GTK_ENTRY (gtk_builder_get_object (builder,
277 "GNUNET_GTK_advertise_pseudonym_metadata_value_entry"));
278 value = gtk_entry_get_text (entry);
279 if ((value == NULL) || (strlen (value) == 0))
280 {
281 GNUNET_break (0);
282 return;
283 }
284 tv = GTK_TREE_VIEW (gtk_builder_get_object (builder,
285 "GNUNET_GTK_advertise_pseudonym_metadata_type_tree_view"));
286 tm = gtk_tree_view_get_model (tv);
287 sel = gtk_tree_view_get_selection (tv);
288 if (TRUE != gtk_tree_selection_get_selected (sel,
289 &tm,
290 &iter))
291 {
292 GNUNET_break (0);
293 return;
294 }
295 gtk_tree_model_get (tm,
296 &iter,
297 1, &type, -1);
298 ls = GTK_LIST_STORE (gtk_builder_get_object (builder,
299 "GNUNET_GTK_meta_data_list_store"));
300 if ( (type == EXTRACTOR_METATYPE_FILENAME) &&
301 (value[strlen(value)-1] != '/') )
302 {
303 GNUNET_asprintf (&avalue,
304 "%s/",
305 value);
306 /* if user typed '\' instead of '/', change it! */
307 slen = strlen (avalue);
308 while ( (slen > 1) &&
309 (avalue[slen-2] == '\\') )
310 {
311 avalue[slen-2] = '/';
312 avalue[slen-1] = '\0';
313 slen--;
314 }
315 while (NULL != (pos = strstr (avalue, "\\")))
316 *pos = '/';
317 /* remove '../' everywhere */
318 while (NULL != (pos = strstr (avalue, "../")))
319 {
320 pos[0] = '_';
321 pos[1] = '_';
322 pos[2] = '_';
323 }
324 ivalue = avalue;
325 }
326 else
327 {
328 ivalue = value;
329 avalue = NULL;
330 }
331
332 gtk_list_store_insert_with_values (ls, &iter, G_MAXINT,
333 0, type,
334 1, (guint) EXTRACTOR_METAFORMAT_UTF8,
335 2, EXTRACTOR_metatype_to_string (type),
336 3, ivalue,
337 -1);
338 GNUNET_free_non_null (avalue);
339 gtk_entry_set_text (GTK_ENTRY (entry), "");
340}
341
342
343/**
344 * Callback with information about local (!) namespaces.
345 * Contains the names of the local namespace and the global
346 * ID. Adds the to the list store.
347 *
348 * @param cls closure, the list store.
349 * @param name human-readable identifier of the namespace
350 * @param id hash identifier for the namespace
351 */
352static void
353add_to_list (void *cls,
354 const char *name,
355 const GNUNET_HashCode *id)
356{
357 GtkListStore *ls = cls;
358 GtkTreeIter iter;
359
360 gtk_list_store_insert_with_values (ls,
361 &iter,
362 -1,
363 0, name,
364 1, GNUNET_FS_namespace_create (GNUNET_GTK_get_fs_handle (),
365 name),
366 -1);
367
368}
369
370
371static void
372selection_changed_cb (GtkTreeSelection *ts,
373 gpointer user_data)
374{
375 GtkTreeIter iter;
376 GtkWidget *ok_button;
377
378 ok_button = GTK_WIDGET (gtk_builder_get_object (builder,
379 "GNUNET_GTK_select_pseudonym_ok_button"));
380 if (TRUE == gtk_tree_selection_get_selected (ts, NULL, &iter))
381 gtk_widget_set_sensitive (ok_button, TRUE);
382 else
383 gtk_widget_set_sensitive (ok_button, FALSE);
384}
385
386
387/**
388 * Advertise pseudonym selected.
389 */
390void
391GNUNET_GTK_main_menu_file_advertise_pseudonym_activate_cb (GtkWidget * dummy,
392 gpointer data)
393{
394 GtkWidget *ad;
395 struct GNUNET_FS_Namespace *ns;
396 struct GNUNET_FS_Namespace *nso;
397 GtkListStore *ls;
398 GtkTreeView *tv;
399 GtkTreeIter iter;
400 GtkTreeSelection *sel;
401 GtkTreeModel *tm;
402 GtkSpinButton *sb;
403 struct GNUNET_FS_BlockOptions bo;
404 struct GNUNET_FS_Uri *nxt;
405 struct GNUNET_FS_Uri *mrg;
406 struct GNUNET_FS_Uri *uri;
407 struct GNUNET_CONTAINER_MetaData *nm;
408 const char *root;
409 char *value;
410 guint ntype;
411 guint nformat;
412 guint type;
413 guint max_type;
414
415 builder = GNUNET_GTK_get_new_builder ("select_pseudonym_dialog.glade");
416 if (builder == NULL)
417 {
418 GNUNET_break (0);
419 return;
420 }
421 ad = GTK_WIDGET (gtk_builder_get_object (builder,
422 "GNUNET_GTK_select_pseudonym_dialog"));
423 ls = GTK_LIST_STORE (gtk_builder_get_object (builder,
424 "GNUNET_GTK_select_pseudonym_liststore"));
425 GNUNET_FS_namespace_list (GNUNET_GTK_get_fs_handle (),
426 &add_to_list,
427 ls);
428 tv = GTK_TREE_VIEW (gtk_builder_get_object (builder,
429 "GNUNET_GTK_select_pseudonym_tree_view"));
430 sel = gtk_tree_view_get_selection (tv);
431 g_signal_connect(G_OBJECT(sel), "changed",
432 G_CALLBACK(selection_changed_cb), NULL);
433 if (GTK_RESPONSE_OK != gtk_dialog_run (GTK_DIALOG (ad)))
434 {
435 gtk_widget_destroy (ad);
436 g_object_unref (G_OBJECT (builder));
437 builder = NULL;
438 return;
439 }
440 GNUNET_assert (TRUE == gtk_tree_selection_get_selected (sel,
441 &tm,
442 &iter));
443 gtk_tree_model_get (tm,
444 &iter,
445 1, &ns,
446 -1);
447 /* free all namespaces from list store except "ns" */
448 if (TRUE ==
449 gtk_tree_model_get_iter_first (tm, &iter))
450 {
451 do
452 {
453 gtk_tree_model_get (tm, &iter,
454 1, &nso,
455 -1);
456 if (ns != nso)
457 GNUNET_FS_namespace_delete (nso, GNUNET_NO);
458 }
459 while (TRUE == gtk_tree_model_iter_next (tm, &iter));
460 }
461 gtk_widget_destroy (ad);
462 g_object_unref (G_OBJECT (builder));
463 builder = NULL;
464
465
466 builder = GNUNET_GTK_get_new_builder ("advertise_pseudonym_dialog.glade");
467 if (builder == NULL)
468 {
469 GNUNET_break (0);
470 return;
471 }
472 GNUNET_GTK_setup_expiration_year_adjustment (builder);
473 ad = GTK_WIDGET (gtk_builder_get_object (builder,
474 "GNUNET_GTK_advertise_pseudonym_dialog"));
475 ls = GTK_LIST_STORE (gtk_builder_get_object (builder,
476 "GNUNET_GTK_metatype_list_store"));
477 max_type = EXTRACTOR_metatype_get_max ();
478 type = 1;
479 while (type < max_type - 1)
480 {
481 gtk_list_store_insert_with_values (ls, &iter, G_MAXINT,
482 0, EXTRACTOR_metatype_to_string (type),
483 1, type,
484 2, EXTRACTOR_metatype_to_description (type),
485 -1);
486 type++;
487 }
488 tv = GTK_TREE_VIEW (gtk_builder_get_object (builder,
489 "GNUNET_GTK_advertise_pseudonym_metadata_type_tree_view"));
490 sel = gtk_tree_view_get_selection (tv);
491 g_signal_connect(G_OBJECT(sel), "changed",
492 G_CALLBACK(GNUNET_GTK_advertise_pseudonym_metadata_value_entry_changed_cb), NULL);
493
494 tv = GTK_TREE_VIEW (gtk_builder_get_object (builder,
495 "GNUNET_GTK_advertise_pseudonym_metadata_tree_view"));
496 sel = gtk_tree_view_get_selection (tv);
497 g_signal_connect(G_OBJECT(sel), "changed",
498 G_CALLBACK(metadata_selection_changed_cb), NULL);
499
500 tv = GTK_TREE_VIEW (gtk_builder_get_object (builder,
501 "GNUNET_GTK_advertise_pseudonym_keyword_list_tree_view"));
502 sel = gtk_tree_view_get_selection (tv);
503 g_signal_connect(G_OBJECT(sel), "changed",
504 G_CALLBACK(keyword_selection_changed_cb), NULL);
505 if (GTK_RESPONSE_OK != gtk_dialog_run (GTK_DIALOG (ad)))
506 {
507 gtk_widget_destroy (ad);
508 g_object_unref (G_OBJECT (builder));
509 builder = NULL;
510 return;
511 }
512 /* get keywords from list store */
513 nxt = NULL;
514 mrg = NULL;
515 uri = NULL;
516 tm = GTK_TREE_MODEL (gtk_builder_get_object (builder,
517 "GNUNET_GTK_keyword_list_store"));
518 if (TRUE ==
519 gtk_tree_model_get_iter_first (tm, &iter))
520 {
521 do
522 {
523 gtk_tree_model_get (tm, &iter,
524 0, &value,
525 -1);
526 nxt = GNUNET_FS_uri_ksk_create_from_args (1, (const char**) &value);
527 mrg = GNUNET_FS_uri_ksk_merge (nxt, uri);
528 GNUNET_FS_uri_destroy (nxt);
529 if (NULL != uri)
530 GNUNET_FS_uri_destroy (uri);
531 uri = mrg;
532 g_free (value);
533 }
534 while (TRUE == gtk_tree_model_iter_next (tm, &iter));
535 }
536 /* get meta */
537 nm = GNUNET_CONTAINER_meta_data_create ();
538 tm = GTK_TREE_MODEL (gtk_builder_get_object (builder,
539 "GNUNET_GTK_meta_data_list_store"));
540 if (TRUE ==
541 gtk_tree_model_get_iter_first (tm, &iter))
542 {
543 do
544 {
545 gtk_tree_model_get (tm, &iter,
546 0, &ntype,
547 1, &nformat,
548 3, &value,
549 -1);
550 GNUNET_CONTAINER_meta_data_insert (nm,
551 "<user>",
552 ntype,
553 nformat,
554 "text/plain",
555 value,
556 strlen (value)+1);
557 g_free (value);
558 }
559 while (TRUE == gtk_tree_model_iter_next (tm, &iter));
560 }
561 bo.anonymity_level = gtk_spin_button_get_value (GTK_SPIN_BUTTON (gtk_builder_get_object (builder,
562 "GNUNET_GTK_advertise_pseudonym_anonymity_spin_button")));
563 bo.content_priority = gtk_spin_button_get_value (GTK_SPIN_BUTTON (gtk_builder_get_object (builder,
564 "GNUNET_GTK_advertise_pseudonym_priority_spin_button")));
565 sb = GTK_SPIN_BUTTON (gtk_builder_get_object (builder,
566 "GNUNET_GTK_advertise_pseudonym_expiration_year_spin_button"));
567 bo.expiration_time = GNUNET_GTK_get_expiration_time (sb);
568 root = gtk_entry_get_text (GTK_ENTRY (gtk_builder_get_object (builder,
569 "GNUNET_GTK_advertise_pseudonym_root_entry")));
570 GNUNET_FS_namespace_advertise (GNUNET_GTK_get_fs_handle (),
571 uri,
572 ns,
573 nm,
574 &bo,
575 root,
576 NULL, NULL);
577 GNUNET_FS_namespace_delete (ns, GNUNET_NO);
578 GNUNET_CONTAINER_meta_data_destroy (nm);
579 if (NULL != uri)
580 GNUNET_FS_uri_destroy (uri);
581 gtk_widget_destroy (ad);
582 g_object_unref (G_OBJECT (builder));
583 builder = NULL;
584}
585
586
587/* end of main_window_adv_pseudonym.c */
diff --git a/src/main_window_create_pseudonym.c b/src/main_window_create_pseudonym.c
deleted file mode 100644
index 4224e6c4..00000000
--- a/src/main_window_create_pseudonym.c
+++ /dev/null
@@ -1,64 +0,0 @@
1/*
2 This file is part of GNUnet
3 (C) 2005, 2006, 2010 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/main_window_create_pseudonym.c
23 * @author Christian Grothoff
24 *
25 */
26#include "common.h"
27
28/**
29 */
30void
31GNUNET_GTK_main_menu_create_pseudonym_activate_cb (GtkWidget * dummy,
32 gpointer data)
33{
34 GtkWidget *ad;
35 GtkBuilder *builder;
36 const char *name;
37 struct GNUNET_FS_Namespace *ns;
38
39 builder = GNUNET_GTK_get_new_builder ("create_namespace_dialog.glade");
40 if (builder == NULL)
41 {
42 GNUNET_break (0);
43 return;
44 }
45 ad = GTK_WIDGET (gtk_builder_get_object (builder,
46 "GNUNET_GTK_create_namespace_dialog"));
47 if (GTK_RESPONSE_OK != gtk_dialog_run (GTK_DIALOG (ad)))
48 {
49 gtk_widget_destroy (ad);
50 g_object_unref (G_OBJECT (builder));
51 return;
52 }
53 name = gtk_entry_get_text (GTK_ENTRY (gtk_builder_get_object (builder,
54 "GNUNET_GTK_create_namespace_name_entry")));
55 /* FIXME: show busy dialog while doing key creation */
56 ns = GNUNET_FS_namespace_create (GNUNET_GTK_get_fs_handle (),
57 name);
58 GNUNET_FS_namespace_delete (ns, GNUNET_NO);
59 gtk_widget_destroy (ad);
60 g_object_unref (G_OBJECT (builder));
61}
62
63
64/* end of main_window_create_pseudonym.c */
diff --git a/src/main_window_file_download.c b/src/main_window_file_download.c
deleted file mode 100644
index b38bf513..00000000
--- a/src/main_window_file_download.c
+++ /dev/null
@@ -1,130 +0,0 @@
1/*
2 This file is part of GNUnet
3 (C) 2005, 2006, 2010 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/main_window_file_download.c
23 * @author Christian Grothoff
24 */
25#include "common.h"
26#include "download.h"
27
28
29static GtkBuilder *builder;
30
31void
32GNUNET_GTK_open_url_dialog_url_entry_changed_cb (GtkEditable *editable,
33 gpointer user_data)
34{
35 struct GNUNET_FS_Uri *uri;
36 char *perr;
37 const char *uris;
38
39 perr = NULL;
40 uris = gtk_entry_get_text (GTK_ENTRY (gtk_builder_get_object (builder,
41 "GNUNET_GTK_open_url_dialog_url_entry")));
42 if (uris != NULL)
43 uri = GNUNET_FS_uri_parse (uris, &perr);
44 else
45 uri = NULL;
46 gtk_widget_set_sensitive (GTK_WIDGET (gtk_builder_get_object (builder,
47 "GNUNET_GTK_open_url_dialog_execute_button")),
48 (uri == NULL) ? FALSE : TRUE);
49 if (uri != NULL)
50 GNUNET_FS_uri_destroy (uri);
51 else
52 GNUNET_free_non_null (perr);
53}
54
55
56/**
57 * User selected "Open URI" in main window.
58 */
59void
60GNUNET_GTK_main_menu_file_download_uri_activate_cb (GtkWidget * dummy,
61 gpointer data)
62{
63 GtkWidget *ad;
64 const char *uris;
65 uint32_t anonymity;
66 struct GNUNET_FS_Uri *uri;
67 char *perr;
68 struct DownloadContext *dc;
69
70 GNUNET_assert (builder == NULL);
71 builder = GNUNET_GTK_get_new_builder ("open_url_dialog.glade");
72 if (builder == NULL)
73 {
74 GNUNET_break (0);
75 return;
76 }
77 ad = GTK_WIDGET (gtk_builder_get_object (builder,
78 "GNUNET_GTK_open_url_dialog"));
79 if (GTK_RESPONSE_OK != gtk_dialog_run (GTK_DIALOG (ad)))
80 {
81 gtk_widget_destroy (ad);
82 g_object_unref (G_OBJECT (builder));
83 builder = NULL;
84 fprintf (stderr,
85 "Dialog closed!\n");
86 return;
87 }
88 uris = gtk_entry_get_text (GTK_ENTRY (gtk_builder_get_object (builder,
89 "GNUNET_GTK_open_url_dialog_url_entry")));
90 anonymity = gtk_spin_button_get_value (GTK_SPIN_BUTTON (gtk_builder_get_object (builder,
91 "GNUNET_GTK_open_url_dialog_anonymity_spin_button")));
92 uri = GNUNET_FS_uri_parse (uris, &perr);
93 gtk_widget_destroy (ad);
94 g_object_unref (G_OBJECT (builder));
95 builder = NULL;
96 if (uri == NULL)
97 {
98 GNUNET_free (perr);
99 /* Why was "execute" button sensitive!? */
100 GNUNET_break (0);
101 return;
102 }
103 if (GNUNET_FS_uri_test_sks (uri) ||
104 GNUNET_FS_uri_test_ksk (uri))
105 {
106 fprintf (stderr,
107 "Starting search!\n");
108 GNUNET_break (NULL !=
109 GNUNET_FS_search_start (GNUNET_GTK_get_fs_handle (),
110 uri,
111 anonymity,
112 GNUNET_FS_SEARCH_OPTION_NONE,
113 NULL));
114 GNUNET_FS_uri_destroy (uri);
115 return;
116 }
117 if (GNUNET_FS_uri_test_chk (uri) ||
118 GNUNET_FS_uri_test_loc (uri))
119 {
120 dc = GNUNET_malloc (sizeof (struct DownloadContext));
121 dc->uri = uri;
122 dc->anonymity = anonymity;
123 GNUNET_GTK_open_download_as_dialog (dc);
124 return;
125 }
126 GNUNET_break (0);
127 GNUNET_FS_uri_destroy (uri);
128}
129
130/* end of main_window_file_download.c */
diff --git a/src/main_window_file_publish.c b/src/main_window_file_publish.c
deleted file mode 100644
index c7ba8cd1..00000000
--- a/src/main_window_file_publish.c
+++ /dev/null
@@ -1,1932 +0,0 @@
1/*
2 This file is part of GNUnet
3 (C) 2005, 2006, 2010 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/main_window_file_publish.c
23 * @author Christian Grothoff
24 */
25#include "common.h"
26#include "edit_publish_dialog.h"
27#include <gnunet/gnunet_util_lib.h>
28
29#define MARKER_DIR_FILE_SIZE "-"
30
31/**
32 * Builder used for the master publish dialog.
33 */
34static GtkBuilder *master_builder;
35
36
37/**
38 * Check if two GtkTreeIters refer to the same element.
39 *
40 * @param tm tree model of the iterators
41 * @param i1 first iterator
42 * @param i2 second iterator
43 * @return GNUNET_YES if they are equal
44 */
45static int
46gtk_tree_iter_equals (GtkTreeModel *tm,
47 GtkTreeIter *i1,
48 GtkTreeIter *i2)
49{
50 GtkTreePath *p1;
51 GtkTreePath *p2;
52 int ret;
53
54 p1 = gtk_tree_model_get_path (tm, i1);
55 p2 = gtk_tree_model_get_path (tm, i2);
56 ret = gtk_tree_path_compare (p1, p2);
57 gtk_tree_path_free (p1);
58 gtk_tree_path_free (p2);
59 return (0 == ret) ? GNUNET_YES : GNUNET_NO;
60}
61
62
63/**
64 * Update selectivity in the master dialog.
65 */
66static void
67update_selectivity ()
68{
69 GtkTreeView *tv;
70 GtkTreeModel *tm;
71 GtkTreeModel *ptm;
72 GtkTreeSelection *sel;
73 GtkTreeIter iter;
74 GtkTreeIter parent;
75 GtkTreeIter pred;
76 GtkWidget *up_button;
77 GtkWidget *down_button;
78 GtkWidget *left_button;
79 GtkWidget *right_button;
80 GtkWidget *delete_button;
81 GtkWidget *edit_button;
82 GtkWidget *execute_button;
83 int is_dir;
84 struct GNUNET_FS_FileInformation *fip;
85 int ns_ok;
86 gchar *namespace_id;
87
88 tm = GTK_TREE_MODEL (gtk_builder_get_object (master_builder,
89 "GNUNET_GTK_file_sharing_publishing_tree_store"));
90 tv = GTK_TREE_VIEW (gtk_builder_get_object (master_builder,
91 "GNUNET_GTK_master_publish_dialog_pseudonym_tree_view"));
92 sel = gtk_tree_view_get_selection (tv);
93 ns_ok = GNUNET_YES;
94 if (TRUE == gtk_tree_selection_get_selected (sel, &ptm, &iter))
95 {
96 gtk_tree_model_get (ptm,
97 &iter,
98 2, &namespace_id,
99 -1);
100 if (namespace_id == NULL)
101 ns_ok = GNUNET_NO;
102 else
103 g_free (namespace_id);
104 }
105 up_button = GTK_WIDGET (gtk_builder_get_object (master_builder,
106 "GNUNET_GTK_master_publish_dialog_up_button"));
107 down_button = GTK_WIDGET (gtk_builder_get_object (master_builder,
108 "GNUNET_GTK_master_publish_dialog_down_button"));
109 left_button = GTK_WIDGET (gtk_builder_get_object (master_builder,
110 "GNUNET_GTK_master_publish_dialog_left_button"));
111 right_button = GTK_WIDGET (gtk_builder_get_object (master_builder,
112 "GNUNET_GTK_master_publish_dialog_right_button"));
113 delete_button = GTK_WIDGET (gtk_builder_get_object (master_builder,
114 "GNUNET_GTK_master_publish_dialog_delete_button"));
115 edit_button = GTK_WIDGET (gtk_builder_get_object (master_builder,
116 "GNUNET_GTK_master_publish_dialog_edit_button"));
117 execute_button = GTK_WIDGET (gtk_builder_get_object (master_builder,
118 "GNUNET_GTK_master_publish_dialog_execute_button"));
119 tv = GTK_TREE_VIEW (gtk_builder_get_object (master_builder,
120 "GNUNET_GTK_master_publish_dialog_file_information_tree_view"));
121 sel = gtk_tree_view_get_selection (tv);
122 tm = gtk_tree_view_get_model (tv);
123 if ( (gtk_tree_model_get_iter_first (tm, &iter)) &&
124 (ns_ok == GNUNET_YES) )
125 gtk_widget_set_sensitive (execute_button, TRUE);
126 else
127 gtk_widget_set_sensitive (execute_button, FALSE);
128 if (TRUE != gtk_tree_selection_get_selected (sel,
129 &tm,
130 &iter))
131 {
132 gtk_widget_set_sensitive (up_button, FALSE);
133 gtk_widget_set_sensitive (down_button, FALSE);
134 gtk_widget_set_sensitive (left_button, FALSE);
135 gtk_widget_set_sensitive (right_button, FALSE);
136 gtk_widget_set_sensitive (delete_button, FALSE);
137 gtk_widget_set_sensitive (edit_button, FALSE);
138 return;
139 }
140 gtk_widget_set_sensitive (delete_button, TRUE);
141 gtk_widget_set_sensitive (edit_button, TRUE);
142
143 /* now figure out which move operations are currently legal */
144 GNUNET_assert (TRUE == gtk_tree_selection_get_selected (sel, NULL, &iter));
145 if (TRUE == gtk_tree_model_iter_next (tm, &iter))
146 {
147 gtk_widget_set_sensitive (down_button, TRUE);
148 }
149 else
150 {
151 gtk_widget_set_sensitive (down_button, FALSE);
152 }
153 GNUNET_assert (TRUE == gtk_tree_selection_get_selected (sel, NULL, &iter));
154 if (TRUE == gtk_tree_model_iter_parent (tm, &parent, &iter))
155 {
156 gtk_widget_set_sensitive (left_button, TRUE);
157 GNUNET_assert (TRUE ==
158 gtk_tree_model_iter_children (tm, &pred, &parent));
159 }
160 else
161 {
162 gtk_widget_set_sensitive (left_button, FALSE);
163 GNUNET_assert (TRUE ==
164 gtk_tree_model_get_iter_first (tm, &pred));
165 }
166 /* iterate over 'next' of pred to find out if our
167 predecessor is a directory! */
168 is_dir = GNUNET_SYSERR;
169 while (GNUNET_YES != gtk_tree_iter_equals (tm, &pred, &iter))
170 {
171 gtk_tree_model_get (tm, &pred,
172 5, &fip, -1);
173 is_dir = GNUNET_FS_file_information_is_directory (fip);
174 GNUNET_assert (TRUE == gtk_tree_model_iter_next (tm, &pred));
175 }
176 if (GNUNET_YES == is_dir)
177 {
178 gtk_widget_set_sensitive (right_button, TRUE);
179 }
180 else
181 {
182 gtk_widget_set_sensitive (right_button, FALSE);
183 }
184 if (GNUNET_SYSERR != is_dir)
185 {
186 gtk_widget_set_sensitive (up_button, TRUE);
187 }
188 else
189 {
190 gtk_widget_set_sensitive (up_button, FALSE);
191 }
192}
193
194
195/**
196 * Add a file to the tree model.
197 *
198 * @param filename file to add
199 * @param bo block options to use
200 * @param do_index should we index or insert?
201 * @param iter parent entry, or NULL for top-level addition
202 */
203static void
204add_file_at_iter (const char *filename,
205 const struct GNUNET_FS_BlockOptions *bo,
206 int do_index,
207 GtkTreeIter *iter)
208{
209 struct GNUNET_FS_FileInformation *fi;
210 GtkTreeRowReference *row_reference;
211 GtkTreePath *path;
212 uint64_t file_size;
213 const char *short_fn;
214 struct GNUNET_CONTAINER_MetaData *meta;
215 struct GNUNET_FS_Uri *ksk_uri;
216 GtkTreeStore *ts;
217 GtkTreeIter pos;
218 char *file_size_fancy;
219 const char *ss;
220 struct stat sbuf;
221
222 if (0 != STAT (filename, &sbuf))
223 return;
224 if (S_ISDIR (sbuf.st_mode))
225 {
226 file_size = 0;
227 }
228 else
229 {
230 if (GNUNET_OK !=
231 GNUNET_DISK_file_size (filename,
232 &file_size,
233 GNUNET_YES))
234 {
235 GNUNET_break (0);
236 return;
237 }
238 }
239 ts = GTK_TREE_STORE (gtk_builder_get_object (master_builder,
240 "GNUNET_GTK_file_sharing_publishing_tree_store"));
241
242 meta = GNUNET_CONTAINER_meta_data_create ();
243 GNUNET_FS_meta_data_extract_from_file (meta,
244 filename,
245 GNUNET_GTK_get_le_plugins());
246 GNUNET_CONTAINER_meta_data_delete (meta,
247 EXTRACTOR_METATYPE_FILENAME,
248 NULL, 0);
249 short_fn = filename;
250 while (NULL != (ss = strstr (short_fn, DIR_SEPARATOR_STR)))
251 short_fn = 1 + ss;
252 GNUNET_CONTAINER_meta_data_insert (meta,
253 "<gnunet-gtk>",
254 EXTRACTOR_METATYPE_FILENAME,
255 EXTRACTOR_METAFORMAT_UTF8,
256 "text/plain",
257 short_fn,
258 strlen(short_fn)+1);
259 ksk_uri = GNUNET_FS_uri_ksk_create_from_meta_data (meta);
260 gtk_tree_store_insert_before (ts,
261 &pos,
262 iter,
263 NULL);
264 path = gtk_tree_model_get_path (GTK_TREE_MODEL (ts),
265 &pos);
266 row_reference = gtk_tree_row_reference_new (GTK_TREE_MODEL (ts),
267 path);
268 gtk_tree_path_free (path);
269 fi = GNUNET_FS_file_information_create_from_file (GNUNET_GTK_get_fs_handle (),
270 row_reference,
271 filename,
272 ksk_uri,
273 meta,
274 do_index,
275 bo);
276 GNUNET_CONTAINER_meta_data_destroy (meta);
277 GNUNET_FS_uri_destroy (ksk_uri);
278 if (S_ISDIR (sbuf.st_mode))
279 file_size_fancy = GNUNET_strdup (MARKER_DIR_FILE_SIZE);
280 else
281 file_size_fancy = GNUNET_STRINGS_byte_size_fancy (file_size);
282 gtk_tree_store_set (ts, &pos,
283 0, file_size_fancy,
284 1, (gboolean) do_index,
285 2, short_fn,
286 3, (guint) bo->anonymity_level,
287 4, (guint) bo->content_priority,
288 5, fi,
289 -1);
290 GNUNET_free (file_size_fancy);
291 update_selectivity ();
292}
293
294
295
296/**
297 * Add an empty directory to the tree model.
298 *
299 * @param name name for the directory
300 * @param bo block options
301 * @param iter parent entry, or NULL for top-level addition
302 * @param pos iterator to set to the location of the new element
303 */
304static void
305create_dir_at_iter (const char *name,
306 const struct GNUNET_FS_BlockOptions *bo,
307 GtkTreeIter *iter,
308 GtkTreeIter *pos)
309{
310 struct GNUNET_FS_FileInformation *fi;
311 GtkTreeRowReference *row_reference;
312 GtkTreePath *path;
313 struct GNUNET_CONTAINER_MetaData *meta;
314 GtkTreeStore *ts;
315
316 ts = GTK_TREE_STORE (gtk_builder_get_object (master_builder,
317 "GNUNET_GTK_file_sharing_publishing_tree_store"));
318 meta = GNUNET_CONTAINER_meta_data_create ();
319 GNUNET_FS_meta_data_make_directory (meta);
320 GNUNET_CONTAINER_meta_data_insert (meta,
321 "<gnunet-gtk>",
322 EXTRACTOR_METATYPE_FILENAME,
323 EXTRACTOR_METAFORMAT_UTF8,
324 "text/plain",
325 name,
326 strlen(name)+1);
327 gtk_tree_store_insert_before (ts,
328 pos,
329 iter,
330 NULL);
331 path = gtk_tree_model_get_path (GTK_TREE_MODEL (ts),
332 pos);
333 row_reference = gtk_tree_row_reference_new (GTK_TREE_MODEL (ts),
334 path);
335 gtk_tree_path_free (path);
336 fi = GNUNET_FS_file_information_create_empty_directory (GNUNET_GTK_get_fs_handle (),
337 row_reference,
338 NULL,
339 meta,
340 bo);
341 GNUNET_CONTAINER_meta_data_destroy (meta);
342 gtk_tree_store_set (ts, pos,
343 0, MARKER_DIR_FILE_SIZE,
344 1, (gboolean) GNUNET_NO,
345 2, name,
346 3, (guint) bo->anonymity_level,
347 4, (guint) bo->content_priority,
348 5, fi,
349 -1);
350 update_selectivity ();
351}
352
353
354/* ************ code for adding directories starts ************* */
355
356
357/**
358 * Data we keep when calculating the publication details for a file.
359 */
360struct PublishData
361{
362 /**
363 * Metadata for the file.
364 */
365 struct GNUNET_CONTAINER_MetaData *meta;
366
367 /**
368 * Iterator for the entry.
369 */
370 GtkTreeIter iter;
371};
372
373
374/**
375 * Entry for each unique meta data entry to track how often
376 * it occured. Contains the keyword and the counter.
377 */
378struct MetaCounter
379{
380
381 /**
382 * Keyword that was found.
383 */
384 const char *value;
385
386 /**
387 * Mimetype of the value.
388 */
389 const char *value_mimetype;
390
391 /**
392 * Type of the value.
393 */
394 enum EXTRACTOR_MetaType type;
395
396 /**
397 * Format of the value.
398 */
399 enum EXTRACTOR_MetaFormat format;
400
401 /**
402 * How many files have meta entries matching this value?
403 * (type and format do not have to match).
404 */
405 unsigned int count;
406
407};
408
409
410/**
411 * Execution context for 'add_dir'
412 */
413struct AddDirContext
414{
415 /**
416 * While scanning, 'parent' is the iter entry for the
417 * parent, or NULL for top-level.
418 */
419 GtkTreeIter *parent;
420
421 /**
422 * Tree store to manipulate.
423 */
424 GtkTreeStore *ts;
425
426 /**
427 * Map from the hash over the meta value to an 'struct MetaCounter'
428 * counter that says how often this value was
429 * encountered in the current directory.
430 */
431 struct GNUNET_CONTAINER_MultiHashMap *metacounter;
432
433 /**
434 * Map from the hash of a filename in the current directory
435 * to the 'struct PublishData*' for the file.
436 */
437 struct GNUNET_CONTAINER_MultiHashMap *metamap;
438
439 /**
440 * Metadata to exclude from using for KSK since it'll be associated
441 * with the parent as well. NULL for nothing blocked.
442 */
443 struct GNUNET_CONTAINER_MetaData *no_ksk;
444
445 /**
446 * Block options to use.
447 */
448 struct GNUNET_FS_BlockOptions bo;
449
450 /**
451 * Index or insert?
452 */
453 int do_index;
454
455 /**
456 * Number of files in the current directory.
457 */
458 unsigned int dir_entry_count;
459};
460
461
462/**
463 * Add the given meta data item to the
464 * meta data statistics tracker.
465 *
466 * @param cls closure (user-defined)
467 * @param plugin_name name of the plugin that produced this value;
468 * special values can be used (i.e. '<zlib>' for zlib being
469 * used in the main libextractor library and yielding
470 * meta data).
471 * @param type libextractor-type describing the meta data
472 * @param format basic format information about data
473 * @param data_mime_type mime-type of data (not of the original file);
474 * can be NULL (if mime-type is not known)
475 * @param data actual meta-data found
476 * @param data_len number of bytes in data
477 * @return 0 to continue extracting, 1 to abort
478 */
479static int
480add_to_meta_counter (void *cls,
481 const char *plugin_name,
482 enum EXTRACTOR_MetaType type,
483 enum EXTRACTOR_MetaFormat format,
484 const char *data_mime_type,
485 const char *data,
486 size_t data_len)
487{
488 struct GNUNET_CONTAINER_MultiHashMap *mcm = cls;
489 struct MetaCounter *cnt;
490 GNUNET_HashCode hc;
491 size_t mlen;
492 size_t dlen;
493
494 if ( (format != EXTRACTOR_METAFORMAT_UTF8) &&
495 (format != EXTRACTOR_METAFORMAT_C_STRING) )
496 return 0;
497 dlen = strlen (data) + 1;
498 GNUNET_CRYPTO_hash (data,
499 dlen - 1,
500 &hc);
501 cnt = GNUNET_CONTAINER_multihashmap_get (mcm, &hc);
502 if (cnt == NULL)
503 {
504 mlen = strlen (data_mime_type) + 1;
505 cnt = GNUNET_malloc (sizeof (struct MetaCounter) +
506 dlen + mlen);
507 cnt->count = 1;
508 cnt->value = (const char *) &cnt[1];
509 cnt->value_mimetype = &cnt->value[dlen];
510 memcpy (&cnt[1],
511 data,
512 dlen);
513 memcpy ((char*) cnt->value_mimetype,
514 data_mime_type,
515 mlen);
516 cnt->type = type;
517 cnt->format = format;
518 GNUNET_CONTAINER_multihashmap_put (mcm,
519 &hc,
520 cnt,
521 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
522
523 }
524 else
525 {
526 cnt->count++;
527 if (cnt->format == EXTRACTOR_METAFORMAT_C_STRING)
528 cnt->format = format; /* possibly improve to UTF8 */
529 if (cnt->type == EXTRACTOR_METATYPE_UNKNOWN)
530 cnt->type = type;
531 }
532 return 0;
533}
534
535
536/**
537 * Extract metadata from a file and add it to the metamap and
538 * the metacounter.
539 *
540 * @param adc context to modify
541 * @param filename name of the file to process
542 */
543static void
544extract_file (struct AddDirContext *adc,
545 const char *filename)
546{
547 struct PublishData *pd;
548 GNUNET_HashCode hc;
549 const char *short_fn;
550 const char *ss;
551
552 adc->dir_entry_count++;
553 pd = GNUNET_malloc (sizeof (struct PublishData));
554 pd->meta = GNUNET_CONTAINER_meta_data_create ();
555 GNUNET_FS_meta_data_extract_from_file (pd->meta,
556 filename,
557 GNUNET_GTK_get_le_plugins());
558 GNUNET_CONTAINER_meta_data_delete (pd->meta,
559 EXTRACTOR_METATYPE_FILENAME,
560 NULL, 0);
561 short_fn = filename;
562 while (NULL != (ss = strstr (short_fn, DIR_SEPARATOR_STR)))
563 short_fn = 1 + ss;
564 GNUNET_CONTAINER_meta_data_insert (pd->meta,
565 "<gnunet-gtk>",
566 EXTRACTOR_METATYPE_FILENAME,
567 EXTRACTOR_METAFORMAT_UTF8,
568 "text/plain",
569 short_fn,
570 strlen(short_fn)+1);
571
572
573 gtk_tree_store_insert_before (adc->ts,
574 &pd->iter,
575 adc->parent,
576 NULL);
577 GNUNET_CRYPTO_hash (filename,
578 strlen (filename),
579 &hc);
580 GNUNET_CONTAINER_multihashmap_put (adc->metamap,
581 &hc,
582 pd,
583 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
584 GNUNET_CONTAINER_meta_data_iterate (pd->meta,
585 &add_to_meta_counter,
586 adc->metacounter);
587}
588
589
590/**
591 * Remove the keyword from the ksk URI.
592 *
593 * @param cls the ksk uri
594 * @param keyword the word to remove
595 * @param is_mandatory ignored
596 * @return always GNUNET_OK
597 */
598static int
599remove_keyword (void *cls,
600 const char *keyword,
601 int is_mandatory)
602{
603 struct GNUNET_FS_Uri *ksk = cls;
604
605 GNUNET_FS_uri_ksk_remove_keyword (ksk, keyword);
606 return GNUNET_OK;
607}
608
609
610/**
611 * Add the specifics of the given entry to the tree store.
612 * Derive KSK from the given meta data, but exclude meta
613 * data given in "md_no_ksk" for keyword generation.
614 *
615 * @param ts tree store to modify
616 * @param iter position in the tree store for this file
617 * @param filename file to add
618 * @param bo block options
619 * @param do_index should we index or insert?
620 * @param md_no_ksk metadata with keywords NOT to add
621 * @param meta metadata for the file
622 */
623static void
624add_entry_to_ts (GtkTreeStore *ts,
625 GtkTreeIter *iter,
626 const char *filename,
627 const struct GNUNET_FS_BlockOptions *bo,
628 int do_index,
629 struct GNUNET_CONTAINER_MetaData *md_no_ksk,
630 struct GNUNET_CONTAINER_MetaData *meta)
631{
632 char *file_size_fancy;
633 struct GNUNET_FS_FileInformation *fi;
634 GtkTreeRowReference *row_reference;
635 GtkTreePath *path;
636 uint64_t file_size;
637 struct GNUNET_FS_Uri *ksk_uri;
638 struct GNUNET_FS_Uri *kill_ksk;
639 const char *ss;
640 const char *short_fn;
641 struct stat sbuf;
642
643 if (0 != STAT (filename, &sbuf))
644 return;
645 if (S_ISDIR (sbuf.st_mode))
646 {
647 file_size = 0;
648 }
649 else
650 {
651 if (GNUNET_OK !=
652 GNUNET_DISK_file_size (filename,
653 &file_size,
654 GNUNET_YES))
655 {
656 GNUNET_break (0);
657 return;
658 }
659 }
660 ksk_uri = GNUNET_FS_uri_ksk_create_from_meta_data (meta);
661 kill_ksk = GNUNET_FS_uri_ksk_create_from_meta_data (md_no_ksk);
662 if (kill_ksk != NULL)
663 {
664 GNUNET_FS_uri_ksk_get_keywords (kill_ksk,
665 &remove_keyword,
666 ksk_uri);
667 GNUNET_FS_uri_destroy (kill_ksk);
668 }
669 path = gtk_tree_model_get_path (GTK_TREE_MODEL (ts),
670 iter);
671 row_reference = gtk_tree_row_reference_new (GTK_TREE_MODEL (ts),
672 path);
673 gtk_tree_path_free (path);
674 if (S_ISDIR (sbuf.st_mode))
675 {
676 GNUNET_CONTAINER_meta_data_delete (meta,
677 EXTRACTOR_METATYPE_MIMETYPE,
678 NULL, 0);
679 GNUNET_FS_meta_data_make_directory (meta);
680 GNUNET_FS_uri_ksk_add_keyword (ksk_uri,
681 GNUNET_FS_DIRECTORY_MIME,
682 GNUNET_NO);
683 fi = GNUNET_FS_file_information_create_empty_directory (GNUNET_GTK_get_fs_handle (),
684 row_reference,
685 ksk_uri,
686 meta,
687 bo);
688 }
689 else
690 {
691 fi = GNUNET_FS_file_information_create_from_file (GNUNET_GTK_get_fs_handle (),
692 row_reference,
693 filename,
694 ksk_uri,
695 meta,
696 do_index,
697 bo);
698 }
699 GNUNET_CONTAINER_meta_data_destroy (meta);
700 GNUNET_FS_uri_destroy (ksk_uri);
701 if (S_ISDIR (sbuf.st_mode))
702 file_size_fancy = GNUNET_strdup (MARKER_DIR_FILE_SIZE);
703 else
704 file_size_fancy = GNUNET_STRINGS_byte_size_fancy (file_size);
705 short_fn = filename;
706 while (NULL != (ss = strstr (short_fn, DIR_SEPARATOR_STR)))
707 short_fn = 1 + ss;
708 gtk_tree_store_set (ts, iter,
709 0, file_size_fancy,
710 1, (gboolean) do_index,
711 2, short_fn,
712 3, (guint) bo->anonymity_level,
713 4, (guint) bo->content_priority,
714 5, fi,
715 -1);
716 GNUNET_free (file_size_fancy);
717}
718
719
720/**
721 * Function called by the directory iterator to
722 * (recursively) add all of the files in the
723 * directory to the tree.
724 *
725 * @param cls the 'struct AddDirContext*' we're in
726 * @param filename file or directory to scan
727 */
728static int
729publish_entry (void *cls,
730 const char *filename)
731{
732 struct AddDirContext *adc = cls;
733 struct PublishData *pd;
734 GNUNET_HashCode hc;
735
736 GNUNET_CRYPTO_hash (filename,
737 strlen (filename),
738 &hc);
739 pd = GNUNET_CONTAINER_multihashmap_get (adc->metamap,
740 &hc);
741 add_entry_to_ts (adc->ts,
742 &pd->iter,
743 filename,
744 &adc->bo,
745 adc->do_index,
746 adc->no_ksk,
747 pd->meta);
748 GNUNET_CONTAINER_multihashmap_remove (adc->metamap,
749 &hc,
750 pd);
751 GNUNET_free (pd);
752 return GNUNET_OK;
753}
754
755
756/**
757 * Context passed to 'migrate_and_drop'.
758 */
759struct MetaProcessContext
760{
761 /**
762 * Metadata with all the keywords we migrated to the parent.
763 */
764 struct GNUNET_CONTAINER_MetaData *md;
765
766 /**
767 * How often does a keyword have to occur to be
768 * migrated to the parent?
769 */
770 unsigned int threshold;
771};
772
773
774/**
775 * Copy "frequent" meta data entries over to the
776 * target meta data struct, free the counters.
777 *
778 */
779static int
780migrate_and_drop (void *cls,
781 const GNUNET_HashCode *key,
782 void *value)
783{
784 struct MetaProcessContext *mpc = cls;
785 struct MetaCounter *counter = value;
786
787 if (counter->count >= mpc->threshold)
788 {
789 GNUNET_CONTAINER_meta_data_insert (mpc->md,
790 "<gnunet-gtk>",
791 counter->type,
792 counter->format,
793 counter->value_mimetype,
794 counter->value,
795 strlen (counter->value)+1);
796 }
797 GNUNET_free (counter);
798 return GNUNET_YES;
799}
800
801
802/**
803 * Go over the collected meta data from all entries in the
804 * directory and push common meta data up one level (by
805 * adding it to the returned struct).
806 *
807 * @param adc collection of child meta data
808 * @return meta data to moved to parent
809 */
810static struct GNUNET_CONTAINER_MetaData *
811process_metadata (struct AddDirContext *adc)
812{
813 struct MetaProcessContext mpc;
814
815 mpc.md = GNUNET_CONTAINER_meta_data_create ();
816 mpc.threshold = (adc->dir_entry_count + 1) / 2; /* 50% */
817 GNUNET_CONTAINER_multihashmap_iterate (adc->metacounter,
818 &migrate_and_drop,
819 &mpc);
820 GNUNET_CONTAINER_multihashmap_destroy (adc->metacounter);
821 return mpc.md;
822}
823
824
825/**
826 * Function called by the directory iterator to
827 * (recursively) add all of the files in the
828 * directory to the tree.
829 *
830 * @param cls the 'struct AddDirContext*' we're in
831 * @param filename file or directory to scan
832 */
833static int
834scan_directory (void *cls,
835 const char *filename)
836
837{
838 struct AddDirContext *adc = cls;
839 struct stat sbuf;
840 GtkTreeIter *parent;
841 struct PublishData *pd;
842 GNUNET_HashCode hc;
843 struct GNUNET_CONTAINER_MultiHashMap *mhm;
844 struct GNUNET_CONTAINER_MultiHashMap *mcm;
845 unsigned int pc;
846
847 if (0 != STAT (filename, &sbuf))
848 return GNUNET_OK;
849 if (S_ISDIR (sbuf.st_mode))
850 {
851 parent = adc->parent;
852 mhm = adc->metamap;
853 mcm = adc->metacounter;
854 pc = adc->dir_entry_count;
855 adc->metamap = GNUNET_CONTAINER_multihashmap_create (1024);
856 adc->metacounter = GNUNET_CONTAINER_multihashmap_create (1024);
857 adc->dir_entry_count = 0;
858 pd = GNUNET_malloc (sizeof (struct PublishData));
859 gtk_tree_store_insert_before (adc->ts,
860 &pd->iter,
861 parent,
862 NULL);
863 adc->parent = &pd->iter;
864 GNUNET_DISK_directory_scan (filename,
865 &scan_directory,
866 adc);
867 pd->meta = process_metadata (adc);
868 adc->no_ksk = pd->meta;
869 GNUNET_DISK_directory_scan (filename,
870 &publish_entry,
871 adc);
872 GNUNET_CONTAINER_multihashmap_destroy (adc->metamap);
873 adc->metamap = mhm;
874 adc->metacounter = mcm;
875 adc->parent = parent;
876 adc->dir_entry_count = pc + 1;
877 if (adc->metamap != NULL)
878 {
879 GNUNET_CRYPTO_hash (filename,
880 strlen (filename),
881 &hc);
882 GNUNET_CONTAINER_multihashmap_put (adc->metamap,
883 &hc,
884 pd,
885 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
886 GNUNET_CONTAINER_meta_data_iterate (pd->meta,
887 &add_to_meta_counter,
888 mcm);
889 }
890 else
891 {
892 GNUNET_assert (mcm == NULL);
893 /* we're top-level */
894 add_entry_to_ts (adc->ts,
895 &pd->iter,
896 filename,
897 &adc->bo,
898 adc->do_index,
899 NULL,
900 pd->meta);
901 }
902 }
903 else
904 {
905 GNUNET_assert (adc->metamap != NULL);
906 extract_file (adc, filename);
907 }
908 return GNUNET_OK;
909}
910
911
912/**
913 * Add a directory to the tree model.
914 *
915 * @param filename directory name to add
916 * @param bo block options
917 * @param do_index should we index?
918 */
919static void
920add_dir (const char *filename,
921 const struct GNUNET_FS_BlockOptions *bo,
922 int do_index)
923{
924 struct stat sbuf;
925 struct AddDirContext scan_ctx;
926
927 if (0 != STAT (filename, &sbuf))
928 return;
929 if (! S_ISDIR (sbuf.st_mode))
930 {
931 GNUNET_break (0);
932 return;
933 }
934 memset (&scan_ctx, 0, sizeof (scan_ctx));
935 scan_ctx.bo = *bo;
936 scan_ctx.do_index = do_index;
937 scan_ctx.ts = GTK_TREE_STORE (gtk_builder_get_object (master_builder,
938 "GNUNET_GTK_file_sharing_publishing_tree_store"));
939 scan_directory (&scan_ctx, filename);
940}
941
942
943/* ************ code for adding directories ends here ************* */
944
945
946static void
947selection_changed_cb (GtkTreeSelection *ts,
948 gpointer user_data)
949{
950 update_selectivity ();
951}
952
953
954static void
955remove_old_entry (GtkTreeStore *ts,
956 GtkTreeIter *root)
957{
958 GtkTreeIter child;
959
960 while (TRUE == gtk_tree_model_iter_children (GTK_TREE_MODEL (ts),
961 &child, root))
962 remove_old_entry (ts, &child);
963 gtk_tree_store_remove (ts, root);
964}
965
966
967/**
968 * Move an entry in the tree.
969 */
970static void
971move_entry (GtkTreeModel *tm,
972 GtkTreeIter *old,
973 GtkTreeIter *newpos,
974 int dsel)
975{
976 struct GNUNET_FS_FileInformation *fip;
977 GtkTreeView *tv;
978 gint do_index;
979 gchar *short_fn;
980 guint anonymity_level;
981 guint priority;
982 char *fsf;
983 GtkTreePath *path;
984 GtkTreeSelection *sel;
985 GtkTreeIter child;
986 GtkTreeIter cnewpos;
987 GtkTreeRowReference *rr;
988 GtkTreeRowReference *rr2;
989
990 gtk_tree_model_get (tm,
991 old,
992 0, &fsf,
993 1, &do_index,
994 2, &short_fn,
995 3, &anonymity_level,
996 4, &priority,
997 5, &fip,
998 -1);
999 gtk_tree_store_set (GTK_TREE_STORE (tm), newpos,
1000 0, fsf,
1001 1, do_index,
1002 2, short_fn,
1003 3, (guint)anonymity_level,
1004 4, (guint) priority,
1005 5, fip,
1006 -1);
1007 sel = NULL;
1008 tv = NULL;
1009 if (dsel == GNUNET_YES)
1010 {
1011 tv = GTK_TREE_VIEW (gtk_builder_get_object (master_builder,
1012 "GNUNET_GTK_master_publish_dialog_file_information_tree_view"));
1013 sel = gtk_tree_view_get_selection (tv);
1014 path = gtk_tree_model_get_path (tm, newpos);
1015 rr = gtk_tree_row_reference_new (tm, path);
1016 gtk_tree_path_free (path);
1017 }
1018 else
1019 {
1020 rr = NULL;
1021 }
1022 if (TRUE == gtk_tree_model_iter_children (tm, &child, old))
1023 {
1024 do
1025 {
1026 path = gtk_tree_model_get_path (tm, &child);
1027 rr2 = gtk_tree_row_reference_new (tm, path);
1028 gtk_tree_path_free (path);
1029 gtk_tree_store_insert_before (GTK_TREE_STORE (tm),
1030 &cnewpos, newpos, NULL);
1031 move_entry (tm, &child, &cnewpos, GNUNET_NO);
1032 path = gtk_tree_row_reference_get_path (rr2);
1033 gtk_tree_row_reference_free (rr2);
1034 GNUNET_assert (TRUE == gtk_tree_model_get_iter (tm,
1035 &child,
1036 path));
1037 gtk_tree_path_free (path);
1038 }
1039 while (TRUE == gtk_tree_model_iter_next (tm, &child));
1040 }
1041 g_free (short_fn);
1042 g_free (fsf);
1043 if (dsel == GNUNET_YES)
1044 {
1045 path = gtk_tree_row_reference_get_path (rr);
1046 gtk_tree_row_reference_free (rr);
1047 gtk_tree_view_expand_to_path (tv, path);
1048 GNUNET_assert (TRUE == gtk_tree_model_get_iter (tm,
1049 newpos,
1050 path));
1051 gtk_tree_path_free (path);
1052 gtk_tree_selection_select_iter (sel,
1053 newpos);
1054 }
1055 update_selectivity ();
1056}
1057
1058/**
1059 * User has changed the "current" identifier for the content in
1060 * the GtkTreeView. Update the model.
1061 */
1062void
1063GNUNET_GTK_master_publish_dialog_pseudonym_updates_renderer_edited_cb (GtkCellRendererText *renderer,
1064 gchar *cpath,
1065 gchar *new_text,
1066 gpointer user_data)
1067{
1068 GtkTreeIter iter;
1069 GtkTreeStore *ts;
1070
1071 ts = GTK_TREE_STORE (gtk_builder_get_object (master_builder,
1072 "GNUNET_GTK_pseudonym_tree_store"));
1073
1074 if (TRUE !=
1075 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (ts), &iter, cpath))
1076 {
1077 GNUNET_break (0);
1078 return;
1079 }
1080 gtk_tree_store_set (ts, &iter, 5, new_text, -1);
1081 update_selectivity ();
1082}
1083
1084
1085/**
1086 * User has changed the "current" identifier for the content in
1087 * the GtkTreeView. Update the model.
1088 */
1089void
1090GNUNET_GTK_master_publish_dialog_pseudonym_identifier_renderer_edited_cb (GtkCellRendererText *renderer,
1091 gchar *cpath,
1092 gchar *new_text,
1093 gpointer user_data)
1094{
1095 GtkTreeIter iter;
1096 GtkTreeStore *ts;
1097
1098 ts = GTK_TREE_STORE (gtk_builder_get_object (master_builder,
1099 "GNUNET_GTK_pseudonym_tree_store"));
1100
1101 if (TRUE !=
1102 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (ts), &iter, cpath))
1103 {
1104 GNUNET_break (0);
1105 return;
1106 }
1107 gtk_tree_store_set (ts, &iter, 2, new_text, -1);
1108 update_selectivity ();
1109}
1110
1111
1112void
1113GNUNET_GTK_master_publish_dialog_right_button_clicked_cb (GtkWidget * dummy,
1114 gpointer data)
1115{
1116 GtkTreeView *tv;
1117 GtkTreeModel *tm;
1118 GtkTreeSelection *sel;
1119 GtkTreeIter iter;
1120 GtkTreeIter parent;
1121 GtkTreeIter pred;
1122 GtkTreeIter prev;
1123 GtkTreeIter pos;
1124
1125 tv = GTK_TREE_VIEW (gtk_builder_get_object (master_builder,
1126 "GNUNET_GTK_master_publish_dialog_file_information_tree_view"));
1127 sel = gtk_tree_view_get_selection (tv);
1128 if (TRUE != gtk_tree_selection_get_selected (sel,
1129 &tm,
1130 &iter))
1131 {
1132 GNUNET_break (0);
1133 return;
1134 }
1135 if (TRUE == gtk_tree_model_iter_parent (tm, &parent, &iter))
1136 {
1137 GNUNET_assert (TRUE == gtk_tree_model_iter_children (tm, &pred, &parent));
1138 }
1139 else if (TRUE != gtk_tree_model_get_iter_first (tm, &pred))
1140 {
1141 GNUNET_break (0);
1142 return;
1143 }
1144 /* iterate over 'next' of pred to find out who our predecessor is! */
1145 memset (&prev, 0, sizeof (GtkTreeIter));
1146 while (GNUNET_YES != gtk_tree_iter_equals (tm, &pred, &iter))
1147 {
1148 prev = pred;
1149 GNUNET_assert (TRUE == gtk_tree_model_iter_next (tm, &pred));
1150 }
1151 gtk_tree_store_insert_before (GTK_TREE_STORE (tm),
1152 &pos, &prev, NULL);
1153 if (TRUE != gtk_tree_selection_get_selected (sel,
1154 &tm,
1155 &iter))
1156 {
1157 GNUNET_break (0);
1158 return;
1159 }
1160 move_entry (tm, &iter, &pos, GNUNET_YES);
1161 remove_old_entry (GTK_TREE_STORE (tm), &iter);
1162}
1163
1164
1165void
1166GNUNET_GTK_master_publish_dialog_left_button_clicked_cb (GtkWidget * dummy,
1167 gpointer data)
1168{
1169 GtkTreeView *tv;
1170 GtkTreeModel *tm;
1171 GtkTreeSelection *sel;
1172 GtkTreeIter iter;
1173 GtkTreeIter parent;
1174 GtkTreeIter pos;
1175
1176 tv = GTK_TREE_VIEW (gtk_builder_get_object (master_builder,
1177 "GNUNET_GTK_master_publish_dialog_file_information_tree_view"));
1178 sel = gtk_tree_view_get_selection (tv);
1179 if (TRUE != gtk_tree_selection_get_selected (sel,
1180 &tm,
1181 &iter))
1182 {
1183 GNUNET_break (0);
1184 return;
1185 }
1186 if (TRUE != gtk_tree_model_iter_parent (tm, &parent, &iter))
1187 {
1188 GNUNET_break (0);
1189 return;
1190 }
1191 gtk_tree_store_insert_after (GTK_TREE_STORE (tm),
1192 &pos, NULL, &parent);
1193 if (TRUE != gtk_tree_selection_get_selected (sel,
1194 &tm,
1195 &iter))
1196 {
1197 GNUNET_break (0);
1198 return;
1199 }
1200 move_entry (tm, &iter, &pos, GNUNET_YES);
1201 remove_old_entry (GTK_TREE_STORE (tm), &iter);
1202}
1203
1204
1205void
1206GNUNET_GTK_master_publish_dialog_up_button_clicked_cb (GtkWidget * dummy,
1207 gpointer data)
1208{
1209 GtkTreeView *tv;
1210 GtkTreeModel *tm;
1211 GtkTreeSelection *sel;
1212 GtkTreeIter iter;
1213 GtkTreeIter parent;
1214 GtkTreeIter pred;
1215 GtkTreeIter prev;
1216 GtkTreeIter *pprev;
1217 GtkTreeIter pos;
1218
1219 tv = GTK_TREE_VIEW (gtk_builder_get_object (master_builder,
1220 "GNUNET_GTK_master_publish_dialog_file_information_tree_view"));
1221 sel = gtk_tree_view_get_selection (tv);
1222 if (TRUE != gtk_tree_selection_get_selected (sel,
1223 &tm,
1224 &iter))
1225 {
1226 GNUNET_break (0);
1227 return;
1228 }
1229 if (TRUE == gtk_tree_model_iter_parent (tm, &parent, &iter))
1230 {
1231 GNUNET_assert (TRUE == gtk_tree_model_iter_children (tm, &pred, &parent));
1232 pprev = &parent;
1233 }
1234 else if (TRUE == gtk_tree_model_get_iter_first (tm, &pred))
1235 {
1236 pprev = NULL;
1237 }
1238 else
1239 {
1240 GNUNET_break (0);
1241 return;
1242 }
1243 /* iterate over 'next' of pred to find out who our predecessor is! */
1244 while (GNUNET_YES != gtk_tree_iter_equals (tm, &pred, &iter))
1245 {
1246 prev = pred;
1247 pprev = &prev;
1248 GNUNET_assert (TRUE == gtk_tree_model_iter_next (tm, &pred));
1249 }
1250 gtk_tree_store_insert_before (GTK_TREE_STORE (tm),
1251 &pos, NULL, pprev);
1252 if (TRUE != gtk_tree_selection_get_selected (sel,
1253 &tm,
1254 &iter))
1255 {
1256 GNUNET_break (0);
1257 return;
1258 }
1259 move_entry (tm, &iter, &pos, GNUNET_YES);
1260 remove_old_entry (GTK_TREE_STORE (tm), &iter);
1261}
1262
1263
1264void
1265GNUNET_GTK_master_publish_dialog_down_button_clicked_cb (GtkWidget * dummy,
1266 gpointer data)
1267{
1268 GtkTreeView *tv;
1269 GtkTreeModel *tm;
1270 GtkTreeSelection *sel;
1271 GtkTreeIter iter;
1272 GtkTreeIter next;
1273 GtkTreeIter pos;
1274
1275 tv = GTK_TREE_VIEW (gtk_builder_get_object (master_builder,
1276 "GNUNET_GTK_master_publish_dialog_file_information_tree_view"));
1277 sel = gtk_tree_view_get_selection (tv);
1278 if (TRUE != gtk_tree_selection_get_selected (sel,
1279 &tm,
1280 &iter))
1281 {
1282 GNUNET_break (0);
1283 return;
1284 }
1285 if (TRUE != gtk_tree_selection_get_selected (sel,
1286 &tm,
1287 &next))
1288 {
1289 GNUNET_break (0);
1290 return;
1291 }
1292 GNUNET_assert (TRUE == gtk_tree_model_iter_next (tm, &next));
1293 gtk_tree_store_insert_after (GTK_TREE_STORE (tm),
1294 &pos, NULL, &next);
1295 if (TRUE != gtk_tree_selection_get_selected (sel,
1296 &tm,
1297 &iter))
1298 {
1299 GNUNET_break (0);
1300 return;
1301 }
1302 move_entry (tm, &iter, &pos, GNUNET_YES);
1303 remove_old_entry (GTK_TREE_STORE (tm), &iter);
1304}
1305
1306
1307void
1308GNUNET_GTK_master_publish_dialog_new_button_clicked_cb (GtkWidget * dummy,
1309 gpointer data)
1310{
1311 GtkTreeView *tv;
1312 GtkTreeSelection *sel;
1313 GtkTreeIter iter;
1314 GtkTreeIter pos;
1315 struct GNUNET_FS_BlockOptions bo;
1316
1317 tv = GTK_TREE_VIEW (gtk_builder_get_object (master_builder,
1318 "GNUNET_GTK_master_publish_dialog_file_information_tree_view"));
1319 sel = gtk_tree_view_get_selection (tv);
1320 /* FIXME: consider opening a dialog to get
1321 * anonymity, priority and expiration prior
1322 * to calling this function (currently we
1323 * use default values for those).
1324 */
1325 bo.anonymity_level = 1;
1326 bo.content_priority = 1000;
1327 bo.expiration_time = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_YEARS);
1328 bo.replication_level = 1;
1329 if (TRUE != gtk_tree_selection_get_selected (sel,
1330 NULL,
1331 &iter))
1332 {
1333 create_dir_at_iter ("unnamed/",
1334 &bo,
1335 NULL, &pos);
1336 return;
1337 }
1338 create_dir_at_iter ("unnamed/",
1339 &bo,
1340 &iter, &pos);
1341}
1342
1343
1344void
1345GNUNET_GTK_master_publish_dialog_add_button_clicked_cb (GtkWidget * dummy,
1346 gpointer data)
1347{
1348 GtkWidget *ad;
1349 GtkBuilder *builder;
1350 char *filename;
1351 struct GNUNET_FS_BlockOptions bo;
1352 int do_index;
1353 GtkSpinButton *sb;
1354
1355 builder = GNUNET_GTK_get_new_builder ("publish-file-dialog.glade");
1356 if (builder == NULL)
1357 {
1358 GNUNET_break (0);
1359 return;
1360 }
1361 ad = GTK_WIDGET (gtk_builder_get_object (builder,
1362 "GNUNET_GTK_publish_file_dialog"));
1363 GNUNET_GTK_setup_expiration_year_adjustment (builder);
1364 if (GTK_RESPONSE_OK != gtk_dialog_run (GTK_DIALOG (ad)))
1365 {
1366 gtk_widget_destroy (ad);
1367 g_object_unref (G_OBJECT (builder));
1368 return;
1369 }
1370 filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER(ad));
1371 sb = GTK_SPIN_BUTTON (gtk_builder_get_object (builder,
1372 "GNUNET_GTK_publish_file_dialog_expiration_year_spin_button"));
1373 bo.anonymity_level = gtk_spin_button_get_value (GTK_SPIN_BUTTON (gtk_builder_get_object (builder,
1374 "GNUNET_GTK_publish_file_dialog_anonymity_spin_button")));
1375 bo.content_priority = gtk_spin_button_get_value (GTK_SPIN_BUTTON (gtk_builder_get_object (builder,
1376 "GNUNET_GTK_publish_file_dialog_priority_spin_button")));
1377 bo.expiration_time = GNUNET_GTK_get_expiration_time (sb);
1378 bo.replication_level = 1; /* FIXME... */
1379 do_index = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (gtk_builder_get_object (builder,
1380 "GNUNET_GTK_publish_file_dialog_do_index_checkbutton")));
1381 add_file_at_iter (filename,
1382 &bo, do_index,
1383 NULL);
1384 gtk_widget_destroy (ad);
1385 g_object_unref (G_OBJECT (builder));
1386 g_free (filename);
1387 update_selectivity ();
1388}
1389
1390
1391void
1392GNUNET_GTK_master_publish_dialog_edit_button_clicked_cb (GtkWidget * dummy,
1393 gpointer data)
1394{
1395 GtkTreeView *tv;
1396 GtkTreeModel *tm;
1397 GtkTreeSelection *sel;
1398 GtkTreeIter iter;
1399 int do_index;
1400 guint anonymity_level;
1401 guint priority;
1402 gchar *short_fn;
1403 struct GNUNET_FS_FileInformation *fip;
1404
1405 tv = GTK_TREE_VIEW (gtk_builder_get_object (master_builder,
1406 "GNUNET_GTK_master_publish_dialog_file_information_tree_view"));
1407 sel = gtk_tree_view_get_selection (tv);
1408 if (TRUE != gtk_tree_selection_get_selected (sel,
1409 &tm,
1410 &iter))
1411 {
1412 GNUNET_break (0);
1413 return;
1414 }
1415 gtk_tree_model_get (tm,
1416 &iter,
1417 1, &do_index,
1418 2, &short_fn,
1419 3, &anonymity_level,
1420 4, &priority,
1421 5, &fip,
1422 -1);
1423 GNUNET_GTK_edit_publish_dialog (&do_index,
1424 &short_fn,
1425 &anonymity_level,
1426 &priority,
1427 fip);
1428 gtk_tree_store_set (GTK_TREE_STORE (tm),
1429 &iter,
1430 1, do_index,
1431 2, short_fn,
1432 3, anonymity_level,
1433 4, priority,
1434 -1);
1435 g_free (short_fn);
1436}
1437
1438
1439/**
1440 * Free row reference stored in the file information's
1441 * client-info pointer.
1442 */
1443static int
1444free_fi_row_reference (void *cls,
1445 struct GNUNET_FS_FileInformation *fi,
1446 uint64_t length,
1447 struct GNUNET_CONTAINER_MetaData *meta,
1448 struct GNUNET_FS_Uri **uri,
1449 struct GNUNET_FS_BlockOptions *bo,
1450 int *do_index,
1451 void **client_info)
1452{
1453 GtkTreeRowReference *row = *client_info;
1454
1455 if (row == NULL)
1456 {
1457 GNUNET_break (0);
1458 return GNUNET_OK;
1459 }
1460 gtk_tree_row_reference_free (row);
1461 return GNUNET_OK;
1462}
1463
1464
1465
1466void
1467GNUNET_GTK_master_publish_dialog_delete_button_clicked_cb (GtkWidget * dummy,
1468 gpointer data)
1469{
1470 GtkTreeView *tv;
1471 GtkTreeModel *tm;
1472 GtkTreeSelection *sel;
1473 GtkTreeIter iter;
1474 struct GNUNET_FS_FileInformation *fip;
1475
1476 tv = GTK_TREE_VIEW (gtk_builder_get_object (master_builder,
1477 "GNUNET_GTK_master_publish_dialog_file_information_tree_view"));
1478 sel = gtk_tree_view_get_selection (tv);
1479 if (TRUE != gtk_tree_selection_get_selected (sel,
1480 &tm,
1481 &iter))
1482 {
1483 GNUNET_break (0);
1484 return;
1485 }
1486 gtk_tree_model_get (tm,
1487 &iter,
1488 5, &fip,
1489 -1);
1490 GNUNET_FS_file_information_destroy (fip,
1491 &free_fi_row_reference,
1492 NULL);
1493 gtk_tree_store_remove (GTK_TREE_STORE (tm),
1494 &iter);
1495 update_selectivity ();
1496}
1497
1498
1499void
1500GNUNET_GTK_master_publish_dialog_open_button_clicked_cb (GtkWidget * dummy,
1501 gpointer data)
1502{
1503 GtkWidget *ad;
1504 GtkBuilder *builder;
1505 char *filename;
1506 int do_index;
1507 GtkSpinButton *sb;
1508 struct GNUNET_FS_BlockOptions bo;
1509
1510 builder = GNUNET_GTK_get_new_builder ("publish-directory-dialog.glade");
1511 if (builder == NULL)
1512 {
1513 GNUNET_break (0);
1514 return;
1515 }
1516 GNUNET_GTK_setup_expiration_year_adjustment (builder);
1517 ad = GTK_WIDGET (gtk_builder_get_object (builder,
1518 "GNUNET_GTK_publish_directory_dialog"));
1519 if (GTK_RESPONSE_OK != gtk_dialog_run (GTK_DIALOG (ad)))
1520 {
1521 gtk_widget_destroy (ad);
1522 g_object_unref (G_OBJECT (builder));
1523 return;
1524 }
1525 filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER(ad));
1526 sb = GTK_SPIN_BUTTON (gtk_builder_get_object (builder,
1527 "GNUNET_GTK_publish_directory_dialog_expiration_year_spin_button"));
1528 bo.anonymity_level = gtk_spin_button_get_value (GTK_SPIN_BUTTON (gtk_builder_get_object (builder,
1529 "GNUNET_GTK_publish_directory_dialog_anonymity_spin_button")));
1530 bo.content_priority = gtk_spin_button_get_value (GTK_SPIN_BUTTON (gtk_builder_get_object (builder,
1531 "GNUNET_GTK_publish_directory_dialog_priority_spin_button")));
1532 bo.expiration_time = GNUNET_GTK_get_expiration_time (sb);
1533 do_index = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (gtk_builder_get_object (builder,
1534 "GNUNET_GTK_publish_directory_dialog_do_index_checkbutton")));
1535
1536 gtk_widget_destroy (ad);
1537 g_object_unref (G_OBJECT (builder));
1538 /* FIXME: open progress dialog here... */
1539 add_dir (filename, &bo, do_index);
1540 g_free (filename);
1541 update_selectivity ();
1542}
1543
1544
1545/**
1546 * Get the file information struct corresponding to the
1547 * given iter in the publish dialog tree model. Recursively
1548 * builds the file information struct from the subtree.
1549 *
1550 * @param tm model to grab fi from
1551 * @param iter position to grab fi from
1552 * @return file information from the given position (never NULL)
1553 */
1554static struct GNUNET_FS_FileInformation *
1555get_file_information (GtkTreeModel *tm,
1556 GtkTreeIter *iter)
1557{
1558 struct GNUNET_FS_FileInformation *fi;
1559 struct GNUNET_FS_FileInformation *fic;
1560 GtkTreeIter child;
1561
1562 gtk_tree_model_get (tm, iter,
1563 5, &fi,
1564 -1);
1565 gtk_tree_store_set (GTK_TREE_STORE (tm), iter,
1566 5, NULL,
1567 -1);
1568 GNUNET_assert (fi != NULL);
1569 if (gtk_tree_model_iter_children (tm, &child, iter))
1570 {
1571 GNUNET_break (GNUNET_YES ==
1572 GNUNET_FS_file_information_is_directory (fi));
1573 do
1574 {
1575 fic = get_file_information (tm, &child);
1576 GNUNET_break (GNUNET_OK ==
1577 GNUNET_FS_file_information_add (fi, fic));
1578 }
1579 while (gtk_tree_model_iter_next (tm, &child));
1580 }
1581 return fi;
1582}
1583
1584
1585/**
1586 * Closure for 'add_updateable_to_ts'.
1587 */
1588struct UpdateableContext
1589{
1590 /**
1591 * Parent of current insertion.
1592 */
1593 GtkTreeIter *parent;
1594
1595 /**
1596 * Tree store we are modifying.
1597 */
1598 GtkTreeStore *ts;
1599
1600 /**
1601 * Name of the namespace.
1602 */
1603 const char *namespace_name;
1604
1605 /**
1606 * Handle to the namespace.
1607 */
1608 struct GNUNET_FS_Namespace *ns;
1609
1610 /**
1611 * Hash codes of identifiers already added to tree store.
1612 */
1613 struct GNUNET_CONTAINER_MultiHashMap *seen;
1614
1615 /**
1616 * Did the iterator get called?
1617 */
1618 int update_called;
1619};
1620
1621
1622/**
1623 * Add updateable entries to the tree view.
1624 *
1625 * @param cls closure
1626 * @param last_id ID to add
1627 * @param last_uri associated URI
1628 * @param last_meta associate meta data
1629 * @param next_id ID for future updates
1630 */
1631static void
1632add_updateable_to_ts (void *cls,
1633 const char *last_id,
1634 const struct GNUNET_FS_Uri *last_uri,
1635 const struct GNUNET_CONTAINER_MetaData *last_meta,
1636 const char *next_id)
1637{
1638 struct UpdateableContext *uc = cls;
1639 struct UpdateableContext sc;
1640 GtkTreeIter iter;
1641 GtkTreeIter titer;
1642 char *desc;
1643 GNUNET_HashCode hc;
1644
1645 uc->update_called = GNUNET_YES;
1646 GNUNET_CRYPTO_hash (last_id,
1647 strlen (last_id),
1648 &hc);
1649 if (NULL !=
1650 GNUNET_CONTAINER_multihashmap_get (uc->seen,
1651 &hc))
1652 return;
1653 GNUNET_CONTAINER_multihashmap_put (uc->seen,
1654 &hc,
1655 "dummy",
1656 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1657 desc = GNUNET_CONTAINER_meta_data_get_first_by_types (last_meta,
1658 EXTRACTOR_METATYPE_DESCRIPTION,
1659 EXTRACTOR_METATYPE_TITLE,
1660 EXTRACTOR_METATYPE_BOOK_TITLE,
1661 EXTRACTOR_METATYPE_FILENAME,
1662 EXTRACTOR_METATYPE_SUMMARY,
1663 EXTRACTOR_METATYPE_ALBUM,
1664 EXTRACTOR_METATYPE_COMMENT,
1665 EXTRACTOR_METATYPE_SUBJECT,
1666 -1);
1667 gtk_tree_store_insert_with_values (uc->ts,
1668 &iter,
1669 uc->parent,
1670 G_MAXINT,
1671 0, uc->namespace_name,
1672 1, uc->ns,
1673 2, last_id,
1674 3, GNUNET_FS_uri_dup (last_uri),
1675 4, GNUNET_CONTAINER_meta_data_duplicate (last_meta),
1676 5, "",
1677 6, desc,
1678 7, TRUE /* update editable (always) */,
1679 8, FALSE /* current not editable (only for top-level) */,
1680 -1);
1681 GNUNET_free_non_null (desc);
1682 sc.parent = &iter;
1683 sc.ts = uc->ts;
1684 sc.namespace_name = uc->namespace_name;
1685 sc.ns = uc->ns;
1686 sc.seen = uc->seen;
1687 sc.update_called = GNUNET_NO;
1688 GNUNET_FS_namespace_list_updateable (uc->ns,
1689 next_id,
1690 &add_updateable_to_ts,
1691 &sc);
1692 if ( (sc.update_called == GNUNET_NO) &&
1693 (next_id != NULL) &&
1694 (strlen (next_id) > 0) )
1695 {
1696 /* add leaf */
1697 gtk_tree_store_insert_with_values (uc->ts,
1698 &titer,
1699 &iter,
1700 G_MAXINT,
1701 0, uc->namespace_name,
1702 1, uc->ns,
1703 2, next_id,
1704 3, NULL,
1705 4, NULL,
1706 5, "",
1707 6, "",
1708 7, TRUE /* update editable (always) */,
1709 8, FALSE /* current not editable (only for top-level) */,
1710 -1);
1711 }
1712}
1713
1714
1715/**
1716 * Add all updateable entries of the current namespace to the
1717 * tree store.
1718 *
1719 * @param cls the 'GtkTreeStore' to update
1720 * @param name name of the namespace to add
1721 * @param id identity of the namespace to add
1722 */
1723static void
1724add_namespace_to_ts (void *cls,
1725 const char *name,
1726 const GNUNET_HashCode *id)
1727{
1728 GtkTreeStore *ts = cls;
1729 struct UpdateableContext uc;
1730 GtkTreeIter iter;
1731
1732 uc.parent = &iter;
1733 uc.namespace_name = name;
1734 uc.ts = ts;
1735 uc.ns = GNUNET_FS_namespace_create (GNUNET_GTK_get_fs_handle (),
1736 name);
1737 uc.update_called = GNUNET_NO;
1738 gtk_tree_store_insert_with_values (ts, &iter,
1739 NULL,
1740 G_MAXINT,
1741 0, name,
1742 1, uc.ns,
1743 2, NULL /* last-id */,
1744 3, NULL /* last-uri */,
1745 4, NULL /* meta */,
1746 5, NULL /* next-ID */,
1747 6, NULL /* last-description */,
1748 7, TRUE /* update editable */,
1749 8, TRUE /* current editable */,
1750 -1);
1751 uc.seen = GNUNET_CONTAINER_multihashmap_create (128);
1752 GNUNET_FS_namespace_list_updateable (uc.ns, NULL,
1753 &add_updateable_to_ts, &uc);
1754 GNUNET_CONTAINER_multihashmap_destroy (uc.seen);
1755}
1756
1757
1758static void
1759free_pseudonym_tree_store (GtkTreeModel *tm,
1760 GtkTreeIter *iter)
1761{
1762 struct GNUNET_FS_Uri *uri;
1763 struct GNUNET_CONTAINER_MetaData *meta;
1764 struct GNUNET_FS_Namespace *ns;
1765 GtkTreeIter child;
1766
1767 gtk_tree_model_get (tm,
1768 iter,
1769 1, &ns,
1770 3, &uri,
1771 4, &meta,
1772 -1);
1773 if (uri != NULL)
1774 GNUNET_FS_uri_destroy (uri);
1775 if (meta != NULL)
1776 GNUNET_CONTAINER_meta_data_destroy (meta);
1777 if (ns != NULL)
1778 {
1779 // FIXME: delete ns?
1780 // GNUNET_FS_namespace_delete (nso, GNUNET_NO);
1781 }
1782 if (TRUE ==
1783 gtk_tree_model_iter_children (tm, &child, iter))
1784 {
1785 do
1786 {
1787 free_pseudonym_tree_store (tm,
1788 &child);
1789 }
1790 while (TRUE == gtk_tree_model_iter_next (tm,
1791 &child));
1792 }
1793}
1794
1795
1796static void
1797free_file_information_tree_store (GtkTreeModel *tm,
1798 GtkTreeIter *iter)
1799{
1800 GtkTreeIter child;
1801 struct GNUNET_FS_FileInformation *fip;
1802
1803 gtk_tree_model_get (tm,
1804 iter,
1805 5, &fip,
1806 -1);
1807 if (fip != NULL)
1808 GNUNET_FS_file_information_destroy (fip, NULL, NULL);
1809 if (TRUE ==
1810 gtk_tree_model_iter_children (tm, &child, iter))
1811 {
1812 do
1813 {
1814 free_file_information_tree_store (tm,
1815 &child);
1816 }
1817 while (TRUE == gtk_tree_model_iter_next (tm,
1818 &child));
1819 }
1820}
1821
1822
1823/**
1824 */
1825void
1826GNUNET_GTK_main_menu_file_publish_activate_cb (GtkWidget * dummy,
1827 gpointer data)
1828{
1829 GtkWidget *ad;
1830 GtkTreeStore *ts;
1831 gint ret;
1832 GtkTreeView *tv;
1833 GtkTreeSelection *sel;
1834 GtkTreeIter iter;
1835 struct GNUNET_FS_FileInformation *fi;
1836 GtkTreeModel *tm;
1837 GtkTreeModel *ptm;
1838 struct GNUNET_FS_Namespace *namespace;
1839 gchar *namespace_id;
1840 gchar *namespace_uid;
1841
1842 GNUNET_assert (master_builder == NULL);
1843 master_builder = GNUNET_GTK_get_new_builder ("publish_dialog.glade");
1844 if (master_builder == NULL)
1845 return;
1846 tv = GTK_TREE_VIEW (gtk_builder_get_object (master_builder,
1847 "GNUNET_GTK_master_publish_dialog_file_information_tree_view"));
1848 sel = gtk_tree_view_get_selection (tv);
1849 g_signal_connect(G_OBJECT(sel), "changed",
1850 G_CALLBACK(selection_changed_cb), NULL);
1851 ad = GTK_WIDGET (gtk_builder_get_object (master_builder,
1852 "GNUNET_GTK_master_publish_dialog"));
1853 ts = GTK_TREE_STORE (gtk_builder_get_object (master_builder,
1854 "GNUNET_GTK_pseudonym_tree_store"));
1855 GNUNET_FS_namespace_list (GNUNET_GTK_get_fs_handle (),
1856 &add_namespace_to_ts,
1857 ts);
1858 tm = GTK_TREE_MODEL (gtk_builder_get_object (master_builder,
1859 "GNUNET_GTK_file_sharing_publishing_tree_store"));
1860 tv = GTK_TREE_VIEW (gtk_builder_get_object (master_builder,
1861 "GNUNET_GTK_master_publish_dialog_pseudonym_tree_view"));
1862 sel = gtk_tree_view_get_selection (tv);
1863 g_signal_connect(G_OBJECT(sel), "changed",
1864 G_CALLBACK(selection_changed_cb), NULL);
1865 ret = gtk_dialog_run (GTK_DIALOG (ad));
1866 if (ret == GTK_RESPONSE_OK)
1867 {
1868 if (TRUE == gtk_tree_selection_get_selected (sel, &ptm, &iter))
1869 {
1870 gtk_tree_model_get (ptm,
1871 &iter,
1872 1, &namespace,
1873 2, &namespace_id,
1874 5, &namespace_uid,
1875 -1);
1876 }
1877 else
1878 {
1879 namespace = NULL;
1880 namespace_id = NULL;
1881 namespace_uid = NULL;
1882 }
1883 if (gtk_tree_model_get_iter_first (tm, &iter))
1884 do
1885 {
1886 fi = get_file_information (tm, &iter);
1887 GNUNET_FS_publish_start (GNUNET_GTK_get_fs_handle (),
1888 fi,
1889 namespace,
1890 namespace_id,
1891 namespace_uid,
1892 GNUNET_FS_PUBLISH_OPTION_NONE);
1893 }
1894 while (gtk_tree_model_iter_next (tm, &iter));
1895 if (namespace_id != NULL)
1896 g_free (namespace_id);
1897 if (namespace_uid != NULL)
1898 g_free (namespace_uid);
1899 }
1900 ptm = GTK_TREE_MODEL (gtk_builder_get_object (master_builder,
1901 "GNUNET_GTK_pseudonym_tree_store"));
1902 /* free state from 'ptm' */
1903 if (TRUE ==
1904 gtk_tree_model_get_iter_first (ptm,
1905 &iter))
1906 do
1907 {
1908 free_pseudonym_tree_store (ptm,
1909 &iter);
1910 }
1911 while (TRUE == gtk_tree_model_iter_next (ptm,
1912 &iter));
1913
1914 /* free state from 'tm' */
1915 if (TRUE ==
1916 gtk_tree_model_get_iter_first (tm,
1917 &iter))
1918 do
1919 {
1920 free_file_information_tree_store (tm,
1921 &iter);
1922 }
1923 while (TRUE == gtk_tree_model_iter_next (tm,
1924 &iter));
1925
1926 gtk_widget_destroy (ad);
1927 g_object_unref (G_OBJECT (master_builder));
1928 master_builder = NULL;
1929}
1930
1931
1932/* end of main_window_file_publish.c */
diff --git a/src/main_window_file_search.c b/src/main_window_file_search.c
deleted file mode 100644
index 407310f1..00000000
--- a/src/main_window_file_search.c
+++ /dev/null
@@ -1,242 +0,0 @@
1/*
2 This file is part of GNUnet
3 (C) 2005, 2006, 2010 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/main_window_file_search.c
23 * @author Christian Grothoff
24 */
25#include "common.h"
26
27/**
28 * Builder used for the search dialog.
29 */
30static GtkBuilder *builder;
31
32
33/**
34 * User double-clicked on namespace or pressed enter;
35 * move namespace root to the 'keywords' line.
36 */
37void
38GNUNET_GTK_search_dialog_namespace_tree_view_row_activated_cb (GtkTreeView *tree_view,
39 GtkTreePath *path,
40 GtkTreeViewColumn *column,
41 gpointer user_data)
42{
43 GtkTreeModel *ls;
44 GtkTreeSelection *sel;
45 GtkEntry *query;
46 GtkTreeIter iter;
47 char *root;
48
49 query = GTK_ENTRY (gtk_builder_get_object (builder,
50 "GNUNET_GTK_search_dialog_keyword_entry"));
51 sel = gtk_tree_view_get_selection (tree_view);
52 if (TRUE ==
53 gtk_tree_selection_get_selected (sel,
54 &ls,
55 &iter))
56 {
57 gtk_tree_model_get (ls, &iter,
58 1, &root,
59 -1);
60 gtk_entry_set_text (query,
61 root);
62 GNUNET_free (root);
63 }
64}
65
66
67void
68GNUNET_GTK_search_dialog_search_button_clicked_cb (GtkWidget * dummy,
69 gpointer data)
70{
71 GtkEntry *query;
72 GtkSpinButton *anonymity;
73 GtkTreeView *namespace;
74 const char *keywords;
75 char *emsg;
76 struct GNUNET_FS_Uri *uri;
77 GNUNET_HashCode *nsid;
78 GtkTreeModel *ls;
79 GtkTreeSelection *sel;
80 GtkTreeIter iter;
81
82 query = GTK_ENTRY (gtk_builder_get_object (builder,
83 "GNUNET_GTK_search_dialog_keyword_entry"));
84 anonymity = GTK_SPIN_BUTTON (gtk_builder_get_object (builder,
85 "GNUNET_GTK_search_dialog_anonymity_spin_button"));
86 namespace = GTK_TREE_VIEW (gtk_builder_get_object (builder,
87 "GNUNET_GTK_search_dialog_namespace_tree_view"));
88 keywords = gtk_entry_get_text (query);
89 nsid = NULL;
90 sel = gtk_tree_view_get_selection (namespace);
91 if (TRUE ==
92 gtk_tree_selection_get_selected (sel,
93 &ls,
94 &iter))
95 gtk_tree_model_get (ls, &iter,
96 2, &nsid,
97 -1);
98 if (nsid != NULL)
99 {
100 uri = GNUNET_FS_uri_sks_create_from_nsid (nsid,
101 keywords);
102 GNUNET_assert (uri != NULL);
103 }
104 else
105 {
106 emsg = NULL;
107 uri = GNUNET_FS_uri_ksk_create (keywords, &emsg);
108 if (uri == NULL)
109 {
110 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
111 _("Invalid keyword string `%s': %s"),
112 keywords,
113 emsg);
114 GNUNET_free_non_null (emsg);
115 return;
116 }
117 }
118 GNUNET_FS_search_start (GNUNET_GTK_get_fs_handle (),
119 uri,
120 gtk_spin_button_get_value_as_int (anonymity),
121 GNUNET_FS_SEARCH_OPTION_NONE,
122 NULL);
123 GNUNET_FS_uri_destroy (uri);
124}
125
126
127
128/**
129 * Add pseudonym data to list store
130 *
131 * @param cls closure (the 'GtkListStore')
132 * @param pseudonym hash code of public key of pseudonym
133 * @param md meta data known about the pseudonym
134 * @param rating the local rating of the pseudonym
135 * @return GNUNET_OK to continue iteration, GNUNET_SYSERR to abort
136 */
137static int
138add_namespace_to_ls (void *cls,
139 const GNUNET_HashCode *
140 pseudonym,
141 const struct
142 GNUNET_CONTAINER_MetaData * md,
143 int rating)
144{
145 GtkListStore *ls = cls;
146 char *root;
147 char *ns_name;
148 GNUNET_HashCode *nsid;
149 char *description;
150 char *uris;
151 char *emsg;
152 struct GNUNET_FS_Uri *uri;
153 GtkTreeIter iter;
154
155 ns_name = GNUNET_PSEUDONYM_id_to_name (GNUNET_GTK_get_configuration (),
156 pseudonym);
157 nsid = GNUNET_malloc (sizeof (GNUNET_HashCode));
158 *nsid = *pseudonym;
159 root = NULL;
160 uris = GNUNET_CONTAINER_meta_data_get_by_type (md,
161 EXTRACTOR_METATYPE_URI);
162 if (uris != NULL)
163 {
164 emsg = NULL;
165 uri = GNUNET_FS_uri_parse (uris, &emsg);
166 if (uri == NULL)
167 GNUNET_free (emsg);
168 root = GNUNET_FS_uri_sks_get_content_id (uri);
169 GNUNET_FS_uri_destroy (uri);
170 }
171 description = GNUNET_CONTAINER_meta_data_get_first_by_types (md,
172 EXTRACTOR_METATYPE_TITLE,
173 EXTRACTOR_METATYPE_BOOK_TITLE,
174 EXTRACTOR_METATYPE_DESCRIPTION,
175 EXTRACTOR_METATYPE_SUMMARY,
176 EXTRACTOR_METATYPE_ALBUM,
177 EXTRACTOR_METATYPE_COMMENT,
178 EXTRACTOR_METATYPE_SUBJECT,
179 EXTRACTOR_METATYPE_KEYWORDS,
180 -1);
181 gtk_list_store_insert_with_values (ls,
182 &iter,
183 G_MAXINT,
184 0, ns_name,
185 1, root,
186 2, nsid,
187 3, description,
188 -1);
189 GNUNET_free (ns_name);
190 GNUNET_free_non_null (root);
191 GNUNET_free_non_null (description);
192 return GNUNET_OK;
193}
194
195
196/**
197 * Search selected in 'file' menu.
198 */
199void
200GNUNET_GTK_main_menu_file_search_activate_cb (GtkWidget * dummy,
201 gpointer data)
202{
203 GtkWidget *ad;
204 GtkListStore *ls;
205 GtkTreeIter iter;
206 GNUNET_HashCode *nsid;
207
208 GNUNET_assert (builder == NULL);
209 builder = GNUNET_GTK_get_new_builder ("search_dialog.glade");
210 if (builder == NULL)
211 return;
212 ad = GTK_WIDGET (gtk_builder_get_object (builder,
213 "GNUNET_GTK_search_dialog"));
214 ls = GTK_LIST_STORE (gtk_builder_get_object (builder,
215 "GNUNET_GTK_namespace_list_store"));
216 GNUNET_PSEUDONYM_list_all (GNUNET_GTK_get_configuration (),
217 &add_namespace_to_ls,
218 ls);
219 gtk_dialog_run (GTK_DIALOG (ad));
220
221 /* free nsids from 'ls' */
222 if (TRUE ==
223 gtk_tree_model_get_iter_first (GTK_TREE_MODEL (ls),
224 &iter))
225 {
226 do
227 {
228 gtk_tree_model_get (GTK_TREE_MODEL (ls),
229 &iter,
230 2, &nsid,
231 -1);
232 GNUNET_free (nsid);
233 }
234 while (TRUE == gtk_tree_model_iter_next (GTK_TREE_MODEL (ls),
235 &iter));
236 }
237 gtk_widget_destroy (ad);
238 g_object_unref (G_OBJECT (builder));
239 builder = NULL;
240}
241
242/* end of main_window_file_search.c */
diff --git a/src/main_window_open_directory.c b/src/main_window_open_directory.c
deleted file mode 100644
index d9d90cff..00000000
--- a/src/main_window_open_directory.c
+++ /dev/null
@@ -1,147 +0,0 @@
1/*
2 This file is part of GNUnet
3 (C) 2005, 2006, 2010 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/main_window_open_directory.c
23 * @author Christian Grothoff
24 */
25#include "common.h"
26#include "fs_event_handler.h"
27
28struct AddChildContext
29{
30 const char *filename;
31 GtkTreeStore *ts;
32 struct SearchTab *tab;
33 struct SearchResult *par;
34 GtkTreeRowReference *prr;
35 GtkTreeIter iter;
36};
37
38
39/**
40 * Function used to process entries in a directory.
41 *
42 * @param cls closure, our 'struct AddChildContext*'
43 * @param filename name of the file in the directory
44 * @param uri URI of the file
45 * @param metadata metadata for the file; metadata for
46 * the directory if everything else is NULL/zero
47 * @param length length of the available data for the file
48 * (of type size_t since data must certainly fit
49 * into memory; if files are larger than size_t
50 * permits, then they will certainly not be
51 * embedded with the directory itself).
52 * @param data data available for the file (length bytes)
53 */
54static void
55add_child (void *cls,
56 const char *filename,
57 const struct GNUNET_FS_Uri *uri,
58 const struct GNUNET_CONTAINER_MetaData *meta,
59 size_t length,
60 const void *data)
61{
62 struct AddChildContext *acc = cls;
63 struct GNUNET_CONTAINER_MetaData *dmeta;
64 GtkTreePath *tp;
65 GtkTreeIter iter;
66
67 if (uri == NULL)
68 {
69 /* directory meta data itself */
70 dmeta = GNUNET_CONTAINER_meta_data_duplicate (meta);
71 GNUNET_CONTAINER_meta_data_insert (dmeta,
72 "<user>",
73 EXTRACTOR_METATYPE_FILENAME,
74 EXTRACTOR_METAFORMAT_C_STRING,
75 "text/plain",
76 acc->filename,
77 strlen (acc->filename) + 1);
78 acc->tab = GNUNET_GTK_add_to_uri_tab (&acc->iter,
79 &acc->par,
80 dmeta,
81 NULL);
82 tp = gtk_tree_model_get_path (GTK_TREE_MODEL (acc->tab->ts),
83 &acc->iter);
84 acc->prr = gtk_tree_row_reference_new (GTK_TREE_MODEL (acc->tab->ts),
85 tp);
86 gtk_tree_path_free (tp);
87 acc->ts = acc->tab->ts;
88 GNUNET_CONTAINER_meta_data_destroy (dmeta);
89 return;
90 }
91 if (acc->ts == NULL)
92 return;
93 GNUNET_assert (NULL !=
94 GNUNET_GTK_add_search_result (acc->tab,
95 &iter,
96 acc->prr,
97 uri,
98 meta,
99 NULL,
100 0));
101}
102
103
104/**
105 * User selected "Open directory" in menu. Display dialog, open
106 * file and then display a new tab with its contents.
107 */
108void
109GNUNET_GTK_main_menu_file_open_gnunet_directory_activate_cb (GtkWidget * dummy,
110 gpointer data)
111{
112 struct AddChildContext acc;
113 GtkWidget *ad;
114 GtkBuilder *builder;
115 char *filename;
116 GtkFileFilter *ff;
117
118 builder = GNUNET_GTK_get_new_builder ("open_directory_dialog.glade");
119 if (builder == NULL)
120 {
121 GNUNET_break (0);
122 return;
123 }
124 ad = GTK_WIDGET (gtk_builder_get_object (builder,
125 "GNUNET_GTK_open_directory_dialog"));
126 ff = GTK_FILE_FILTER (gtk_builder_get_object (builder,
127 "gnunet_directory_filter"));
128 /* FIXME: some day, write a custom file filter for gnunet-directories... */
129 gtk_file_filter_add_pattern (ff, "*" GNUNET_FS_DIRECTORY_EXT);
130 if (GTK_RESPONSE_OK != gtk_dialog_run (GTK_DIALOG (ad)))
131 {
132 gtk_widget_destroy (ad);
133 g_object_unref (G_OBJECT (builder));
134 return;
135 }
136 filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER(ad));
137 gtk_widget_destroy (ad);
138 g_object_unref (G_OBJECT (builder));
139 acc.filename = filename;
140 acc.ts = NULL;
141 GNUNET_GTK_mmap_and_scan (filename,
142 &add_child,
143 &acc);
144 g_free (filename);
145}
146
147/* end of main_window_open_directory.c */
diff --git a/src/main_window_view_toggles.c b/src/main_window_view_toggles.c
deleted file mode 100644
index fd974180..00000000
--- a/src/main_window_view_toggles.c
+++ /dev/null
@@ -1,89 +0,0 @@
1/*
2 This file is part of GNUnet
3 (C) 2005, 2006, 2010 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/main_window_view_toggles.c
23 * @author Christian Grothoff
24 *
25 * This file contains callbacks for the 'view' menu that toggle views.
26 */
27#include "common.h"
28
29
30/**
31 * Toggle the visibility of a widget based on the checkeness
32 * of a menu item.
33 *
34 * @param toggled_widget name of widget to toggle
35 * @param toggle_menu name of menu entry
36 */
37static void
38toggle_view (const char *toggled_widget,
39 const char *toggle_menu)
40{
41 GtkCheckMenuItem *mi;
42 GtkWidget *widget;
43
44 widget = GTK_WIDGET (GNUNET_GTK_get_main_window_object (toggled_widget));
45 mi = GTK_CHECK_MENU_ITEM (GNUNET_GTK_get_main_window_object (toggle_menu));
46 if (gtk_check_menu_item_get_active (mi))
47 gtk_widget_show (widget);
48 else
49 gtk_widget_hide (widget);
50}
51
52
53/**
54 * Preview view is toggled.
55 */
56void
57GNUNET_GTK_main_menu_view_preview_toggled_cb (GtkWidget * dummy,
58 gpointer data)
59{
60 toggle_view ("GNUNET_GTK_main_window_preview_image",
61 "GNUNET_GTK_main_menu_view_preview");
62}
63
64
65/**
66 * Neighbour view is toggled.
67 */
68void
69GNUNET_GTK_main_menu_view_neighbours_toggled_cb (GtkWidget * dummy,
70 gpointer data)
71{
72 toggle_view ("GNUNET_GTK_main_window_peerinfo_treeview",
73 "GNUNET_GTK_main_menu_view_neighbours");
74}
75
76
77/**
78 * Metadata view is toggled.
79 */
80void
81GNUNET_GTK_main_menu_view_metadata_toggled_cb (GtkWidget * dummy,
82 gpointer data)
83{
84 toggle_view ("GNUNET_GTK_main_window_metadata_treeview",
85 "GNUNET_GTK_main_menu_view_metadata");
86}
87
88
89/* end of main_window_view_toggles.c */
diff --git a/src/os_installation.c b/src/os_installation.c
deleted file mode 100644
index af065e7e..00000000
--- a/src/os_installation.c
+++ /dev/null
@@ -1,441 +0,0 @@
1/*
2 This file is part of GNUnet.
3 (C) 2006, 2010 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/os_installation.c
23 * @brief get paths used by the program; this code is almost the
24 * same as src/util/os_installation.c in libgnunetutil; however,
25 * it contains sublte changes to detect the installation path
26 * of gnunet-gtk (which may be different from the path for
27 * GNUnet itself) and also needs to be replicated anyway since
28 * some of the methods try to find the location of the binary
29 * of the test-code itself, which would never yield the
30 * correct result for gnunet-gtk if the code lives in libgnunetutil.
31 * @author Milan
32 * @author Christian Grothoff
33 */
34
35#include "common.h"
36#include <sys/stat.h>
37#include <stdlib.h>
38#include <string.h>
39#include <unistd.h>
40#include <gnunet/gnunet_util_lib.h>
41#if DARWIN
42#include <mach-o/ldsyms.h>
43#include <mach-o/dyld.h>
44#endif
45
46#if LINUX
47/**
48 * Try to determine path by reading /proc/PID/exe
49 */
50static char *
51get_path_from_proc_maps ()
52{
53 char fn[64];
54 char line[1024];
55 char dir[1024];
56 FILE *f;
57 char *lgu;
58
59 GNUNET_snprintf (fn,
60 sizeof(fn),
61 "/proc/%u/maps",
62 getpid ());
63 f = fopen (fn, "r");
64 if (f == NULL)
65 return NULL;
66 while (NULL != fgets (line, sizeof(line), f))
67 {
68 if ((1 == sscanf (line,
69 "%*x-%*x %*c%*c%*c%*c %*x %*2u:%*2u %*u%*[ ]%s",
70 dir)) &&
71 (NULL != (lgu = strstr (dir, "gnunet-gtk"))))
72 {
73 lgu[0] = '\0';
74 fclose (f);
75 return GNUNET_strdup (dir);
76 }
77 }
78 fclose (f);
79 return NULL;
80}
81
82/**
83 * Try to determine path by reading /proc/PID/exe
84 */
85static char *
86get_path_from_proc_exe ()
87{
88 char fn[64];
89 char lnk[1024];
90 ssize_t size;
91
92 GNUNET_snprintf (fn,
93 sizeof(fn), "/proc/%u/exe", getpid ());
94 size = readlink (fn, lnk, sizeof (lnk)-1);
95 if (size <= 0)
96 {
97 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "readlink", fn);
98 return NULL;
99 }
100 GNUNET_assert (size < sizeof (lnk));
101 lnk[size] = '\0';
102 while ((lnk[size] != '/') && (size > 0))
103 size--;
104 if ((size < 4) || (lnk[size - 4] != '/'))
105 {
106 /* not installed in "/bin/" -- binary path probably useless */
107 return NULL;
108 }
109 lnk[size] = '\0';
110 return GNUNET_strdup (lnk);
111}
112#endif
113
114#if WINDOWS
115/**
116 * Try to determine path with win32-specific function
117 */
118static char *
119get_path_from_module_filename ()
120{
121 char path[4097];
122 char *idx;
123
124 GetModuleFileName (NULL, path, sizeof(path)-1);
125 idx = path + strlen (path);
126 while ((idx > path) && (*idx != '\\') && (*idx != '/'))
127 idx--;
128 *idx = '\0';
129 return GNUNET_strdup (path);
130}
131#endif
132
133#if DARWIN
134typedef int (*MyNSGetExecutablePathProto) (char *buf, size_t * bufsize);
135
136static char *
137get_path_from_NSGetExecutablePath ()
138{
139 static char zero = '\0';
140 char *path;
141 size_t len;
142 MyNSGetExecutablePathProto func;
143 int ret;
144
145 path = NULL;
146 func =
147 (MyNSGetExecutablePathProto) dlsym (RTLD_DEFAULT, "_NSGetExecutablePath");
148 if (!func)
149 return NULL;
150 path = &zero;
151 len = 0;
152 /* get the path len, including the trailing \0 */
153 func (path, &len);
154 if (len == 0)
155 return NULL;
156 path = GNUNET_malloc (len);
157 ret = func (path, &len);
158 if (ret != 0)
159 {
160 GNUNET_free (path);
161 return NULL;
162 }
163 len = strlen (path);
164 while ((path[len] != '/') && (len > 0))
165 len--;
166 path[len] = '\0';
167 return path;
168}
169
170static char *
171get_path_from_dyld_image ()
172{
173 const char *path;
174 char *p, *s;
175 int i;
176 int c;
177
178 p = NULL;
179 c = _dyld_image_count ();
180 for (i = 0; i < c; i++)
181 {
182 if (_dyld_get_image_header (i) == &_mh_dylib_header)
183 {
184 path = _dyld_get_image_name (i);
185 if (path != NULL && strlen (path) > 0)
186 {
187 p = strdup (path);
188 s = p + strlen (p);
189 while ((s > p) && (*s != '/'))
190 s--;
191 s++;
192 *s = '\0';
193 }
194 break;
195 }
196 }
197 return p;
198}
199#endif
200
201static char *
202get_path_from_PATH ()
203{
204 char *path;
205 char *pos;
206 char *end;
207 char *buf;
208 const char *p;
209
210 p = getenv ("PATH");
211 if (p == NULL)
212 return NULL;
213 path = GNUNET_strdup (p); /* because we write on it */
214 buf = GNUNET_malloc (strlen (path) + 20);
215 pos = path;
216
217 while (NULL != (end = strchr (pos, ':')))
218 {
219 *end = '\0';
220 sprintf (buf, "%s/%s", pos, "gnunet-gtk");
221 if (GNUNET_DISK_file_test (buf) == GNUNET_YES)
222 {
223 pos = GNUNET_strdup (pos);
224 GNUNET_free (buf);
225 GNUNET_free (path);
226 return pos;
227 }
228 pos = end + 1;
229 }
230 sprintf (buf, "%s/%s", pos, "gnunet-gtk");
231 if (GNUNET_DISK_file_test (buf) == GNUNET_YES)
232 {
233 pos = GNUNET_strdup (pos);
234 GNUNET_free (buf);
235 GNUNET_free (path);
236 return pos;
237 }
238 GNUNET_free (buf);
239 GNUNET_free (path);
240 return NULL;
241}
242
243static char *
244get_path_from_GNUNET_PREFIX ()
245{
246 const char *p;
247
248 p = getenv ("GNUNET_GTK_PREFIX");
249 if (p != NULL)
250 return GNUNET_strdup (p);
251 p = getenv ("GNUNET_PREFIX");
252 if (p != NULL)
253 return GNUNET_strdup (p);
254 return NULL;
255}
256
257/*
258 * @brief get the path to GNUnet bin/ or lib/, prefering the lib/ path
259 * @author Milan
260 *
261 * @return a pointer to the executable path, or NULL on error
262 */
263static char *
264os_get_gnunet_path ()
265{
266 char *ret;
267
268 ret = get_path_from_GNUNET_PREFIX ();
269 if (ret != NULL)
270 return ret;
271#if LINUX
272 ret = get_path_from_proc_maps ();
273 if (ret != NULL)
274 return ret;
275 ret = get_path_from_proc_exe ();
276 if (ret != NULL)
277 return ret;
278#endif
279#if WINDOWS
280 ret = get_path_from_module_filename ();
281 if (ret != NULL)
282 return ret;
283#endif
284#if DARWIN
285 ret = get_path_from_dyld_image ();
286 if (ret != NULL)
287 return ret;
288 ret = get_path_from_NSGetExecutablePath ();
289 if (ret != NULL)
290 return ret;
291#endif
292 ret = get_path_from_PATH ();
293 if (ret != NULL)
294 return ret;
295 /* other attempts here */
296 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
297 _
298 ("Could not determine installation path for %s. Set `%s' environment variable.\n"),
299 "gnunet-gtk",
300 "GNUNET_GTK_PREFIX");
301 return NULL;
302}
303
304/*
305 * @brief get the path to current app's bin/
306 * @author Milan
307 *
308 * @return a pointer to the executable path, or NULL on error
309 */
310static char *
311os_get_exec_path ()
312{
313 char *ret;
314
315 ret = NULL;
316#if LINUX
317 ret = get_path_from_proc_exe ();
318 if (ret != NULL)
319 return ret;
320#endif
321#if WINDOWS
322 ret = get_path_from_module_filename ();
323 if (ret != NULL)
324 return ret;
325#endif
326#if DARWIN
327 ret = get_path_from_NSGetExecutablePath ();
328 if (ret != NULL)
329 return ret;
330#endif
331 /* other attempts here */
332 return ret;
333}
334
335
336
337/**
338 * @brief get the path to a specific GNUnet installation directory or,
339 * with GNUNET_IPK_SELF_PREFIX, the current running apps installation directory
340 * @author Milan
341 * @return a pointer to the dir path (to be freed by the caller)
342 */
343char *
344GNUNET_GTK_installation_get_path (enum GNUNET_OS_InstallationPathKind dirkind)
345{
346 size_t n;
347 const char *dirname;
348 char *execpath = NULL;
349 char *tmp;
350 int isbasedir;
351
352 /* if wanted, try to get the current app's bin/ */
353 if (dirkind == GNUNET_OS_IPK_SELF_PREFIX)
354 execpath = os_get_exec_path ();
355
356 /* try to get GNUnet's bin/ or lib/, or if previous was unsuccessful some
357 * guess for the current app */
358 if (execpath == NULL)
359 execpath = os_get_gnunet_path ();
360
361 if (execpath == NULL)
362 return NULL;
363
364 n = strlen (execpath);
365 if (n == 0)
366 {
367 /* should never happen, but better safe than sorry */
368 GNUNET_free (execpath);
369 return NULL;
370 }
371 /* remove filename itself */
372 while ((n > 1) && (execpath[n - 1] == DIR_SEPARATOR))
373 execpath[--n] = '\0';
374
375 isbasedir = 1;
376 if ((n > 5) &&
377 ((0 == strcasecmp (&execpath[n - 5], "lib32")) ||
378 (0 == strcasecmp (&execpath[n - 5], "lib64"))))
379 {
380 if (dirkind != GNUNET_OS_IPK_LIBDIR)
381 {
382 /* strip '/lib32' or '/lib64' */
383 execpath[n - 5] = '\0';
384 n -= 5;
385 }
386 else
387 isbasedir = 0;
388 }
389 else if ((n > 3) &&
390 ((0 == strcasecmp (&execpath[n - 3], "bin")) ||
391 (0 == strcasecmp (&execpath[n - 3], "lib"))))
392 {
393 /* strip '/bin' or '/lib' */
394 execpath[n - 3] = '\0';
395 n -= 3;
396 }
397 /* in case this was a directory named foo-bin, remove "foo-" */
398 while ((n > 1) && (execpath[n - 1] == DIR_SEPARATOR))
399 execpath[--n] = '\0';
400 switch (dirkind)
401 {
402 case GNUNET_OS_IPK_PREFIX:
403 case GNUNET_OS_IPK_SELF_PREFIX:
404 dirname = DIR_SEPARATOR_STR;
405 break;
406 case GNUNET_OS_IPK_BINDIR:
407 dirname = DIR_SEPARATOR_STR "bin" DIR_SEPARATOR_STR;
408 break;
409 case GNUNET_OS_IPK_LIBDIR:
410 if (isbasedir)
411 dirname =
412 DIR_SEPARATOR_STR "lib" DIR_SEPARATOR_STR "gnunet-gtk"
413 DIR_SEPARATOR_STR;
414 else
415 dirname = DIR_SEPARATOR_STR "gnunet-gtk" DIR_SEPARATOR_STR;
416 break;
417 case GNUNET_OS_IPK_DATADIR:
418 dirname =
419 DIR_SEPARATOR_STR "share" DIR_SEPARATOR_STR "gnunet-gtk"
420 DIR_SEPARATOR_STR;
421 break;
422 case GNUNET_OS_IPK_ICONDIR:
423 dirname =
424 DIR_SEPARATOR_STR "share" DIR_SEPARATOR_STR "icons" DIR_SEPARATOR_STR;
425 break;
426 case GNUNET_OS_IPK_LOCALEDIR:
427 dirname =
428 DIR_SEPARATOR_STR "share" DIR_SEPARATOR_STR "locale"
429 DIR_SEPARATOR_STR;
430 break;
431 default:
432 GNUNET_free (execpath);
433 return NULL;
434 }
435 tmp = GNUNET_malloc (strlen (execpath) + strlen (dirname) + 1);
436 sprintf (tmp, "%s%s", execpath, dirname);
437 GNUNET_free (execpath);
438 return tmp;
439}
440
441/* end of os_installation.c */
diff --git a/src/peerinfo.c b/src/peerinfo.c
deleted file mode 100644
index 147144cd..00000000
--- a/src/peerinfo.c
+++ /dev/null
@@ -1,90 +0,0 @@
1/*
2 This file is part of GNUnet.
3 (C) 2010 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/peerinfo.c
23 * @brief Updates the peerinfo view
24 * @author Christian Grothoff
25 */
26#include "peerinfo.h"
27
28/**
29 * Function called for peers that we know about.
30 *
31 * @param cls closure
32 * @param peer id of the peer, NULL for last call
33 * @param hello hello message for the peer (can be NULL)
34 * @param err_msg NULL if successful, otherwise contains error message
35 */
36void
37GNUNET_GTK_peerinfo_processor (void *cls,
38 const struct GNUNET_PeerIdentity * peer,
39 const struct GNUNET_HELLO_Message * hello,
40 const char * err_msg)
41{
42 GtkListStore *ls;
43 GtkTreeModel *tm;
44 GtkTreeIter iter;
45 int found;
46 gchar *pid;
47 const char *npid;
48 struct GNUNET_CRYPTO_HashAsciiEncoded enc;
49
50 GNUNET_CRYPTO_hash_to_enc (&peer->hashPubKey,
51 &enc);
52 npid = (const char*) &enc;
53 ls = GTK_LIST_STORE (GNUNET_GTK_get_main_window_object ("GNUNET_GTK_peer_info_list_store"));
54 tm = GTK_TREE_MODEL (ls);
55 found = GNUNET_NO;
56 if (TRUE == gtk_tree_model_get_iter_first (tm, &iter))
57 {
58 do
59 {
60 pid = NULL;
61 gtk_tree_model_get (tm,
62 &iter,
63 0, &pid, -1);
64 if (pid != NULL)
65 {
66 if (0 == strcmp (pid, npid))
67 {
68 found = GNUNET_YES;
69 g_free (pid);
70 break;
71 }
72 }
73 g_free (pid);
74 }
75 while ( (found == GNUNET_NO) &&
76 (TRUE == gtk_tree_model_iter_next (tm,
77 &iter)));
78 }
79 if (found == GNUNET_NO)
80 gtk_list_store_append (ls, &iter);
81 gtk_list_store_set (ls,
82 &iter,
83 0, npid,
84 1, 0 /* number of known addresses */,
85 2, "" /* country name */,
86 3, NULL /* country flag */,
87 -1);
88}
89
90/* end of peerinfo.c */
diff --git a/src/peerinfo.h b/src/peerinfo.h
deleted file mode 100644
index b620822f..00000000
--- a/src/peerinfo.h
+++ /dev/null
@@ -1,47 +0,0 @@
1/*
2 This file is part of GNUnet.
3 (C) 2010 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/peerinfo.h
23 * @brief Updates the peerinfo view
24 * @author Christian Grothoff
25 */
26#ifndef PEERINFO_H
27#define PEERINFO_H
28
29#include "common.h"
30#include <gnunet/gnunet_peerinfo_service.h>
31
32/**
33 * Function called for peers that we know about.
34 *
35 * @param cls closure
36 * @param peer id of the peer, NULL for last call
37 * @param hello hello message for the peer (can be NULL)
38 * @param err_msg NULL if successful, otherwise contains error message
39 */
40void
41GNUNET_GTK_peerinfo_processor (void *cls,
42 const struct GNUNET_PeerIdentity * peer,
43 const struct GNUNET_HELLO_Message * hello,
44 const char * err_msg);
45
46/* end of peerinfo.h */
47#endif