/* This file is part of GNUnet. (C) 2005 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/namespace.c * @brief code for operations with namespaces * @author Christian Grothoff */ #include "platform.h" #include "gnunetgtk_common.h" #include "fs.h" #include "helper.h" #include "meta.h" #include "namespace.h" #include #define UPDATE_CONTENT_LIST_FREQUENCY (5 * cronMINUTES) /** * @brief linked list of pages in the search notebook */ typedef struct NL { struct NL * next; GtkWidget * treeview; GtkWidget * namespacepage; GtkTreeModel * model; GtkWidget * anonymityButton; char * name; HashCode512 id; struct ECRS_MetaData * meta; } NamespaceList; static NamespaceList * head; static GladeXML * metaXML; static GtkWidget * makeNamespaceFrame(GtkWidget ** treeview, GtkWidget ** anonSpin) { GtkWidget * window; GtkWidget * child; GtkWidget * resultList; GtkCellRenderer * renderer; GtkListStore * model; GladeXML * namespaceXML; int col; namespaceXML = glade_xml_new(getGladeFileName(), "namespaceContentFrame", PACKAGE_NAME); connectGladeWithPlugins(namespaceXML); window = glade_xml_get_widget(namespaceXML, "namespaceContentFrame"); resultList = glade_xml_get_widget(namespaceXML, "namespaceContentFrameTreeView"); *anonSpin = glade_xml_get_widget(namespaceXML, "namespaceAnonymitySpinButton"); if (treeview != NULL) (*treeview) = GTK_WIDGET(GTK_TREE_VIEW(resultList)); model = gtk_list_store_new(IN_NAMESPACE_NUM, G_TYPE_STRING, /* (file)name */ G_TYPE_UINT64, /* size */ G_TYPE_STRING, /* description */ G_TYPE_STRING, /* mime-type */ G_TYPE_STRING, /* last-ID */ G_TYPE_STRING, /* next-ID */ G_TYPE_STRING, /* pub-freq */ G_TYPE_STRING, /* next pub date */ G_TYPE_POINTER, /* URI */ G_TYPE_POINTER); /* META */ gtk_tree_view_set_model(GTK_TREE_VIEW(resultList), GTK_TREE_MODEL(model)); renderer = gtk_cell_renderer_text_new(); col = gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(resultList), -1, _("Filename"), renderer, "text", IN_NAMESPACE_FILENAME, NULL); gtk_tree_view_column_set_resizable(gtk_tree_view_get_column(GTK_TREE_VIEW(resultList), col - 1), TRUE); renderer = gtk_cell_renderer_text_new(); col = gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(resultList), -1, _("Filesize"), renderer, "text", IN_NAMESPACE_SIZE, NULL); gtk_tree_view_column_set_resizable(gtk_tree_view_get_column(GTK_TREE_VIEW(resultList), col - 1), TRUE); renderer = gtk_cell_renderer_text_new(); col = gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(resultList), -1, _("Description"), renderer, "text", IN_NAMESPACE_DESCRIPTION, NULL); gtk_tree_view_column_set_resizable(gtk_tree_view_get_column(GTK_TREE_VIEW(resultList), col - 1), TRUE); renderer = gtk_cell_renderer_text_new(); col = gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(resultList), -1, _("Mime-type"), renderer, "text", IN_NAMESPACE_MIMETYPE, NULL); gtk_tree_view_column_set_resizable(gtk_tree_view_get_column(GTK_TREE_VIEW(resultList), col - 1), TRUE); renderer = gtk_cell_renderer_text_new(); col = gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(resultList), -1, _("Publication Frequency"), renderer, "text", IN_NAMESPACE_PUB_FREQ_STRING, NULL); gtk_tree_view_column_set_resizable(gtk_tree_view_get_column(GTK_TREE_VIEW(resultList), col - 1), TRUE); renderer = gtk_cell_renderer_text_new(); col = gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(resultList), -1, _("Next Publication Date"), renderer, "text", IN_NAMESPACE_PUB_DATE_STRING, NULL); gtk_tree_view_column_set_resizable(gtk_tree_view_get_column(GTK_TREE_VIEW(resultList), col - 1), TRUE); renderer = gtk_cell_renderer_text_new(); col = gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(resultList), -1, _("Last ID"), renderer, "text", IN_NAMESPACE_LAST_STRING, NULL); gtk_tree_view_column_set_resizable(gtk_tree_view_get_column(GTK_TREE_VIEW(resultList), col - 1), TRUE); renderer = gtk_cell_renderer_text_new(); col = gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(resultList), -1, _("Next ID"), renderer, "text", IN_NAMESPACE_NEXT_STRING, NULL); gtk_tree_view_column_set_resizable(gtk_tree_view_get_column(GTK_TREE_VIEW(resultList), col - 1), TRUE); child = gtk_bin_get_child(GTK_BIN(window)); gtk_widget_ref(GTK_WIDGET(child)); gtk_container_remove(GTK_CONTAINER(window), child); gtk_widget_destroy(window); UNREF(namespaceXML); return child; } /** * Add the given content to the globally available * content model. Check that it is not already * present! */ static int updateView(const ECRS_FileInfo * fi, const HashCode512 * key, int isRoot, void * closure) { GtkTreeModel * model = GTK_TREE_MODEL(closure); struct ECRS_URI * euri; GtkTreeIter iter; char * filename; char * uriString; unsigned long long size; if (gtk_tree_model_get_iter_first(model, &iter)) { do { gtk_tree_model_get(model, &iter, NAMESPACE_URI, &euri, -1); if (ECRS_equalsUri(euri, fi->uri)) return OK; /* already listed */ } while (gtk_tree_model_iter_next(GTK_TREE_MODEL(model), &iter)); } filename = ECRS_getFirstFromMetaData(fi->meta, EXTRACTOR_FILENAME, EXTRACTOR_TITLE, EXTRACTOR_DESCRIPTION, EXTRACTOR_SUBJECT, EXTRACTOR_ARTIST, EXTRACTOR_AUTHOR, EXTRACTOR_PUBLISHER, EXTRACTOR_CREATOR, EXTRACTOR_PRODUCER, EXTRACTOR_UNKNOWN, -1); if (filename == NULL) filename = STRDUP(_("no name given")); else { char *dotdot; while ( NULL != (dotdot = strstr(filename, ".."))) dotdot[0] = dotdot[1] = '_'; } if (ECRS_isFileUri(fi->uri)) size = ECRS_fileSize(fi->uri); else size = 0; uriString = ECRS_uriToString(fi->uri); gtk_list_store_append(GTK_LIST_STORE(model), &iter); gtk_list_store_set(GTK_LIST_STORE(model), &iter, NAMESPACE_FILENAME, filename, NAMESPACE_SIZE, size, NAMESPACE_URISTRING, uriString, NAMESPACE_URI, ECRS_dupUri(fi->uri), NAMESPACE_META, ECRS_dupMetaData(fi->meta), -1); FREE(filename); FREE(uriString); return OK; } static void clearContentList(void * mdl) { GtkTreeModel * model = GTK_TREE_MODEL(mdl); struct ECRS_URI * uri; struct ECRS_MetaData * meta; GtkTreeIter iter; if (gtk_tree_model_get_iter_first(model, &iter)) { do { gtk_tree_model_get(model, &iter, NAMESPACE_URI, &uri, NAMESPACE_META, &meta, -1); ECRS_freeUri(uri); ECRS_freeMetaData(meta); } while (gtk_list_store_remove(GTK_LIST_STORE(model), &iter)); } } /** * Update the list of the globally available content. */ static void doUpdateContentList(void * unused) { GtkWidget * contentList; GtkTreeModel * model; contentList = glade_xml_get_widget(getMainXML(), "availableContentList"); model = gtk_tree_view_get_model(GTK_TREE_VIEW(contentList)); FSUI_listURIs(&updateView, model); } static void updateContentList(void * unused) { gtkSaveCall(&doUpdateContentList, NULL); } void on_refreshContentListButton_clicked(gpointer dummy, gpointer dummy1) { updateContentList(NULL); } /** * Update the model that lists the content of a namespace: * add this content. * * @param uri URI of the last content published * @param lastId the ID of the last publication * @param nextId the ID of the next update * @param publicationFrequency how often are updates scheduled? * @param nextPublicationTime the scheduled time for the * next update (0 for sporadic updates) * @return OK to continue iteration, SYSERR to abort */ static int addNamespaceContentToModel(void * cls, const ECRS_FileInfo * fi, const HashCode512 * lastId, const HashCode512 * nextId, TIME_T publicationFrequency, TIME_T nextPublicationTime) { GtkListStore * model = GTK_LIST_STORE(cls); GtkTreeIter iter; char * filename; char * desc; char * mime; char * uriString; EncName last; EncName next; char * freq; char * date; unsigned long long size; filename = ECRS_getFirstFromMetaData(fi->meta, EXTRACTOR_FILENAME, EXTRACTOR_TITLE, EXTRACTOR_ARTIST, EXTRACTOR_AUTHOR, EXTRACTOR_PUBLISHER, EXTRACTOR_CREATOR, EXTRACTOR_PRODUCER, EXTRACTOR_UNKNOWN, -1); if (filename == NULL) filename = STRDUP(_("no name given")); else { char *dotdot; while (NULL != (dotdot = strstr(filename, ".."))) dotdot[0] = dotdot[1] = '_'; } desc = ECRS_getFirstFromMetaData(fi->meta, EXTRACTOR_DESCRIPTION, EXTRACTOR_GENRE, EXTRACTOR_ALBUM, EXTRACTOR_COMMENT, EXTRACTOR_SUBJECT, EXTRACTOR_FORMAT, EXTRACTOR_SIZE, EXTRACTOR_KEYWORDS, -1); if (desc == NULL) desc = STRDUP(""); mime = ECRS_getFromMetaData(fi->meta, EXTRACTOR_MIMETYPE); if (mime == NULL) mime = STRDUP(_("unknown")); if (ECRS_isFileUri(fi->uri)) size = ECRS_fileSize(fi->uri); else size = 0; uriString = ECRS_uriToString(fi->uri); hash2enc(lastId, &last); if (nextId != NULL) hash2enc(nextId, &next); else memset(&next, 0, sizeof(EncName)); if (publicationFrequency == ECRS_SBLOCK_UPDATE_SPORADIC) date = STRDUP(_("unspecified")); else if (publicationFrequency == ECRS_SBLOCK_UPDATE_NONE) date = STRDUP(_("never")); else date = GN_CTIME(&nextPublicationTime); freq = updateIntervalToString(publicationFrequency); gtk_list_store_append(model, &iter); gtk_list_store_set(model, &iter, IN_NAMESPACE_FILENAME, filename, IN_NAMESPACE_SIZE, size, IN_NAMESPACE_DESCRIPTION, desc, IN_NAMESPACE_MIMETYPE, mime, IN_NAMESPACE_LAST_STRING, &last, IN_NAMESPACE_NEXT_STRING, &next, IN_NAMESPACE_PUB_FREQ_STRING, freq, IN_NAMESPACE_PUB_DATE_STRING, date, IN_NAMESPACE_URI, ECRS_dupUri(fi->uri), IN_NAMESPACE_META, ECRS_dupMetaData(fi->meta), -1); FREE(filename); FREE(uriString); FREE(freq); FREE(date); FREE(mime); return OK; } /** * Add a tab for the given namespace. */ static int addTabForNamespace(void * unused, const char * namespaceName, const HashCode512 * namespaceId, const struct ECRS_MetaData * md, int rating) { NamespaceList * list; GtkWidget * label; GtkWidget * spin; GtkWidget * notebook; GtkListStore * model; label = gtk_label_new(namespaceName); list = MALLOC(sizeof(NamespaceList)); list->name = STRDUP(namespaceName); list->id = *namespaceId; list->meta = ECRS_dupMetaData(md); list->namespacepage = makeNamespaceFrame(&list->treeview, &spin); list->anonymityButton = spin; model = GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW(list->treeview))); list->model = GTK_TREE_MODEL(model); list->next = head; head = list; notebook = glade_xml_get_widget(getMainXML(), "localNamespacesNotebook"); gtk_notebook_append_page(GTK_NOTEBOOK(notebook), list->namespacepage, label); gtk_widget_show(notebook); FSUI_listNamespaceContent (ctx, namespaceName, &addNamespaceContentToModel, model); return OK; } void on_namespacemetaDataDialogKeywordAddButton_clicked(gpointer dummy, GtkWidget * uploadButton) { handleKeywordListUpdate(metaXML, "namespaceKeywordEntry", "namespaceMetaDataDialogKeywordList"); } void on_namespacemetaDataDialogMetaDataAddButton_clicked(gpointer dummy, GtkWidget * uploadButton) { handleMetaDataListUpdate(metaXML, "namespaceMetaDataDialogMetaTypeComboBox", "namespaceMetaDataValueEntry", "namespaceMetaDataDialogMetaDataList"); } void create_namespace_clicked(GtkWidget * dummy1, GtkWidget * dummy2) { const char * namespaceName; GtkWidget * nameLine; GtkWidget * dialog; GtkWidget * spin; struct ECRS_MetaData * meta; struct ECRS_URI * keywordURI; struct ECRS_URI * root; HashCode512 namespaceId; HashCode512 rootEntry; metaXML = glade_xml_new(getGladeFileName(), "namespaceMetaDataDialog", PACKAGE_NAME); connectGladeWithPlugins(metaXML); dialog = glade_xml_get_widget(metaXML, "namespaceMetaDataDialog"); createMetaDataListTreeView(metaXML, "namespaceMetaDataDialogMetaDataList", NULL, NULL); createKeywordListTreeView(metaXML, "namespaceMetaDataDialogKeywordList", NULL); createMetaTypeComboBox(metaXML, "namespaceMetaDataDialogMetaTypeComboBox"); gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK); if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK) { meta = getMetaDataFromList(metaXML, "namespaceMetaDataDialogMetaDataList", NULL); keywordURI = getKeywordURIFromList(metaXML, "namespaceMetaDataDialogKeywordList"); spin = glade_xml_get_widget(metaXML, "namespaceAnonymityspinbutton"); nameLine = glade_xml_get_widget(metaXML, "namespaceRootEntry"); namespaceName = gtk_entry_get_text(GTK_ENTRY(nameLine)); if (namespaceName == NULL) namespaceName = "root"; /* do NOT translate "root"! */ hash(namespaceName, strlen(namespaceName), &rootEntry); nameLine = glade_xml_get_widget(metaXML, "namespaceNameEntry"); namespaceName = gtk_entry_get_text(GTK_ENTRY(nameLine)); root = FSUI_createNamespace(ctx, gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(spin)), namespaceName, meta, keywordURI, &rootEntry); if (root != NULL) { ECRS_getNamespaceId(root, &namespaceId); addTabForNamespace(NULL, namespaceName, &namespaceId, meta, 0); ECRS_freeUri(root); } else { GtkWidget * dialog; dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, _("Failed to create namespace `%s'." "Consult logs, most likely error is" " that a namespace with that name " "already exists."), namespaceName); gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(dialog); } ECRS_freeMetaData(meta); ECRS_freeUri(keywordURI); } gtk_widget_destroy(dialog); UNREF(metaXML); metaXML = NULL; } void namespaceDelete_clicked(GtkWidget * dummy1, GtkWidget * dummy2) { GtkWidget * notebook; NamespaceList * list; NamespaceList * prev; gint num; GtkWidget * page; GtkWidget * dialog; gint ret; notebook = glade_xml_get_widget(getMainXML(), "localNamespacesNotebook"); num = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook)); if (num == -1) { /* IMPROVE-ME: disable the menu item as long as this may happen! */ dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, _("No local namespaces available that could be deleted!")); gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(dialog); return; } page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook), num); list = head; prev = NULL; while ( (list != NULL) && (list->namespacepage != page) ) { prev = list; list = list->next; } if (list == NULL) { BREAK(); return; } /* open window to ask for confirmation, only then delete */ dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_YES_NO, _("Should the namespace `%s' really be deleted?"), list->name); ret = gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(dialog); if (GTK_RESPONSE_YES != ret) return; gtk_notebook_remove_page(GTK_NOTEBOOK(notebook), num); if (prev == NULL) head = list->next; else prev->next = list->next; FSUI_deleteNamespace(list->name); FREE(list->name); ECRS_freeMetaData(list->meta); FREE(list); } typedef struct { unsigned int anonymityLevel; char * namespaceName; TIME_T updateInterval; HashCode512 * lastId; HashCode512 thisId; HashCode512 * nextId; struct ECRS_MetaData * meta; } IUC; /** * Publish the selected file in the * selected namespace. */ static void initiateUpload(GtkTreeModel * model, GtkTreePath * path, GtkTreeIter * iter, gpointer data) { IUC * cls = data; struct ECRS_URI * resultURI; struct ECRS_URI * dst; struct ECRS_MetaData * ometa; struct ECRS_MetaData * meta; NamespaceList * list; ECRS_FileInfo fi; dst = NULL; meta = cls->meta; gtk_tree_model_get(model, iter, NAMESPACE_URI, &dst, NAMESPACE_META, &ometa, -1); /* FIXME: we may want to optionally combine the metadata from the original file ID (ometa) with the new metadata (cls->meta) here; or if we limit us to one file at a time, show the original metadata immediately with the dialog. */ if (dst == NULL) { BREAK(); return; } resultURI = FSUI_addToNamespace(ctx, cls->anonymityLevel, cls->namespaceName, cls->updateInterval, cls->lastId, &cls->thisId, cls->nextId, dst, meta); if (resultURI != NULL) { list = head; while ( (list != NULL) && (0 != strcmp(cls->namespaceName, list->name)) ) list = list->next; if (list == NULL) { BREAK(); } else { /* update namespace content list! */ fi.uri = dst; fi.meta = meta; addNamespaceContentToModel(list->model, &fi, &cls->thisId, cls->nextId, cls->updateInterval, cls->updateInterval + TIME(NULL)); } ECRS_freeUri(resultURI); } else { infoMessage(YES, _("Failed to insert content into namespace " "(consult logs).\n")); } } void on_namespaceInsertMetaDataDialogMetaDataAddButton_clicked(GtkWidget * dummy1, GtkWidget * dummy2) { handleMetaDataListUpdate(metaXML, "namespaceInsertMetaTypeComboBox", "metaDataValueEntry", "metaDataTreeView"); } void on_namespaceInsertButton_clicked(GtkWidget * dummy1, GtkWidget * dummy2) { const char * identifierName; NamespaceList * list; GtkWidget * nameLine; GtkWidget * page; GtkWidget * notebook; GtkWidget * dialog; struct ECRS_MetaData * meta; HashCode512 nextId; GtkWidget * contentList; GtkTreeSelection * selection; IUC cls; gint num; GtkTreeIter iter; contentList = glade_xml_get_widget(getMainXML(), "availableContentList"); selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(contentList)); if (0 == gtk_tree_selection_count_selected_rows(selection)) { /* IMPROVE-ME: disable the menu item as long as this may happen! */ dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, _("You must select some available content for publication first!")); gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(dialog); return; } if (FALSE == gtk_tree_selection_get_selected(selection, NULL, &iter)) { BREAK(); return; } gtk_tree_model_get(gtk_tree_view_get_model(GTK_TREE_VIEW(contentList)), &iter, NAMESPACE_META, &meta, -1); notebook = glade_xml_get_widget(getMainXML(), "localNamespacesNotebook"); num = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook)); GNUNET_ASSERT(num != -1); page =gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook), num); list = head; while ( (list != NULL) && (list->namespacepage != page) ) list = list->next; if (list == NULL) { BREAK(); return; } cls.namespaceName = list->name; metaXML = glade_xml_new(getGladeFileName(), "namespaceInsertDialog", PACKAGE_NAME); connectGladeWithPlugins(metaXML); createMetaDataListTreeView(metaXML, "metaDataTreeView", "namespaceInsertPreview", meta); createMetaTypeComboBox(metaXML, "namespaceInsertMetaTypeComboBox"); dialog = glade_xml_get_widget(metaXML, "namespaceInsertDialog"); gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK); if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK) { if (OK != tryParseTimeInterval(metaXML, "updateIntervalComboBoxEntry", &cls.updateInterval)) { gtk_widget_destroy(dialog); UNREF(metaXML); metaXML = NULL; dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, _("Failed to parse given time interval!")); gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(dialog); return; } meta = getMetaDataFromList(metaXML, "metaDataTreeView", "namespaceInsertPreview"); cls.anonymityLevel = getAnonymityLevel(metaXML, "anonymitySpinButton"); nameLine = glade_xml_get_widget(metaXML, "namespaceContentIdentifierEntry"); identifierName = gtk_entry_get_text(GTK_ENTRY(nameLine)); if (identifierName == NULL) identifierName = ""; hash(identifierName, strlen(identifierName), &cls.thisId); cls.lastId = NULL; nameLine = glade_xml_get_widget(metaXML, "nextIdentifierEntry"); identifierName = gtk_entry_get_text(GTK_ENTRY(nameLine)); if ( (identifierName == NULL) || (strlen(identifierName) == 0)) { cls.nextId = NULL; } else { hash(identifierName, strlen(identifierName), &nextId); cls.nextId = &nextId; } cls.meta = meta; gtk_tree_selection_selected_foreach (selection, &initiateUpload, &cls); ECRS_freeMetaData(meta); } gtk_widget_destroy(dialog); UNREF(metaXML); metaXML = NULL; } void on_namespaceUpdateButton_clicked(GtkWidget * dummy1, GtkWidget * dummy2) { const char * identifierName; NamespaceList * list; GtkWidget * nameLine; GtkWidget * page; GtkWidget * notebook; GtkWidget * dialog; GtkWidget * spin; GtkWidget * update; GtkTreeIter iter; struct ECRS_MetaData * meta; HashCode512 nextId; HashCode512 prevId; GtkWidget * contentList; GtkTreeSelection * selection; GtkTreeSelection * selectionNamespace; IUC cls; gint num; const char * last; const char * next; const char * freq; contentList = glade_xml_get_widget(getMainXML(), "availableContentList"); selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(contentList)); if (0 == gtk_tree_selection_count_selected_rows(selection)) { /* IMPROVE-ME: disable the menu item as long as this may happen! */ dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, _("You must select some available content for publication first!")); gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(dialog); return; } if (FALSE == gtk_tree_selection_get_selected(selection, NULL, &iter)) { BREAK(); return; } gtk_tree_model_get(gtk_tree_view_get_model(GTK_TREE_VIEW(contentList)), &iter, NAMESPACE_META, &meta, -1); notebook = glade_xml_get_widget(getMainXML(), "localNamespacesNotebook"); num = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook)); GNUNET_ASSERT(num != -1); page =gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook), num); list = head; while ( (list != NULL) && (list->namespacepage != page) ) list = list->next; if (list == NULL) { BREAK(); return; } cls.namespaceName = list->name; /* check that in namespace (updateable) content is selected! */ selectionNamespace = gtk_tree_view_get_selection(GTK_TREE_VIEW(list->treeview)); if (0 == gtk_tree_selection_count_selected_rows(selectionNamespace)) { /* IMPROVE-ME: disable the menu item as long as this may happen! */ dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, _("You must select some existing namespace content to be updated first!")); gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(dialog); return; } if (FALSE == gtk_tree_selection_get_selected(selectionNamespace, NULL, &iter)) { BREAK(); return; } gtk_tree_model_get(list->model, &iter, IN_NAMESPACE_LAST_STRING, &last, IN_NAMESPACE_NEXT_STRING, &next, IN_NAMESPACE_PUB_FREQ_STRING, &freq, -1); metaXML = glade_xml_new(getGladeFileName(), "namespaceUpdateDialog", PACKAGE_NAME); connectGladeWithPlugins(metaXML); nameLine = glade_xml_get_widget(metaXML, "identifierLabel"); gtk_label_set_text(GTK_LABEL(nameLine), next); if (OK != enc2hash(next, &cls.thisId)) { BREAK(); UNREF(metaXML); metaXML = NULL; return; } if (OK == enc2hash(last, &prevId)) { cls.lastId = &prevId; } else { BREAK(); /* should not happen, try to continue */ cls.lastId = NULL; } nameLine = glade_xml_get_widget(metaXML, "nextIdentifierEntry"); if (OK != parseTimeInterval(freq, &cls.updateInterval)) { BREAK(); cls.updateInterval = ECRS_SBLOCK_UPDATE_SPORADIC; } if (cls.updateInterval == ECRS_SBLOCK_UPDATE_SPORADIC) { gtk_entry_set_text(GTK_ENTRY(nameLine), ""); } else { EncName updateName; if (OK != FSUI_computeNextId(list->name, &prevId, &cls.thisId, cls.updateInterval, &nextId)) { BREAK(); UNREF(metaXML); metaXML = NULL; return; } hash2enc(&nextId, &updateName); gtk_entry_set_text(GTK_ENTRY(nameLine), (const char*) &updateName); gtk_entry_set_editable(GTK_ENTRY(nameLine), FALSE); } update = glade_xml_get_widget(metaXML, "namespaceUpdateIntervalComboBoxEntry"); gtk_entry_set_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(update))), freq); createMetaDataListTreeView(metaXML, "namespaceUpdateMetaDataTreeView", "namespaceUpdatePreviewImage", meta); createMetaTypeComboBox(metaXML, "namespaceUpdateMetaTypeComboBox"); dialog = glade_xml_get_widget(metaXML, "namespaceUpdateDialog"); gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK); if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK) { const char * error = NULL; nameLine = glade_xml_get_widget(metaXML, "nextIdentifierEntry"); if (OK != tryParseTimeInterval(metaXML, "namespaceUpdateIntervalComboBoxEntry", &cls.updateInterval)) { error = _("Failed to parse given time interval!"); } else { identifierName = gtk_entry_get_text(GTK_ENTRY(nameLine)); if ( (cls.updateInterval != ECRS_SBLOCK_UPDATE_NONE) && ( (identifierName == NULL) || (strlen(identifierName) == 0)) ) { error = _("You must specify an identifier for the next publication."); } } if (error != NULL) { gtk_widget_destroy(dialog); UNREF(metaXML); metaXML = NULL; dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, error); gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(dialog); return; } hash(identifierName, strlen(identifierName), &nextId); cls.nextId = &nextId; cls.meta = getMetaDataFromList(metaXML, "namespaceUpdateMetaDataTreeView", "namespaceUpdatePreviewImage"); spin = glade_xml_get_widget(metaXML, "namespaceUpdateAnonymitySpinButton"); cls.anonymityLevel = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(spin)); gtk_tree_selection_selected_foreach (selection, &initiateUpload, &cls); ECRS_freeMetaData(cls.meta); } gtk_widget_destroy(dialog); UNREF(metaXML); metaXML = NULL; } void on_clearAvailableContentButton_clicked(GtkWidget * dummy1, GtkWidget * dummy2) { GtkWidget * contentList; GtkTreeModel * model; contentList = glade_xml_get_widget(getMainXML(), "availableContentList"); model = gtk_tree_view_get_model(GTK_TREE_VIEW(contentList)); FSUI_clearTrackedURIS(); gtkSaveCall(&clearContentList, model); updateContentList(NULL); } void on_trackingCheckButton_toggled(GtkWidget * dummy1, GtkWidget * dummy2) { GtkWidget * trackCheckButton; trackCheckButton = glade_xml_get_widget(getMainXML(), "trackingCheckButton"); FSUI_trackURIS(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(trackCheckButton)) == TRUE ? YES : NO); } void fs_namespace_start() { GtkWidget * contentList; GtkListStore * model; GtkCellRenderer * renderer; GtkWidget * trackCheckButton; int col; trackCheckButton = glade_xml_get_widget(getMainXML(), "trackingCheckButton"); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(trackCheckButton), FSUI_trackStatus() == YES ? TRUE : FALSE); contentList = glade_xml_get_widget(getMainXML(), "availableContentList"); model = gtk_list_store_new(NAMESPACE_NUM, G_TYPE_STRING, /* name */ G_TYPE_UINT64, /* size */ G_TYPE_STRING, /* uri-string */ G_TYPE_POINTER, G_TYPE_POINTER); /* uri */ gtk_tree_view_set_model(GTK_TREE_VIEW(contentList), GTK_TREE_MODEL(model)); renderer = gtk_cell_renderer_text_new(); col = gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(contentList), -1, _("Filename"), renderer, "text", NAMESPACE_FILENAME, NULL); gtk_tree_view_column_set_resizable(gtk_tree_view_get_column(GTK_TREE_VIEW(contentList), col - 1), TRUE); renderer = gtk_cell_renderer_text_new(); col = gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(contentList), -1, _("Filesize"), renderer, "text", NAMESPACE_SIZE, NULL); gtk_tree_view_column_set_resizable(gtk_tree_view_get_column(GTK_TREE_VIEW(contentList), col - 1), TRUE); renderer = gtk_cell_renderer_text_new(); col = gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(contentList), -1, _("URI"), renderer, "text", NAMESPACE_URISTRING, NULL); gtk_tree_view_column_set_resizable(gtk_tree_view_get_column(GTK_TREE_VIEW(contentList), col - 1), TRUE); addCronJob(&updateContentList, 0, UPDATE_CONTENT_LIST_FREQUENCY, NULL); FSUI_listNamespaces(ctx, YES, &addTabForNamespace, NULL); } #if 0 void on_availableContentList_destroy(GtkWidget * dummy1, GtkWidget * dummy2) { GtkWidget * contentList; GtkTreeModel * model; delCronJob(&updateContentList, UPDATE_CONTENT_LIST_FREQUENCY, NULL); contentList = glade_xml_get_widget(getMainXML(), "availableContentList"); model = gtk_tree_view_get_model(GTK_TREE_VIEW(contentList)); clearContentList(model); } void on_localNamespacesNotebook_destroy(GtkWidget * dummy1, GtkWidget * dummy2) { NamespaceList * pos; GtkTreeIter iter; struct ECRS_URI * u; struct ECRS_MetaData * m; while (head != NULL) { pos = head->next; FREE(head->name); ECRS_freeMetaData(head->meta); if (gtk_tree_model_get_iter_first(head->model, &iter)) { do { gtk_tree_model_get(head->model, &iter, IN_NAMESPACE_URI, &u, IN_NAMESPACE_META, &m, -1); gtk_list_store_set(GTK_LIST_STORE(head->model), &iter, IN_NAMESPACE_URI, NULL, IN_NAMESPACE_META, NULL, -1); if (u != NULL) ECRS_freeUri(u); if (m != NULL) ECRS_freeMetaData(m); } while (gtk_tree_model_iter_next(head->model, &iter)); } FREE(head); head = pos; } } #endif void fs_namespace_stop() { } /* end of namespace.c */