/* This file is part of GNUnet (C) 2005, 2006, 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file src/main_window_open_directory.c * @author Christian Grothoff */ #include "common.h" #include "fs_event_handler.h" struct AddChildContext { const char *filename; GtkTreeStore *ts; struct SearchTab *tab; struct SearchResult *par; GtkTreeIter iter; }; /** * Function used to process entries in a directory. * * @param cls closure, our 'struct AddChildContext*' * @param filename name of the file in the directory * @param uri URI of the file * @param metadata metadata for the file; metadata for * the directory if everything else is NULL/zero * @param length length of the available data for the file * (of type size_t since data must certainly fit * into memory; if files are larger than size_t * permits, then they will certainly not be * embedded with the directory itself). * @param data data available for the file (length bytes) */ static void add_child (void *cls, const char *filename, const struct GNUNET_FS_Uri *uri, const struct GNUNET_CONTAINER_MetaData *meta, size_t length, const void *data) { struct AddChildContext *acc = cls; struct GNUNET_CONTAINER_MetaData *dmeta; GtkTreeIter iter; if (uri == NULL) { /* directory meta data itself */ dmeta = GNUNET_CONTAINER_meta_data_duplicate (meta); GNUNET_CONTAINER_meta_data_insert (dmeta, "", EXTRACTOR_METATYPE_FILENAME, EXTRACTOR_METAFORMAT_C_STRING, "text/plain", acc->filename, strlen (acc->filename) + 1); acc->tab = GNUNET_GTK_add_to_uri_tab (&acc->iter, &acc->par, dmeta, NULL); acc->ts = acc->tab->ts; GNUNET_CONTAINER_meta_data_destroy (dmeta); return; } if (acc->ts == NULL) return; GNUNET_GTK_add_search_result (acc->tab, &iter, acc->par, uri, meta, NULL, 0); } /** * User selected "Open directory" in menu. Display dialog, open * file and then display a new tab with its contents. */ void GNUNET_GTK_main_menu_file_open_gnunet_directory_activate_cb (GtkWidget * dummy, gpointer data) { struct AddChildContext acc; GtkWidget *ad; GtkBuilder *builder; char *filename; struct GNUNET_DISK_FileHandle *fh; struct GNUNET_DISK_MapHandle *mh; GtkFileFilter *ff; uint64_t fsize; void * ddata; builder = GNUNET_GTK_get_new_builder ("open_directory_dialog.glade"); if (builder == NULL) { GNUNET_break (0); return; } ad = GTK_WIDGET (gtk_builder_get_object (builder, "GNUNET_GTK_open_directory_dialog")); ff = GTK_FILE_FILTER (gtk_builder_get_object (builder, "gnunet_directory_filter")); /* FIXME: some day, write a custom file filter for gnunet-directories... */ gtk_file_filter_add_pattern (ff, "*" GNUNET_FS_DIRECTORY_EXT); if (GTK_RESPONSE_OK != gtk_dialog_run (GTK_DIALOG (ad))) { gtk_widget_destroy (ad); g_object_unref (G_OBJECT (builder)); return; } filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER(ad)); gtk_widget_destroy (ad); g_object_unref (G_OBJECT (builder)); if (GNUNET_OK != GNUNET_DISK_file_size (filename, &fsize, GNUNET_YES)) { GNUNET_break (0); g_free (filename); return; } fh = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ, GNUNET_DISK_PERM_NONE); if (fh == NULL) { GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", filename); g_free (filename); return; } ddata = GNUNET_DISK_file_map (fh, &mh, GNUNET_DISK_MAP_TYPE_READ, (size_t) fsize); if (ddata == NULL) { GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "mmap", filename); GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (fh)); g_free (filename); return; } acc.filename = filename; acc.ts = NULL; if (GNUNET_SYSERR == GNUNET_FS_directory_list_contents ((size_t) fsize, ddata, 0, &add_child, &acc)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Selected file `%s' is not a GNUnet directory!\n"), filename); } GNUNET_break (GNUNET_OK == GNUNET_DISK_file_unmap (mh)); GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (fh)); g_free (filename); } /* end of main_window_open_directory.c */