/* This file is part of GNUnet. (C) 2005, 2006 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/plugins/fs/upload.c * @brief code for uploading with gnunet-gtk * @author Christian Grothoff */ #include "platform.h" #include "gnunetgtk_common.h" #include "search.h" #include "upload.h" #include "fs.h" #include "meta.h" #include #ifdef MINGW #include #ifndef BIF_NONEWFOLDERBUTTON #define BIF_NONEWFOLDERBUTTON 0x200 #endif #endif /** * XML tree for the meta-data dialog of upload. * (there can only be one at a time; * maybe NULL at times where there is no dialog) */ static GladeXML * metaXML; /* ************ FSUI event handlers ************ */ void fs_upload_update(UploadList * list, unsigned long long completed) { GtkTreeIter iter; GtkTreePath * path; int progress; if (list->total != 0) progress = 100 * completed / list->total; else progress = 100; path = gtk_tree_row_reference_get_path(list->summaryViewRowReference); gtk_tree_model_get_iter(GTK_TREE_MODEL(upload_summary), &iter, path); gtk_tree_path_free(path); gtk_tree_store_set(upload_summary, &iter, UPLOAD_PROGRESS, progress, -1); } void fs_upload_complete(UploadList * list, struct ECRS_URI * uri) { GtkTreeIter iter; GtkTreePath * path; char * us; list->has_terminated = YES; list->uri = ECRS_dupUri(uri); us = ECRS_uriToString(uri); path = gtk_tree_row_reference_get_path(list->summaryViewRowReference); gtk_tree_model_get_iter(GTK_TREE_MODEL(upload_summary), &iter, path); gtk_tree_path_free(path); gtk_tree_store_set(upload_summary, &iter, UPLOAD_URISTRING, us, -1); FREE(us); } void fs_upload_error(UploadList * list) { /* FIXME: indicate error in summary dialog! */ list->has_terminated = YES; } void fs_upload_stopped(UploadList * list) { GtkTreeIter iter; GtkTreePath * path; UploadList * prev; path = gtk_tree_row_reference_get_path(list->summaryViewRowReference); gtk_tree_model_get_iter(GTK_TREE_MODEL(upload_summary), &iter, path); gtk_tree_path_free(path); gtk_tree_row_reference_free(list->summaryViewRowReference); list->summaryViewRowReference = NULL; gtk_tree_store_remove(upload_summary, &iter); FREE(list->filename); if (list->uri != NULL) { ECRS_freeUri(list->uri); list->uri = NULL; } if (upload_head == list) upload_head = list->next; else { prev = upload_head; while ( (prev != NULL) && (prev->next != list) ) prev = prev->next; if (prev != NULL) prev->next = list->next; else GE_BREAK(ectx, 0); } FREE(list); } UploadList * fs_upload_started(struct FSUI_UploadList * fsui, UploadList * parent, const char * filename, struct ECRS_URI * uri, unsigned long long total, unsigned long long completed, FSUI_State state) { UploadList * ret; GtkTreeIter iter; GtkTreePath * path; int progress; ret = MALLOC(sizeof(UploadList)); memset(ret, 0, sizeof(UploadList)); ret->filename = STRDUP(filename); ret->fsui_list = fsui; ret->total = total; if (parent == NULL) { gtk_tree_store_append(upload_summary, &iter, NULL); } else { GtkTreeIter par; path = gtk_tree_row_reference_get_path(parent->summaryViewRowReference); gtk_tree_model_get_iter(GTK_TREE_MODEL(upload_summary), &par, path); gtk_tree_path_free(path); gtk_tree_store_append(upload_summary, &iter, &par); } if (total != 0) progress = 100 * completed / total; else progress = 100; gtk_tree_store_set(upload_summary, &iter, UPLOAD_FILENAME, filename, UPLOAD_PROGRESS, progress, UPLOAD_URISTRING, "", /* FIXME: set if URI != NULL! */ UPLOAD_INTERNAL, ret, -1); path = gtk_tree_model_get_path(GTK_TREE_MODEL(upload_summary), &iter); ret->summaryViewRowReference = gtk_tree_row_reference_new(GTK_TREE_MODEL(upload_summary), path); ret->has_terminated = ( (state != FSUI_ACTIVE) && (state != FSUI_PENDING) ); ret->next = upload_head; upload_head = ret; return ret; } /* *************** user upload event handling ************** */ void on_selectAlternativePreviewButton_selection_changed_fs(GtkWidget * preview, GtkWidget * fileChooser) { char * fn; fn = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fileChooser)); if (fn == NULL) { gtk_image_set_from_pixbuf(GTK_IMAGE(preview), NULL); } else { GdkPixbuf * buf; buf = gdk_pixbuf_new_from_file(fn, NULL); gtk_image_set_from_pixbuf(GTK_IMAGE(preview), buf); g_object_unref(buf); free(fn); } } void on_metaDataDialogKeywordAddButton_clicked_fs(gpointer dummy, GtkWidget * button) { handleKeywordListUpdate(metaXML, "fileInformationKeywordEntry", "metaDataDialogKeywordList"); } void on_metaDataDialogMetaDataAddButton_clicked_fs(gpointer dummy, GtkWidget * button) { handleMetaDataListUpdate(metaXML, "metaDataDialogMetaTypeComboBox", "metaDataDialogValueEntry", "metaDataDialogMetaDataList"); } void on_metaDataDialogKeywordRemoveButton_clicked_fs(gpointer dummy, GtkWidget * button) { handleListRemove(metaXML, "metaDataDialogKeywordList"); } void on_metaDataDialogMetaDataRemoveButton_clicked_fs(gpointer dummy, GtkWidget * button) { handleListRemove(metaXML, "metaDataDialogMetaDataList"); } /** * The selection of the keyword list changed. * Update button status. */ static void on_keyword_list_selection_changed(gpointer signal, gpointer cls) { GtkTreeSelection * selection; GtkWidget * button; selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(glade_xml_get_widget(metaXML, "metaDataDialogKeywordList"))); button = glade_xml_get_widget(metaXML, "metaDataDialogKeywordRemoveButton"); gtk_widget_set_sensitive(button, gtk_tree_selection_count_selected_rows(selection) > 0); } /** * The selection of the metadata list changed. * Update button status. */ static void on_metadata_list_selection_changed(gpointer signal, gpointer cls) { GtkTreeSelection * selection; GtkWidget * button; selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(glade_xml_get_widget(metaXML, "metaDataDialogMetaDataList"))); button = glade_xml_get_widget(metaXML, "metaDataDialogMetaDataRemoveButton"); gtk_widget_set_sensitive(button, gtk_tree_selection_count_selected_rows(selection) > 0); } /** * The user has edited the metadata entry. * Update add button status. */ void on_metaDataDialogValueEntry_changed_fs(gpointer dummy2, GtkWidget * searchEntry) { const char * input; GtkWidget * button; input = gtk_entry_get_text(GTK_ENTRY(glade_xml_get_widget(metaXML, "metaDataDialogValueEntry"))); if (input == NULL) return; button = glade_xml_get_widget(metaXML, "metaDataDialogMetaDataAddButton"); gtk_widget_set_sensitive(button, strlen(input) > 0); } /** * The user has edited the keyword entry. * Update add button status. */ void on_fileInformationKeywordEntry_changed_fs(gpointer dummy2, GtkWidget * searchEntry) { const char * input; GtkWidget * button; input = gtk_entry_get_text(GTK_ENTRY(glade_xml_get_widget(metaXML, "fileInformationKeywordEntry"))); if (input == NULL) return; button = glade_xml_get_widget(metaXML, "metaDataDialogKeywordAddButton"); gtk_widget_set_sensitive(button, strlen(input) > 0); } typedef struct { const char * filename; unsigned int anonymity; unsigned int priority; int index; int extract; int deep_index; cron_t expire; struct ECRS_MetaData * meta; struct ECRS_URI * gkeywordURI; struct ECRS_URI * keywordURI; } FSUC; static void * start_upload_helper(void * cls) { FSUC * fsuc = cls; FSUI_startUpload(ctx, fsuc->filename, (DirectoryScanCallback) &disk_directory_scan, ectx, fsuc->anonymity, fsuc->priority, fsuc->index, fsuc->extract, fsuc->deep_index, fsuc->expire, fsuc->meta, fsuc->gkeywordURI, fsuc->keywordURI); return NULL; } void on_fsinsertuploadbutton_clicked_fs(gpointer dummy, GtkWidget * uploadButton) { FSUC fsuc; const char * filenamerest; GtkWidget * dialog; EXTRACTOR_ExtractorList * extractors; char * config; struct ECRS_MetaData * meta; struct ECRS_URI * keywordURI; extractors = EXTRACTOR_loadDefaultLibraries(); config = NULL; GC_get_configuration_value_string(cfg, "FS", "EXTRACTORS", NULL, &config); if (config != NULL) { extractors = EXTRACTOR_loadConfigLibraries(extractors, config); FREE(config); } fsuc.filename = getEntryLineValue(getMainXML(), "uploadFilenameComboBoxEntry"); metaXML = glade_xml_new(getGladeFileName(), "metaDataDialog", PACKAGE_NAME); connectGladeWithPlugins(metaXML); dialog = glade_xml_get_widget(metaXML, "metaDataDialog"); meta = ECRS_createMetaData(); ECRS_extractMetaData(ectx, meta, fsuc.filename, extractors); EXTRACTOR_removeAll(extractors); filenamerest = &fsuc.filename[strlen(fsuc.filename)-1]; while ( (filenamerest > fsuc.filename) && (filenamerest[-1] != DIR_SEPARATOR) ) filenamerest--; ECRS_addToMetaData(meta, EXTRACTOR_FILENAME, filenamerest); createMetaDataListTreeView(metaXML, "metaDataDialogMetaDataList", "previewImage", meta); keywordURI = ECRS_metaDataToUri(meta); ECRS_freeMetaData(meta); createKeywordListTreeView(metaXML, "metaDataDialogKeywordList", keywordURI); ECRS_freeUri(keywordURI); createMetaTypeComboBox(metaXML, "metaDataDialogMetaTypeComboBox"); g_signal_connect_data(gtk_tree_view_get_selection(GTK_TREE_VIEW(glade_xml_get_widget(metaXML, "metaDataDialogKeywordList"))), "changed", G_CALLBACK(&on_keyword_list_selection_changed), NULL, NULL, 0); g_signal_connect_data(gtk_tree_view_get_selection(GTK_TREE_VIEW(glade_xml_get_widget(metaXML, "metaDataDialogMetaDataList"))), "changed", G_CALLBACK(&on_metadata_list_selection_changed), NULL, NULL, 0); gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK); if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL) { fsuc.anonymity = getSpinButtonValue(getMainXML(), "uploadAnonymityLevelSpinButton"); fsuc.priority = getSpinButtonValue(getMainXML(), "contentPrioritySpinButton"); fsuc.index = getToggleButtonValue(getMainXML(), "indexbutton"); fsuc.extract = getToggleButtonValue(getMainXML(), "doExtractCheckButton"); fsuc.deep_index = getToggleButtonValue(getMainXML(), "deepIndexCheckButton"); fsuc.expire = get_time() + 2 * cronYEARS; fsuc.meta = getMetaDataFromList(metaXML, "metaDataDialogMetaDataList", "previewImage"); fsuc.keywordURI = getKeywordURIFromList(metaXML, "metaDataDialogKeywordList"); fsuc.gkeywordURI = ECRS_stringToUri(ectx, ECRS_URI_PREFIX ECRS_SEARCH_INFIX); run_with_save_calls(&start_upload_helper, &fsuc); ECRS_freeMetaData(fsuc.meta); ECRS_freeUri(fsuc.gkeywordURI); ECRS_freeUri(fsuc.keywordURI); } gtk_widget_destroy (dialog); UNREF(metaXML); metaXML = NULL; } #ifndef MINGW static char * selectFile(const char * oldfilename) { GladeXML * uploadXML; GtkFileChooser * dialog; char * ret; uploadXML = glade_xml_new(getGladeFileName(), "uploadfilechooserdialog", PACKAGE_NAME); connectGladeWithPlugins(uploadXML); dialog = GTK_FILE_CHOOSER(glade_xml_get_widget(uploadXML, "uploadfilechooserdialog")); gtk_file_chooser_set_filename(dialog, oldfilename); if (getToggleButtonValue(getMainXML(), "scopeRecursiveButton")) gtk_file_chooser_set_action(dialog, GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER); if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL) ret = gtk_file_chooser_get_filename(dialog); else ret = NULL; gtk_widget_destroy(GTK_WIDGET(dialog)); UNREF(uploadXML); return ret; } #else /* MINGW */ static char * selectFile(const char * oldfilename) { if (getToggleButtonValue(getMainXML(), "scopeFileOnlyButton")) return plibc_ChooseFile(_("Choose the file you want to publish."), OFN_FILEMUSTEXIST | OFN_SHAREAWARE); return plibc_ChooseDir(_("Choose the directory you want to publish."), BIF_USENEWUI | BIF_SHAREABLE | BIF_NONEWFOLDERBUTTON); } #endif /* MINGW */ void on_mainFileSharingInsertBrowseButton_clicked_fs(GtkWidget * browseButton, gpointer dummy) { char * filename; char * ofn; const char *oldfilename; GtkWidget * uploadLine; GtkEntry * entry; GtkListStore * model; GtkTreeIter iter; uploadLine = glade_xml_get_widget(getMainXML(), "uploadFilenameComboBoxEntry"); entry = GTK_ENTRY(gtk_bin_get_child(GTK_BIN(uploadLine))); oldfilename = gtk_entry_get_text(entry); if (oldfilename == NULL) oldfilename = getenv("PWD"); if (oldfilename == NULL) oldfilename = getenv("HOME"); if (oldfilename == NULL) oldfilename = "/"; ofn = string_expandFileName(ectx, oldfilename); filename = selectFile(ofn); FREE(ofn); if (NULL == filename) return; gtk_entry_set_text(entry, filename); model = GTK_LIST_STORE(gtk_combo_box_get_model(GTK_COMBO_BOX(uploadLine))); gtk_list_store_prepend(model, &iter); gtk_list_store_set(model, &iter, 0, filename, -1); free(filename); } /* FIXME: handlers for clear and stop! */ struct FCBC { int (*method)(struct FSUI_Context * ctx, struct FSUI_UploadList * list); struct FSUI_UploadList * argument; }; static void * fsui_callback(void * cls) { struct FCBC * fcbc = cls; fcbc->method(ctx, fcbc->argument); return NULL; } static void clearCompletedUploadCallback(GtkTreeModel * model, GtkTreePath * path, GtkTreeIter * iter, gpointer unused) { UploadList * ul; struct FCBC fcbc; GE_ASSERT(ectx, model == GTK_TREE_MODEL(upload_summary)); gtk_tree_model_get(model, iter, UPLOAD_INTERNAL, &ul, -1); if (ul->has_terminated) { fcbc.method = &FSUI_stopUpload; fcbc.argument = ul->fsui_list; run_with_save_calls(&fsui_callback, &fcbc); } } /** * The user has edited the search entry. * Update search button status. */ void on_uploadFilenameComboBoxEntry_changed_fs(gpointer dummy2, GtkWidget * searchEntry) { const char * filename; GtkWidget * uploadButton; struct stat buf; int ok; GtkWidget * toggle; filename = getEntryLineValue(getMainXML(), "uploadFilenameComboBoxEntry"); ok = (0 == stat(filename, &buf)); if (ok) ok = (0 == ACCESS(filename, R_OK)); if (ok) { if (S_ISDIR(buf.st_mode)) { toggle = glade_xml_get_widget(getMainXML(), "scopeRecursiveButton"); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle), 1); } else { toggle = glade_xml_get_widget(getMainXML(), "scopeFileOnlyButton"); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle), 1); } } uploadButton = glade_xml_get_widget(getMainXML(), "fsinsertuploadbutton"); gtk_widget_set_sensitive(uploadButton, ok); } void on_clearCompletedUploadsButton_clicked_fs(void * unused, GtkWidget * clearButton) { ggc_tree_model_foreach(GTK_TREE_MODEL(upload_summary), &clearCompletedUploadCallback, NULL); } static void fsuiCallUploadCallback(GtkTreeModel * model, GtkTreePath * path, GtkTreeIter * iter, gpointer fsui_call) { UploadList * ul; struct FCBC fcbc; GE_ASSERT(ectx, model == GTK_TREE_MODEL(upload_summary)); gtk_tree_model_get(model, iter, UPLOAD_INTERNAL, &ul, -1); fcbc.method = fsui_call; fcbc.argument = ul->fsui_list; run_with_save_calls(&fsui_callback, &fcbc); } void on_abortUploadButton_clicked_fs(void * unused, GtkWidget * clearButton) { GtkTreeSelection * selection; GtkWidget * uploadList; uploadList = glade_xml_get_widget(getMainXML(), "activeUploadsList"); selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(uploadList)); ggc_tree_selection_selected_foreach (selection, &fsuiCallUploadCallback, &FSUI_abortUpload); } void on_stopUploadButton_clicked_fs(void * unused, GtkWidget * clearButton) { GtkTreeSelection * selection; GtkWidget * uploadList; uploadList = glade_xml_get_widget(getMainXML(), "activeUploadsList"); selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(uploadList)); ggc_tree_selection_selected_foreach (selection, &fsuiCallUploadCallback, &FSUI_abortUpload); ggc_tree_selection_selected_foreach (selection, &fsuiCallUploadCallback, &FSUI_stopUpload); } /* end of upload.c */