From 5c5f49c95a5def2db09459fa9ce92301c3d8d4d6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=A0=D1=83=D1=81=D0=BB=D0=B0=D0=BD=20=D0=98=D0=B6=D0=B1=D1?=
 =?UTF-8?q?=83=D0=BB=D0=B0=D1=82=D0=BE=D0=B2?= <lrn1986@gmail.com>
Date: Sat, 24 Dec 2011 23:07:30 +0400
Subject: [PATCH] Temporary fix for charset conversion

---
 src/fs/gnunet-fs-gtk-common.c                      |   87 ++++++----
 src/fs/gnunet-fs-gtk-common.h                      |   18 ++
 src/fs/gnunet-fs-gtk-download.c                    |   10 +-
 src/fs/gnunet-fs-gtk-edit_publish_dialog.c         |    5 +-
 src/fs/gnunet-fs-gtk-event_handler.c               |   36 ++++-
 src/fs/gnunet-fs-gtk-main_window_adv_pseudonym.c   |    6 +-
 .../gnunet-fs-gtk-main_window_create_pseudonym.c   |   10 +-
 src/fs/gnunet-fs-gtk-main_window_file_publish.c    |   53 ++++++-
 src/fs/gnunet-fs-gtk-main_window_open_directory.c  |   10 +-
 src/fs/gnunet-fs-gtk.c                             |   21 ++-
 src/include/gnunet_gtk.h                           |   28 ++++
 src/lib/nls.c                                      |  167 ++++++++++++++++++++
 12 files changed, 391 insertions(+), 60 deletions(-)

diff --git a/src/fs/gnunet-fs-gtk-common.c b/src/fs/gnunet-fs-gtk-common.c
index b2bf9b2..bd33d17 100644
--- a/src/fs/gnunet-fs-gtk-common.c
+++ b/src/fs/gnunet-fs-gtk-common.c
@@ -26,6 +26,53 @@
 #include "gnunet-fs-gtk-common.h"
 
 /**
+ * Converts metadata specified by @data of size @data_len
+ * and saved in format @format to UTF-8 encoded string.
+ * Works only for C-string and UTF8 metadata formats
+ * (returns NULL for everything else).
+ * Verifies UTF-8 strings.
+ *
+ * @param format format of the @data
+ * @param data data to convert
+ * @param data_len length of the data buffer (in bytes)
+ * @return NULL if can't be converted, allocated string otherwise,
+ *         freeable with GNUNET_free* ().
+ */
+char *
+GNUNET_FS_GTK_dubious_meta_to_utf8 (enum EXTRACTOR_MetaFormat format, const char *data, size_t data_len)
+{
+  gchar *result = NULL;
+
+  if (format == EXTRACTOR_METAFORMAT_UTF8)
+  {
+    /* data must not contain NULLs (hence the -1) */
+    if (g_utf8_validate (data, data_len - 1, NULL))
+      result = GNUNET_strdup (data);
+    else
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+          "Failed to validate supposedly utf-8 string `%s' of length %u, assuming it to be a C string\n",
+          data, data_len);
+      format = EXTRACTOR_METAFORMAT_C_STRING;
+    }
+  }
+  if (format == EXTRACTOR_METAFORMAT_C_STRING)
+  {
+    if (data_len > 0)
+    { /* There are no guarantees that data is NULL-terminated, AFAIU,
+       * so let's play it safe, shall we?
+       */
+      char *data_copy = GNUNET_malloc (data_len + 1);
+      memcpy (data_copy, data, data_len);
+      data_copy[data_len] = '\0';
+      result = GNUNET_GTK_from_loc_to_utf8 (data_copy);
+      GNUNET_free (data_copy);
+    }
+  }
+  return result;
+}
+
+/**
  * Add meta data to list store.
  *
  * @param cls closure (the GtkListStore)
@@ -49,44 +96,17 @@ GNUNET_FS_GTK_add_meta_data_to_list_store (void *cls, const char *plugin_name,
                                            const char *data, size_t data_len)
 {
   GtkListStore *ls = GTK_LIST_STORE (cls);
-  const gchar *data_to_insert = NULL;
-  gchar *free_data = NULL;
-  gsize rd;
-  gsize wr;
+  gchar *data_to_insert = NULL;
 
-  if (format == EXTRACTOR_METAFORMAT_UTF8)
-  {
-    if (g_utf8_validate (data, data_len, NULL))
-      data_to_insert = data;
-    else
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-          "Failed to validate supposedly utf-8 string `%s' of length %u, assuming it to be a C string\n",
-          data, data_len);
-      format = EXTRACTOR_METAFORMAT_C_STRING;
-    }
-  }
-  if (format == EXTRACTOR_METAFORMAT_C_STRING)
-  {
-    GError *gerr = NULL;
-    rd = wr = 0;
-    free_data = g_locale_to_utf8 (data, data_len, &rd, &wr, &gerr);
-    if (gerr != NULL)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-          "Error when converting a C string `%s' of length %u to utf-8 (converted %u to %u bytes): %s\n",
-          data, data_len, rd, wr, gerr->message);
-      g_error_free (gerr);
-    }
-    data_to_insert = free_data;
-  }
+  data_to_insert = GNUNET_FS_GTK_dubious_meta_to_utf8 (format, data, data_len);
 
   if (NULL != data_to_insert)  
+  {
     gtk_list_store_insert_with_values (ls, NULL, G_MAXINT, 0, type, 1, format,
                                        2, EXTRACTOR_metatype_to_string (type),
-                                       3, data_to_insert, -1);  
-  if (NULL != free_data)
-    g_free (free_data);
+                                       3, data_to_insert, -1);
+    g_free (data_to_insert);
+  }
 
   return 0;
 }
@@ -194,5 +214,4 @@ GNUNET_FS_GTK_mmap_and_scan (const char *filename,
   GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (fh));
 }
 
-
 /* end of gnunet-fs-gtk-common.c */
diff --git a/src/fs/gnunet-fs-gtk-common.h b/src/fs/gnunet-fs-gtk-common.h
index 9484b0e..d0d7b4f 100644
--- a/src/fs/gnunet-fs-gtk-common.h
+++ b/src/fs/gnunet-fs-gtk-common.h
@@ -101,5 +101,23 @@ GNUNET_FS_GTK_add_meta_data_to_list_store (void *cls, const char *plugin_name,
                                            const char *data_mime_type,
                                            const char *data, size_t data_len);
 
+/**
+ * Converts metadata specified by @data of size @data_len
+ * and saved in format @format to UTF-8 encoded string.
+ * Works only for C-string and UTF8 metadata formats
+ * (returns NULL for everything else).
+ * Verifies UTF-8 strings.
+ *
+ * @param format format of the @data
+ * @param data data to convert
+ * @param data_len length of the data buffer (in bytes)
+ * @return NULL if can't be converted, allocated string otherwise,
+ *         freeable with GNUNET_free* ().
+ */
+char *
+GNUNET_FS_GTK_dubious_meta_to_utf8 (enum EXTRACTOR_MetaFormat format,
+    const char *data, size_t data_len);
+
+
 #endif
 /* end of gnunet-fs-gtk-common.h */
diff --git a/src/fs/gnunet-fs-gtk-download.c b/src/fs/gnunet-fs-gtk-download.c
index 3f5f213..09ae7e1 100644
--- a/src/fs/gnunet-fs-gtk-download.c
+++ b/src/fs/gnunet-fs-gtk-download.c
@@ -73,7 +73,7 @@ GNUNET_GTK_save_as_dialog_delete_event_cb (GtkWidget *widget, GdkEvent  *event,
     return FALSE;
   }
   GNUNET_free_non_null (dc->filename);
-  dc->filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dlc->dialog));
+  dc->filename = GNUNET_GTK_filechooser_get_filename_loc (GTK_FILE_CHOOSER (dlc->dialog));
   dc->is_recursive =
       (TRUE ==
        gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (cb))) ? GNUNET_YES :
@@ -165,6 +165,7 @@ GNUNET_FS_GTK_open_download_as_dialog (struct DownloadContext *dc)
   if (dc->filename != NULL)
   {
     char buf[1024];
+    char *buf_utf8;
 
     if (NULL != getcwd (buf, sizeof (buf)))
     {
@@ -173,7 +174,12 @@ GNUNET_FS_GTK_open_download_as_dialog (struct DownloadContext *dc)
         strcat (buf, DIR_SEPARATOR_STR);
         strcat (buf, dc->filename);
       }
-      gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (ad), buf);
+      buf_utf8 = GNUNET_GTK_from_loc_to_utf8 (buf);
+      if (buf_utf8 != NULL)
+      {
+        gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (ad), buf_utf8);
+        GNUNET_free (buf_utf8);
+      }
     }
   }
   dlc = g_new0 (struct dialog_context, 1);
diff --git a/src/fs/gnunet-fs-gtk-edit_publish_dialog.c b/src/fs/gnunet-fs-gtk-edit_publish_dialog.c
index 8c0d76b..5324e3a 100644
--- a/src/fs/gnunet-fs-gtk-edit_publish_dialog.c
+++ b/src/fs/gnunet-fs-gtk-edit_publish_dialog.c
@@ -530,6 +530,7 @@ GNUNET_GTK_edit_publication_metadata_preview_file_chooser_button_file_set_cb (
                  (builder,
                   "GNUNET_GTK_edit_publication_metadata_preview_image"));
   gtk_image_set_from_file (image, fn);
+  g_free (fn);
   state->preview_changed = GNUNET_YES;
 }
 
@@ -589,7 +590,7 @@ preserve_meta_items (void *cls, const char *plugin_name,
     GNUNET_break (0);
     return 0;
   }
-
+  /* FIXME: make sure this is all correct UTF-8-wise */
   keep = GNUNET_NO;
   switch (format)
   {
@@ -808,6 +809,7 @@ file_information_update (void *cls, struct GNUNET_FS_FileInformation *fi,
     }
     g_object_unref (finfo);
     g_object_unref (f);
+    g_free (fn);
   }
   GNUNET_CONTAINER_meta_data_destroy (nm);
 
@@ -1016,6 +1018,7 @@ file_information_extract (void *cls, struct GNUNET_FS_FileInformation *fi,
 
 /**
  * Open the dialog to edit file information data.
+ * short_fn MUST be UTF-8-encoded
  */
 void
 GNUNET_FS_GTK_edit_publish_dialog (GtkBuilder *builder, 
diff --git a/src/fs/gnunet-fs-gtk-event_handler.c b/src/fs/gnunet-fs-gtk-event_handler.c
index 23129eb..631c342 100644
--- a/src/fs/gnunet-fs-gtk-event_handler.c
+++ b/src/fs/gnunet-fs-gtk-event_handler.c
@@ -548,6 +548,7 @@ setup_download (struct DownloadEntry *de, struct DownloadEntry *pde,
   GtkTreeIter iter;
   GtkTreePath *path;
   struct SearchResult *srp;
+  gchar *filename_utf8;
 
   if (de == NULL)
   {
@@ -587,13 +588,15 @@ setup_download (struct DownloadEntry *de, struct DownloadEntry *pde,
     return de;
   }
   gtk_tree_path_free (path);
+  filename_utf8 = GNUNET_GTK_from_loc_to_utf8 ((char *) filename);
   gtk_tree_store_set (de->ts, &iter, 4,
                       (guint) ((size >
                                 0) ? (100 * completed /
                                       size) : 100) /* progress */ ,
-		      6, filename /* filename/description */ ,
+		      6, filename_utf8 /* filename/description */ ,
                       8, "blue" /* status colour: pending */ ,
                       -1);
+  GNUNET_free_non_null (filename_utf8);
   return de;
 }
 
@@ -1111,6 +1114,7 @@ setup_search (struct GNUNET_FS_SearchContext *sc,
   }
   else
   {
+    /* FS_uri functions should produce UTF-8, so let them be */
     if (GNUNET_FS_uri_test_ksk (query))
       tab->query_txt = GNUNET_FS_uri_ksk_to_string_fancy (query);
     else
@@ -1291,6 +1295,16 @@ GNUNET_GTK_add_search_result (struct SearchTab *tab, GtkTreeIter * iter,
                                                      -1);
   if (desc == NULL)
     desc = GNUNET_strdup (_("no description supplied"));
+  else
+  {
+    char *utf8_desc = NULL;
+    utf8_desc = GNUNET_FS_GTK_dubious_meta_to_utf8 (EXTRACTOR_METAFORMAT_UTF8, desc, strlen (desc) + 1);
+    GNUNET_free (desc);
+    if (utf8_desc != NULL)
+      desc = utf8_desc;
+    else
+      desc = NULL;
+  }
   if (uri == NULL)
     uris = GNUNET_strdup (_("no URI"));
   else
@@ -1348,7 +1362,7 @@ GNUNET_GTK_add_search_result (struct SearchTab *tab, GtkTreeIter * iter,
   if (pixbuf != NULL)
     g_object_unref (pixbuf);
   GNUNET_free (uris);
-  GNUNET_free (desc);
+  GNUNET_free_non_null (desc);
   GNUNET_free_non_null (mime);
   tp = gtk_tree_model_get_path (GTK_TREE_MODEL (ts), iter);
   sr->rr = gtk_tree_row_reference_new (GTK_TREE_MODEL (ts), tp);
@@ -1468,6 +1482,16 @@ update_search_result (struct SearchResult *sr,
                                                      -1);
   if (desc == NULL)
     desc = GNUNET_strdup (_("no description supplied"));
+  else
+  {
+    char *utf8_desc = NULL;
+    utf8_desc = GNUNET_FS_GTK_dubious_meta_to_utf8 (EXTRACTOR_METAFORMAT_UTF8, desc, strlen (desc) + 1);
+    GNUNET_free (desc);
+    if (utf8_desc != NULL)
+      desc = utf8_desc;
+    else
+      desc = NULL;
+  }
   mime =
       GNUNET_CONTAINER_meta_data_get_first_by_types (meta,
                                                      EXTRACTOR_METATYPE_MIMETYPE,
@@ -1497,7 +1521,7 @@ update_search_result (struct SearchResult *sr,
                       (gint) availability_rank, -1);
   if (pixbuf != NULL)
     g_object_unref (pixbuf);
-  GNUNET_free (desc);
+  GNUNET_free_non_null (desc);
   GNUNET_free_non_null (mime);
 
   notebook =
@@ -1610,6 +1634,7 @@ setup_publish (struct GNUNET_FS_PublishContext *pc, const char *fn,
   GtkWidget *close_button;
   GtkNotebook *notebook;
   char *size_fancy;
+  char *fn_utf8 = NULL;
 
   if (NULL == parent)
   {
@@ -1676,11 +1701,14 @@ setup_publish (struct GNUNET_FS_PublishContext *pc, const char *fn,
   ent = GNUNET_malloc (sizeof (struct PublishEntry));
   ent->is_top = (parent == NULL) ? GNUNET_YES : GNUNET_NO;
   ent->tab = publish_tab;
-  gtk_tree_store_insert_with_values (publish_tab->ts, &iter, pitrptr, G_MAXINT, 0, fn,
+  fn_utf8 = GNUNET_GTK_from_loc_to_utf8 ((char *) fn);
+  gtk_tree_store_insert_with_values (publish_tab->ts, &iter, pitrptr, G_MAXINT,
+                                     0, fn_utf8,
                                      1, size_fancy, 2, "white", 3,
                                      (guint) 0 /* progress */ ,
 				     4, ent,
                                      -1);
+  GNUNET_free_non_null (fn_utf8);
   path = gtk_tree_model_get_path (GTK_TREE_MODEL (publish_tab->ts), &iter);
   GNUNET_assert (NULL != path);
   ent->rr = gtk_tree_row_reference_new (GTK_TREE_MODEL (publish_tab->ts), path);
diff --git a/src/fs/gnunet-fs-gtk-main_window_adv_pseudonym.c b/src/fs/gnunet-fs-gtk-main_window_adv_pseudonym.c
index b15060b..711b78f 100644
--- a/src/fs/gnunet-fs-gtk-main_window_adv_pseudonym.c
+++ b/src/fs/gnunet-fs-gtk-main_window_adv_pseudonym.c
@@ -48,12 +48,14 @@ add_to_list (void *cls, const char *name, const GNUNET_HashCode * id)
 {
   GtkListStore *ls = cls;
   GtkTreeIter iter;
+  char *name_utf8;
+  name_utf8 = GNUNET_GTK_from_loc_to_utf8 ((char *) name);
 
-  gtk_list_store_insert_with_values (ls, &iter, -1, 0, name, 1,
+  gtk_list_store_insert_with_values (ls, &iter, -1, 0, name_utf8, 1,
                                      GNUNET_FS_namespace_create
                                      (GNUNET_FS_GTK_get_fs_handle (), name),
                                      -1);
-
+  GNUNET_free_non_null (name_utf8);
 }
 
 
diff --git a/src/fs/gnunet-fs-gtk-main_window_create_pseudonym.c b/src/fs/gnunet-fs-gtk-main_window_create_pseudonym.c
index e0a8b0e..c912aab 100644
--- a/src/fs/gnunet-fs-gtk-main_window_create_pseudonym.c
+++ b/src/fs/gnunet-fs-gtk-main_window_create_pseudonym.c
@@ -31,6 +31,7 @@ GNUNET_GTK_create_namespace_dialog_response_cb (GtkDialog *dialog,
   gint response_id, gpointer user_data)
 {
   const char *name;
+  gchar *name_loc;
   struct GNUNET_FS_Namespace *ns;
   GtkWidget *ad;
   GtkBuilder *builder;
@@ -51,8 +52,13 @@ GNUNET_GTK_create_namespace_dialog_response_cb (GtkDialog *dialog,
                            (builder,
                             "GNUNET_GTK_create_namespace_name_entry")));
   /* FIXME: show busy dialog while doing key creation */
-  ns = GNUNET_FS_namespace_create (GNUNET_FS_GTK_get_fs_handle (), name);
-  GNUNET_FS_namespace_delete (ns, GNUNET_NO);
+  name_loc = GNUNET_GTK_from_utf8_to_loc ((char *) name);
+  if (NULL != name_loc)
+  {
+    ns = GNUNET_FS_namespace_create (GNUNET_FS_GTK_get_fs_handle (), name_loc);
+    GNUNET_FS_namespace_delete (ns, GNUNET_NO);
+    GNUNET_free (name_loc);
+  }
   gtk_widget_destroy (ad);
   g_object_unref (G_OBJECT (builder));
 }
diff --git a/src/fs/gnunet-fs-gtk-main_window_file_publish.c b/src/fs/gnunet-fs-gtk-main_window_file_publish.c
index 1629842..7172e33 100644
--- a/src/fs/gnunet-fs-gtk-main_window_file_publish.c
+++ b/src/fs/gnunet-fs-gtk-main_window_file_publish.c
@@ -211,6 +211,7 @@ add_file_at_iter (gpointer data, const char *filename, const struct GNUNET_FS_Bl
   GtkTreePath *path;
   uint64_t file_size;
   const char *short_fn;
+  char *short_fn_utf8;
   struct GNUNET_CONTAINER_MetaData *meta;
   struct GNUNET_FS_Uri *ksk_uri;
   GtkTreeStore *ts;
@@ -248,10 +249,11 @@ add_file_at_iter (gpointer data, const char *filename, const struct GNUNET_FS_Bl
   short_fn = filename;
   while (NULL != (ss = strstr (short_fn, DIR_SEPARATOR_STR)))
     short_fn = 1 + ss;
+  short_fn_utf8 = GNUNET_GTK_from_loc_to_utf8 ((char *) short_fn);
   GNUNET_CONTAINER_meta_data_insert (meta, "<gnunet-gtk>",
                                      EXTRACTOR_METATYPE_FILENAME,
                                      EXTRACTOR_METAFORMAT_UTF8, "text/plain",
-                                     short_fn, strlen (short_fn) + 1);
+                                     short_fn_utf8, strlen (short_fn_utf8) + 1);
   ksk_uri = GNUNET_FS_uri_ksk_create_from_meta_data (meta);
   gtk_tree_store_insert_before (ts, &pos, iter, NULL);
   path = gtk_tree_model_get_path (GTK_TREE_MODEL (ts), &pos);
@@ -268,8 +270,9 @@ add_file_at_iter (gpointer data, const char *filename, const struct GNUNET_FS_Bl
   else
     file_size_fancy = GNUNET_STRINGS_byte_size_fancy (file_size);
   gtk_tree_store_set (ts, &pos, 0, file_size_fancy, 1, (gboolean) do_index, 2,
-                      short_fn, 3, (guint) bo->anonymity_level, 4,
+                      short_fn_utf8, 3, (guint) bo->anonymity_level, 4,
                       (guint) bo->content_priority, 5, fi, -1);
+  GNUNET_free_non_null (short_fn_utf8);
   GNUNET_free (file_size_fancy);
   update_selectivity (data);
 }
@@ -294,6 +297,7 @@ create_dir_at_iter (gpointer data, const char *name, const struct GNUNET_FS_Bloc
   GtkTreeStore *ts;
   GtkBuilder *builder;
   
+  
   builder = GTK_BUILDER (data);
 
   ts = GTK_TREE_STORE (gtk_builder_get_object
@@ -504,6 +508,7 @@ extract_file (struct AddDirContext *adc, const char *filename)
   GNUNET_HashCode hc;
   const char *short_fn;
   const char *ss;
+  char *short_fn_utf8;
 
   adc->dir_entry_count++;
   pd = GNUNET_malloc (sizeof (struct PublishData));
@@ -515,11 +520,12 @@ extract_file (struct AddDirContext *adc, const char *filename)
   short_fn = filename;
   while (NULL != (ss = strstr (short_fn, DIR_SEPARATOR_STR)))
     short_fn = 1 + ss;
+  short_fn_utf8 = GNUNET_GTK_from_loc_to_utf8 ((char *) short_fn);
   GNUNET_CONTAINER_meta_data_insert (pd->meta, "<gnunet-gtk>",
                                      EXTRACTOR_METATYPE_FILENAME,
                                      EXTRACTOR_METAFORMAT_UTF8, "text/plain",
-                                     short_fn, strlen (short_fn) + 1);
-
+                                     short_fn, strlen (short_fn_utf8) + 1);
+  GNUNET_free_non_null (short_fn_utf8);
 
   gtk_tree_store_insert_before (adc->ts, &pd->iter, adc->parent, NULL);
   GNUNET_CRYPTO_hash (filename, strlen (filename), &hc);
@@ -576,6 +582,7 @@ add_entry_to_ts (GtkTreeStore * ts, GtkTreeIter * iter, const char *filename,
   struct GNUNET_FS_Uri *kill_ksk;
   const char *ss;
   const char *short_fn;
+  char *short_fn_utf8;
   struct stat sbuf;
 
   if (0 != STAT (filename, &sbuf))
@@ -627,9 +634,11 @@ add_entry_to_ts (GtkTreeStore * ts, GtkTreeIter * iter, const char *filename,
   short_fn = filename;
   while (NULL != (ss = strstr (short_fn, DIR_SEPARATOR_STR)))
     short_fn = 1 + ss;
+  short_fn_utf8 = GNUNET_GTK_from_loc_to_utf8 ((char *) short_fn);
   gtk_tree_store_set (ts, iter, 0, file_size_fancy, 1, (gboolean) do_index, 2,
-                      short_fn, 3, (guint) bo->anonymity_level, 4,
+                      short_fn_utf8, 3, (guint) bo->anonymity_level, 4,
                       (guint) bo->content_priority, 5, fi, -1);
+  GNUNET_free_non_null (short_fn_utf8);
   GNUNET_free (file_size_fancy);
 }
 
@@ -774,8 +783,19 @@ scan_directory (void *cls, const char *filename)
     }
     else
     {
+      char *filename_utf8;
+      const char *ss, *short_fn;
       GNUNET_assert (mcm == NULL);
       /* we're top-level */
+      short_fn = filename;
+      while (NULL != (ss = strstr (short_fn, DIR_SEPARATOR_STR)))
+        short_fn = 1 + ss;
+      filename_utf8 = GNUNET_GTK_from_loc_to_utf8 ((char *) short_fn);
+      GNUNET_CONTAINER_meta_data_insert (pd->meta, "<gnunet-gtk>",
+                                         EXTRACTOR_METATYPE_FILENAME,
+                                         EXTRACTOR_METAFORMAT_UTF8, "text/plain",
+                                         filename_utf8, strlen (filename_utf8) + 1);
+      GNUNET_free_non_null (filename_utf8);
       add_entry_to_ts (adc->ts, &pd->iter, filename, &adc->bo, adc->do_index,
                        NULL, pd->meta);
     }
@@ -1384,7 +1404,7 @@ GNUNET_GTK_publish_directory_dialog_response_cb (GtkDialog *dialog,
 					   "GNUNET_GTK_publish_directory_dialog"));
   if (response_id == -5)
   {
-    filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (ad));
+    filename = GNUNET_GTK_filechooser_get_filename_loc (GTK_FILE_CHOOSER (ad));
     sb = GTK_SPIN_BUTTON (gtk_builder_get_object (builder,
         "GNUNET_GTK_publish_directory_dialog_expiration_year_spin_button"));
     if (!GNUNET_GTK_get_selected_anonymity_level (builder,
@@ -1539,6 +1559,18 @@ add_updateable_to_ts (void *cls, const char *last_id,
                                                      EXTRACTOR_METATYPE_COMMENT,
                                                      EXTRACTOR_METATYPE_SUBJECT,
                                                      -1);
+  if (desc == NULL)
+    desc = GNUNET_strdup (_("no description supplied"));
+  else
+  {
+    char *utf8_desc = NULL;
+    utf8_desc = GNUNET_FS_GTK_dubious_meta_to_utf8 (EXTRACTOR_METAFORMAT_UTF8, desc, strlen (desc) + 1);
+    GNUNET_free (desc);
+    if (utf8_desc != NULL)
+      desc = utf8_desc;
+    else
+      desc = NULL;
+  }
   gtk_tree_store_insert_with_values (uc->ts, &iter, uc->parent, G_MAXINT, 0,
                                      uc->namespace_name, 1, uc->ns, 2, last_id,
                                      3, GNUNET_FS_uri_dup (last_uri), 4,
@@ -1586,13 +1618,15 @@ add_namespace_to_ts (void *cls, const char *name, const GNUNET_HashCode * id)
   GtkTreeStore *ts = cls;
   struct UpdateableContext uc;
   GtkTreeIter iter;
+  gchar *name_utf8;
 
   uc.parent = &iter;
   uc.namespace_name = name;
   uc.ts = ts;
   uc.ns = GNUNET_FS_namespace_create (GNUNET_FS_GTK_get_fs_handle (), name);
   uc.update_called = GNUNET_NO;
-  gtk_tree_store_insert_with_values (ts, &iter, NULL, G_MAXINT, 0, name, 1,
+  name_utf8 = GNUNET_GTK_from_loc_to_utf8 ((char *) name);
+  gtk_tree_store_insert_with_values (ts, &iter, NULL, G_MAXINT, 0, name_utf8, 1,
                                      uc.ns, 2, NULL /* last-id */ ,
                                      3, NULL /* last-uri */ ,
                                      4, NULL /* meta */ ,
@@ -1601,6 +1635,7 @@ add_namespace_to_ts (void *cls, const char *name, const GNUNET_HashCode * id)
                                      7, TRUE /* update editable */ ,
                                      8, TRUE /* current editable */ ,
                                      -1);
+  GNUNET_free_non_null (name_utf8);
   uc.seen = GNUNET_CONTAINER_multihashmap_create (128);
   GNUNET_FS_namespace_list_updateable (uc.ns, NULL, &add_updateable_to_ts, &uc);
   GNUNET_CONTAINER_multihashmap_destroy (uc.seen);
@@ -1726,6 +1761,7 @@ hide_master_publish_dialog (gpointer user_data, gint ret)
       do
       {
         fi = get_file_information (tm, &iter);
+        /* FIXME: should we convert namespace id and uid from UTF8? */
         GNUNET_FS_publish_start (GNUNET_FS_GTK_get_fs_handle (), fi, namespace,
                                  namespace_id, namespace_uid,
                                  GNUNET_FS_PUBLISH_OPTION_NONE);
@@ -1801,7 +1837,6 @@ GNUNET_GTK_publish_file_dialog_response_cb (GtkDialog *dialog,
   if (response_id == -5)
   {
     /* OK */
-    filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (ad));
     sb = GTK_SPIN_BUTTON (gtk_builder_get_object (builder,
         "GNUNET_GTK_publish_file_dialog_expiration_year_spin_button"));
 
@@ -1816,6 +1851,8 @@ GNUNET_GTK_publish_file_dialog_response_cb (GtkDialog *dialog,
     do_index = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (
         gtk_builder_get_object (builder,
         "GNUNET_GTK_publish_file_dialog_do_index_checkbutton")));
+
+    filename = GNUNET_GTK_filechooser_get_filename_loc (GTK_FILE_CHOOSER (ad));
     add_file_at_iter (user_data, filename, &bo, do_index, NULL);
     g_free (filename);
     update_selectivity (user_data);
diff --git a/src/fs/gnunet-fs-gtk-main_window_open_directory.c b/src/fs/gnunet-fs-gtk-main_window_open_directory.c
index 23e71fc..e614451 100644
--- a/src/fs/gnunet-fs-gtk-main_window_open_directory.c
+++ b/src/fs/gnunet-fs-gtk-main_window_open_directory.c
@@ -67,7 +67,7 @@ add_child (void *cls, const char *filename, const struct GNUNET_FS_Uri *uri,
     dmeta = GNUNET_CONTAINER_meta_data_duplicate (meta);
     GNUNET_CONTAINER_meta_data_insert (dmeta, "<user>",
                                        EXTRACTOR_METATYPE_FILENAME,
-                                       EXTRACTOR_METAFORMAT_C_STRING,
+                                       EXTRACTOR_METAFORMAT_UTF8,
                                        "text/plain", acc->filename,
                                        strlen (acc->filename) + 1);
     acc->tab = GNUNET_GTK_add_to_uri_tab (&acc->iter, &acc->par, dmeta, NULL);
@@ -91,7 +91,7 @@ GNUNET_GTK_open_directory_dialog_response_cb (GtkDialog *dialog,
 {
   GtkBuilder *builder;
   GtkWidget *ad;
-  char *filename;
+  char *filename, *filename_utf8;
   struct AddChildContext acc;
 
   builder = GTK_BUILDER (user_data);
@@ -105,12 +105,14 @@ GNUNET_GTK_open_directory_dialog_response_cb (GtkDialog *dialog,
     return;
   }
 
-  filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (ad));
+  filename = GNUNET_GTK_filechooser_get_filename_loc (GTK_FILE_CHOOSER (ad));
+  filename_utf8 = GNUNET_GTK_filechooser_get_filename_utf8 (GTK_FILE_CHOOSER (ad));
   gtk_widget_destroy (ad);
   g_object_unref (G_OBJECT (builder));
-  acc.filename = filename;
+  acc.filename = filename_utf8;
   acc.ts = NULL;
   GNUNET_FS_GTK_mmap_and_scan (filename, &add_child, &acc);
+  g_free (filename_utf8);
   g_free (filename);
 }
 
diff --git a/src/fs/gnunet-fs-gtk.c b/src/fs/gnunet-fs-gtk.c
index 5545371..bf6e171 100644
--- a/src/fs/gnunet-fs-gtk.c
+++ b/src/fs/gnunet-fs-gtk.c
@@ -501,8 +501,11 @@ main_window_search_button_clicked_cb (GtkButton *button, gpointer user_data)
   mime_keyword = NULL; 
   if (mime_model && gtk_combo_box_get_active_iter (mime_combo, &iter))  
     gtk_tree_model_get (mime_model, &iter, 0, &mime_keyword, -1);  
-  if (mime_keyword == NULL)
-    mime_keyword = g_strdup ("");
+  if (strcmp (mime_keyword, " ") == 0)
+  {
+    g_free (mime_keyword);
+    mime_keyword = NULL;
+  }
 
   ref = g_object_get_data (G_OBJECT (toggle_button), "selected-row-reference");
   if (ref)
@@ -516,7 +519,7 @@ main_window_search_button_clicked_cb (GtkButton *button, gpointer user_data)
   query_entry = GTK_ENTRY (gtk_builder_get_object (builder,
 						   "main_window_search_entry"));
   entry_keywords = gtk_entry_get_text (query_entry);
-  keywords = g_strdup_printf ("%s +%s", entry_keywords, mime_keyword);
+  keywords = g_strdup_printf ("%s %s%s", entry_keywords, mime_keyword ? "+" : "", mime_keyword ? mime_keyword : "");
   g_free (mime_keyword);
   if (nsid != NULL)
   {
@@ -613,6 +616,18 @@ add_namespace_to_ts (void *cls, const GNUNET_HashCode * pseudonym,
                                                      EXTRACTOR_METATYPE_SUBJECT,
                                                      EXTRACTOR_METATYPE_KEYWORDS,
                                                      -1);
+  if (description == NULL)
+    description = g_strdup (_("no description supplied"));
+  else
+  {
+    char *utf8_desc = NULL;
+    utf8_desc = GNUNET_FS_GTK_dubious_meta_to_utf8 (EXTRACTOR_METAFORMAT_UTF8, description, strlen (description));
+    GNUNET_free (description);
+    if (utf8_desc != NULL)
+      description = utf8_desc;
+    else
+      description = NULL;
+  }
   gtk_tree_store_insert_with_values (ts, &iter, NULL, G_MAXINT, 0, ns_name, 1,
       nsid, 2, root, 3, description, -1);
   GNUNET_free (ns_name);
diff --git a/src/include/gnunet_gtk.h b/src/include/gnunet_gtk.h
index 4f3e2cd..2ce6447 100644
--- a/src/include/gnunet_gtk.h
+++ b/src/include/gnunet_gtk.h
@@ -117,6 +117,34 @@ GNUNET_GTK_tray_icon_create (GtkWindow * main, const char *icon_name,
 void
 GNUNET_GTK_tray_icon_destroy (void);
 
+char *
+GNUNET_GTK_from_utf8_to_loc (gchar *str_utf8);
+
+char *
+GNUNET_GTK_from_loc_to_utf8 (gchar *str_loc);
+
+char *
+GNUNET_GTK_from_filename_to_utf8 (gchar *filename);
+
+char *
+GNUNET_GTK_from_utf8_to_filename (gchar *str_utf8);
+
+char *
+GNUNET_GTK_from_loc_to_filename (gchar *str_loc);
+
+char *
+GNUNET_GTK_from_filename_to_loc (gchar *filename);
+
+/* Returns filename form filechooser, encoded in locale-dependent
+ * encoding, suitable to be given to CRT and/or GNUnet
+ */
+char *
+GNUNET_GTK_filechooser_get_filename_loc (GtkFileChooser *fc);
+
+gchar *
+GNUNET_GTK_filechooser_get_filename_utf8 (GtkFileChooser *fc);
+
+
 
 /* ******************* main loop ***************** */
 
diff --git a/src/lib/nls.c b/src/lib/nls.c
index a040f8e..f313ce5 100644
--- a/src/lib/nls.c
+++ b/src/lib/nls.c
@@ -53,4 +53,171 @@ GNUNET_GTK_setup_nls ()
 #endif
 }
 
+
+char *
+GNUNET_GTK_from_utf8_to_loc (gchar *str_utf8)
+{
+  char *str_loc;
+  const char *loc_charset;
+  gboolean is_UTF8;
+
+  if (NULL == str_utf8)
+    return NULL;
+
+  is_UTF8 = g_get_charset (&loc_charset);
+  if (is_UTF8)
+    str_loc = GNUNET_strdup (str_utf8);
+  else
+    str_loc = GNUNET_STRINGS_from_utf8 (str_utf8, strlen (str_utf8), loc_charset);
+
+  return str_loc;
+}
+
+char *
+GNUNET_GTK_from_loc_to_utf8 (gchar *str_loc)
+{
+  char *str_utf8;
+  const char *loc_charset;
+  gboolean is_UTF8;
+
+  if (NULL == str_loc)
+    return NULL;
+
+  is_UTF8 = g_get_charset (&loc_charset);
+  if (is_UTF8)
+    str_utf8 = GNUNET_strdup (str_loc);
+  else
+    str_utf8 = GNUNET_STRINGS_to_utf8 (str_loc, strlen (str_loc), loc_charset);
+
+  return str_utf8;
+}
+
+/* This is copied from GLib */
+static gboolean
+get_filename_charset (const gchar **filename_charset)
+{
+  const gchar **charsets;
+  gboolean is_utf8;
+  
+  is_utf8 = g_get_filename_charsets (&charsets);
+
+  if (filename_charset)
+    *filename_charset = charsets[0];
+  
+  return is_utf8;
+}
+
+char *
+GNUNET_GTK_from_filename_to_utf8 (gchar *filename)
+{
+  char *str_utf8;
+  const char *filename_charset;
+  gboolean is_UTF8;
+
+  if (NULL == filename)
+    return NULL;
+
+  is_UTF8 = get_filename_charset (&filename_charset);
+  if (is_UTF8)
+    str_utf8 = GNUNET_strdup (filename);
+  else
+    str_utf8 = GNUNET_STRINGS_to_utf8 (filename, strlen (filename), filename_charset);
+
+  return str_utf8;
+}
+
+char *
+GNUNET_GTK_from_utf8_to_filename (gchar *str_utf8)
+{
+  char *filename;
+  const char *filename_charset;
+  gboolean is_UTF8;
+
+  if (NULL == str_utf8)
+    return NULL;
+
+  is_UTF8 = get_filename_charset (&filename_charset);
+  if (is_UTF8)
+    filename = GNUNET_strdup (str_utf8);
+  else
+    filename = GNUNET_STRINGS_from_utf8 (str_utf8, strlen (str_utf8), filename_charset);
+
+  return filename;
+}
+
+char *
+GNUNET_GTK_from_loc_to_filename (gchar *str_loc)
+{
+  char *filename;
+  const char *filename_charset;
+  const char *loc_charset;
+  gboolean is_filename_UTF8, is_loc_UTF8;
+
+  if (NULL == str_loc)
+    return NULL;
+
+  is_filename_UTF8 = get_filename_charset (&filename_charset);
+  is_loc_UTF8 = g_get_charset (&loc_charset);
+  if (is_filename_UTF8 && is_loc_UTF8)
+    filename = GNUNET_strdup (str_loc);
+  else if (is_filename_UTF8)
+    filename = GNUNET_STRINGS_to_utf8 (str_loc, strlen (str_loc), loc_charset);
+  else if (is_loc_UTF8)
+    filename = GNUNET_STRINGS_from_utf8 (str_loc, strlen (str_loc), filename_charset);
+  else
+    /* Pray that iconv() knows these charsets */
+    filename = GNUNET_STRINGS_conv (str_loc, strlen (str_loc), loc_charset, filename_charset);
+
+  return filename;
+}
+
+char *
+GNUNET_GTK_from_filename_to_loc (gchar *filename)
+{
+  char *str_loc;
+  const char *loc_charset;
+  const char *filename_charset;
+  gboolean is_loc_UTF8, is_filename_UTF8;
+
+  if (NULL == filename)
+    return NULL;
+
+  is_filename_UTF8 = get_filename_charset (&filename_charset);
+  is_loc_UTF8 = g_get_charset (&loc_charset);
+  if (is_loc_UTF8 && is_filename_UTF8)
+    str_loc = GNUNET_strdup (filename);
+  else if (is_loc_UTF8)
+    str_loc = GNUNET_STRINGS_to_utf8 (filename, strlen (filename), filename_charset);
+  else if (is_filename_UTF8)
+    str_loc = GNUNET_STRINGS_from_utf8 (filename, strlen (filename), loc_charset);
+  else
+    /* Pray that iconv() knows these charsets */
+    str_loc = GNUNET_STRINGS_conv (filename, strlen (filename), filename_charset, loc_charset);
+
+  return str_loc;
+}
+
+/* Returns filename form filechooser, encoded in locale-dependent
+ * encoding, suitable to be given to CRT and/or GNUnet
+ */
+char *
+GNUNET_GTK_filechooser_get_filename_loc (GtkFileChooser *fc)
+{
+  char *filename_loc;
+  gchar *filename = gtk_file_chooser_get_filename (fc);
+  filename_loc = GNUNET_GTK_from_filename_to_loc (filename);
+  g_free (filename);
+  return filename_loc;
+}
+
+gchar *
+GNUNET_GTK_filechooser_get_filename_utf8 (GtkFileChooser *fc)
+{
+  char *filename_utf8;
+  gchar *filename = gtk_file_chooser_get_filename (fc);
+  filename_utf8 = GNUNET_GTK_from_filename_to_utf8 (filename);
+  g_free (filename);
+  return filename_utf8;
+}
+
 /* end of nls.c */
-- 
1.7.4

