gimp/plug-ins/metadata/metadata-xml.c

1180 lines
40 KiB
C

/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* metadata-editor.c
* Copyright (C) 2016, 2017 Ben Touchette
*
* This program 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 3 of the License, or
* (at your option) any later version.
*
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <stdlib.h>
#include <ctype.h>
#include <gegl.h>
#include <gtk/gtk.h>
#include <gexiv2/gexiv2.h>
#include <glib.h>
#include <glib/gstdio.h>
#include <libgimp/gimp.h>
#include <libgimp/gimpui.h>
#include "libgimp/stdplugins-intl.h"
#include "metadata-misc.h"
#include "metadata-xml.h"
#include "metadata-tags.h"
extern gboolean gimpmetadata;
extern gboolean force_write;
gboolean xmptag;
gboolean iptctag;
gboolean tagvalue;
gboolean taglistvalue;
gboolean tagname;
gboolean tagmode;
gboolean listelement;
gboolean element;
gchar *str_tag_value;
gchar *str_tag_name;
gchar *str_tag_mode;
gchar *str_element;
gchar *list_tag_data[256][256];
gint row_count = 0;
gint item_count = 0;
void
xml_parser_start_element (GMarkupParseContext *context,
const gchar *element_name,
const gchar **attribute_names,
const gchar **attribute_values,
gpointer user_data,
GError **error)
{
if (strcmp (element_name, "gimp-metadata") == 0)
{
gimpmetadata = TRUE;
}
else if (strcmp (element_name, "iptc-tag") == 0)
{
item_count = 0;
row_count = 0;
iptctag = TRUE;
}
else if (strcmp (element_name, "xmp-tag") == 0)
{
item_count = 0;
row_count = 0;
xmptag = TRUE;
}
else if (strcmp (element_name, "tag-value") == 0)
{
tagvalue = TRUE;
}
else if (strcmp (element_name, "tag-list-value") == 0)
{
taglistvalue = TRUE;
}
else if (strcmp (element_name, "tag-name") == 0)
{
tagname = TRUE;
}
else if (strcmp (element_name, "tag-mode") == 0)
{
tagmode = TRUE;
}
else if (strcmp (element_name, "list-element") == 0)
{
listelement = TRUE;
row_count += 1;
}
else if (strcmp (element_name, "element") == 0)
{
element = TRUE;
item_count += 1;
}
}
void
xml_parser_data (GMarkupParseContext *context,
const gchar *text,
gsize text_len,
gpointer user_data,
GError **error)
{
if (tagvalue)
{
if (str_tag_value)
g_free(str_tag_value);
if (text)
str_tag_value = g_strdup(text);
else
str_tag_value = g_strconcat("", NULL);
}
else if (tagname)
{
if (str_tag_name)
g_free(str_tag_name);
if (text)
str_tag_name = g_strdup(text);
else
str_tag_name = g_strconcat("", NULL);
}
else if (tagmode)
{
if (str_tag_mode)
g_free(str_tag_mode);
if (text)
str_tag_mode = g_strdup(text);
else
str_tag_mode = g_strconcat("", NULL);
}
else if (element)
{
if (str_element)
g_free(str_element);
if (text)
str_element = g_strdup(text);
else
str_element = g_strconcat("", NULL);
}
}
void
set_tag_ui (metadata_editor *args,
gint index,
gchar *name,
gchar *value,
gchar* mode)
{
GtkWidget *widget;
gchar *value_utf;
widget = GTK_WIDGET (gtk_builder_get_object (args->builder, str_tag_name));
if (!strcmp ("single", mode))
{
GtkEntry *entry_widget;
value_utf = g_locale_to_utf8 (str_tag_value, -1, NULL, NULL, NULL);
entry_widget = GTK_ENTRY (widget);
gtk_entry_set_text (entry_widget, value_utf);
}
else if (!strcmp ("multi", mode))
{
GtkTextView *text_view;
GtkTextBuffer *buffer;
value_utf = g_locale_to_utf8 (str_tag_value, -1, NULL, NULL, NULL);
text_view = GTK_TEXT_VIEW (widget);
buffer = gtk_text_view_get_buffer (text_view);
gtk_text_buffer_set_text (buffer, value_utf, -1);
}
else if (!strcmp ("combo", mode))
{
gint32 value;
value_utf = g_locale_to_utf8 (str_tag_value, -1, NULL, NULL, NULL);
value = atoi(value_utf);
gtk_combo_box_set_active (GTK_COMBO_BOX(widget), value);
}
else if (!strcmp ("list", mode))
{
GtkTreeModel *treemodel;
GtkListStore *liststore;
GtkTreeIter iter;
gint number_of_rows;
gint row;
gint item;
liststore = GTK_LIST_STORE(gtk_tree_view_get_model((GtkTreeView *)widget));
treemodel = GTK_TREE_MODEL (liststore);
number_of_rows =
gtk_tree_model_iter_n_children(GTK_TREE_MODEL(liststore), NULL);
/* Clear all current values */
for (row = number_of_rows; row > -1; row--)
{
if (gtk_tree_model_iter_nth_child(treemodel, &iter, NULL, row))
{
gtk_list_store_remove(liststore, &iter);
}
}
/* Add new values values */
if (!strcmp ("Xmp.plus.Licensor", name))
{
for (row = 1; row < row_count+1; row++)
{
gtk_list_store_append (liststore, &iter);
gtk_list_store_set (liststore, &iter,
COL_LICENSOR_NAME, list_tag_data[row][1],
COL_LICENSOR_ID, list_tag_data[row][2],
COL_LICENSOR_PHONE1, list_tag_data[row][3],
COL_LICENSOR_PHONE_TYPE1, list_tag_data[row][4],
COL_LICENSOR_PHONE2, list_tag_data[row][5],
COL_LICENSOR_PHONE_TYPE2, list_tag_data[row][6],
COL_LICENSOR_EMAIL, list_tag_data[row][7],
COL_LICENSOR_WEB, list_tag_data[row][8],
-1);
for (item = 1; item < G_N_ELEMENTS (licensor) + 1; item++)
{
if (list_tag_data[row][item])
{
if (list_tag_data[row][item])
g_free(list_tag_data[row][item]);
}
}
}
if (row_count < 2)
{
for (row = 0; row < 2 - row_count; row++)
{
gtk_list_store_append (liststore, &iter);
gtk_list_store_set (liststore, &iter,
COL_LICENSOR_NAME, NULL,
COL_LICENSOR_ID, NULL,
COL_LICENSOR_PHONE1, NULL,
COL_LICENSOR_PHONE_TYPE1, NULL,
COL_LICENSOR_PHONE2, NULL,
COL_LICENSOR_PHONE_TYPE2, NULL,
COL_LICENSOR_EMAIL, NULL,
COL_LICENSOR_WEB, NULL,
-1);
}
}
}
else if (!strcmp ("Xmp.plus.ImageCreator", name))
{
for (row = 1; row < row_count+1; row++)
{
gtk_list_store_append (liststore, &iter);
gtk_list_store_set (liststore, &iter,
COL_IMG_CR8_NAME, list_tag_data[row][1],
COL_IMG_CR8_ID, list_tag_data[row][2],
-1);
for (item = 1; item < G_N_ELEMENTS (imagecreator) + 1; item++)
{
if (list_tag_data[row][item])
{
if (list_tag_data[row][item])
g_free(list_tag_data[row][item]);
}
}
}
if (row_count < 2)
{
for (row = 0; row < 2 - row_count; row++)
{
gtk_list_store_append (liststore, &iter);
gtk_list_store_set (liststore, &iter,
COL_IMG_CR8_NAME, NULL,
COL_IMG_CR8_ID, NULL,
-1);
}
}
}
else if (!strcmp ("Xmp.iptcExt.ArtworkOrObject", name))
{
for (row = 1; row < row_count+1; row++)
{
gtk_list_store_append (liststore, &iter);
gtk_list_store_set (liststore, &iter,
COL_AOO_TITLE, list_tag_data[row][1],
COL_AOO_DATE_CREAT, list_tag_data[row][2],
COL_AOO_CREATOR, list_tag_data[row][3],
COL_AOO_SOURCE, list_tag_data[row][4],
COL_AOO_SRC_INV_ID, list_tag_data[row][5],
COL_AOO_CR_NOT, list_tag_data[row][6],
-1);
for (item = 1; item < G_N_ELEMENTS (artworkorobject) + 1; item++)
{
if (list_tag_data[row][item])
{
if (list_tag_data[row][item])
g_free(list_tag_data[row][item]);
}
}
}
if (row_count < 2)
{
for (row = 0; row < 2 - row_count; row++)
{
gtk_list_store_append (liststore, &iter);
gtk_list_store_set (liststore, &iter,
COL_AOO_TITLE, NULL,
COL_AOO_DATE_CREAT, NULL,
COL_AOO_CREATOR, NULL,
COL_AOO_SOURCE, NULL,
COL_AOO_SRC_INV_ID, NULL,
COL_AOO_CR_NOT, NULL,
-1);
}
}
}
else if (!strcmp ("Xmp.iptcExt.RegistryId", name))
{
for (row = 1; row < row_count+1; row++)
{
gtk_list_store_append (liststore, &iter);
gtk_list_store_set (liststore, &iter,
COL_REGSITRY_ORG_ID, list_tag_data[row][1],
COL_REGSITRY_ITEM_ID, list_tag_data[row][2],
-1);
for (item = 1; item < G_N_ELEMENTS (registryid) + 1; item++)
{
if (list_tag_data[row][item])
{
if (list_tag_data[row][item])
g_free(list_tag_data[row][item]);
}
}
}
if (row_count < 2)
{
for (row = 0; row < 2 - row_count; row++)
{
gtk_list_store_append (liststore, &iter);
gtk_list_store_set (liststore, &iter,
COL_REGSITRY_ORG_ID, NULL,
COL_REGSITRY_ITEM_ID, NULL,
-1);
}
}
}
else if (!strcmp ("Xmp.plus.CopyrightOwner", name))
{
if (row_count > 0)
{
for (row = 1; row < row_count+1; row++)
{
gtk_list_store_append (liststore, &iter);
gtk_list_store_set (liststore, &iter,
COL_CR_OWNER_NAME, list_tag_data[row][1],
COL_CR_OWNER_ID, list_tag_data[row][2],
-1);
for (item = 1; item < G_N_ELEMENTS (copyrightowner) + 1; item++)
{
if (list_tag_data[row][item])
{
if (list_tag_data[row][item])
g_free(list_tag_data[row][item]);
}
}
}
}
if (row_count < 2)
{
for (row = 0; row < 2 - row_count; row++)
{
gtk_list_store_append (liststore, &iter);
gtk_list_store_set (liststore, &iter,
COL_CR_OWNER_NAME, NULL,
COL_CR_OWNER_ID, NULL,
-1);
}
}
}
else if (!strcmp ("Xmp.iptcExt.LocationShown", name))
{
for (row = 1; row < row_count+1; row++)
{
gtk_list_store_append (liststore, &iter);
gtk_list_store_set (liststore, &iter,
COL_LOC_SHO_SUB_LOC, list_tag_data[row][1],
COL_LOC_SHO_CITY, list_tag_data[row][2],
COL_LOC_SHO_STATE_PROV, list_tag_data[row][3],
COL_LOC_SHO_CNTRY, list_tag_data[row][4],
COL_LOC_SHO_CNTRY_ISO, list_tag_data[row][5],
COL_LOC_SHO_CNTRY_WRLD_REG, list_tag_data[row][6],
-1);
for (item = 1; item < G_N_ELEMENTS (locationshown) + 1; item++)
{
if (list_tag_data[row][item])
{
if (list_tag_data[row][item])
g_free(list_tag_data[row][item]);
}
}
}
if (row_count < 2)
{
for (row = 0; row < 2 - row_count; row++)
{
gtk_list_store_append (liststore, &iter);
gtk_list_store_set (liststore, &iter,
COL_LOC_SHO_SUB_LOC, NULL,
COL_LOC_SHO_CITY, NULL,
COL_LOC_SHO_STATE_PROV, NULL,
COL_LOC_SHO_CNTRY, NULL,
COL_LOC_SHO_CNTRY_ISO, NULL,
COL_LOC_SHO_CNTRY_WRLD_REG, NULL,
-1);
}
}
}
else if (!strcmp ("Xmp.iptcExt.OrganisationInImageName", name))
{
for (row = 1; row < row_count+1; row++)
{
gtk_list_store_append (liststore, &iter);
gtk_list_store_set (liststore, &iter,
COL_ORG_IMG_NAME, list_tag_data[row][1],
-1);
if (list_tag_data[row][1])
{
if (list_tag_data[row][1])
g_free(list_tag_data[row][1]);
}
}
if (row_count < 2)
{
for (row = 0; row < 2 - row_count; row++)
{
gtk_list_store_append (liststore, &iter);
gtk_list_store_set (liststore, &iter,
COL_ORG_IMG_NAME, NULL,
-1);
}
}
}
else if (!strcmp ("Xmp.iptcExt.OrganisationInImageCode", name))
{
for (row = 1; row < row_count+1; row++)
{
gtk_list_store_append (liststore, &iter);
gtk_list_store_set (liststore, &iter,
COL_ORG_IMG_CODE, list_tag_data[row][1],
-1);
if (list_tag_data[row][1])
{
if (list_tag_data[row][1])
g_free(list_tag_data[row][1]);
}
}
if (row_count < 2)
{
for (row = 0; row < 2 - row_count; row++)
{
gtk_list_store_append (liststore, &iter);
gtk_list_store_set (liststore, &iter,
COL_ORG_IMG_CODE, NULL,
-1);
}
}
}
else if (!strcmp ("Xmp.plus.PropertyReleaseID", name))
{
for (row = 1; row < row_count+1; row++)
{
gtk_list_store_append (liststore, &iter);
gtk_list_store_set (liststore, &iter,
COL_PROP_REL_ID, list_tag_data[row][1],
-1);
if (list_tag_data[row][1])
{
if (list_tag_data[row][1])
g_free(list_tag_data[row][1]);
}
}
if (row_count < 2)
{
for (row = 0; row < 2 - row_count; row++)
{
gtk_list_store_append (liststore, &iter);
gtk_list_store_set (liststore, &iter,
COL_PROP_REL_ID, NULL,
-1);
}
}
}
else if (!strcmp ("Xmp.plus.ModelReleaseID", name))
{
for (row = 1; row < row_count+1; row++)
{
gtk_list_store_append (liststore, &iter);
gtk_list_store_set (liststore, &iter,
COL_MOD_REL_ID, list_tag_data[row][1],
-1);
if (list_tag_data[row][1])
{
if (list_tag_data[row][1])
g_free(list_tag_data[row][1]);
}
}
if (row_count < 2)
{
for (row = 0; row < 2 - row_count; row++)
{
gtk_list_store_append (liststore, &iter);
gtk_list_store_set (liststore, &iter,
COL_MOD_REL_ID, NULL,
-1);
}
}
}
}
}
const gchar *
get_tag_ui_text (metadata_editor *args,
gchar *name,
gchar *mode)
{
GObject *object;
object = gtk_builder_get_object (args->builder, name);
if (! strcmp ("single", mode))
{
GtkEntry *entry = GTK_ENTRY (object);
return gtk_entry_get_text (entry);
}
else if (!strcmp ("multi", mode))
{
GtkTextView *text_view = GTK_TEXT_VIEW (object);
GtkTextBuffer *buffer;
GtkTextIter start;
GtkTextIter end;
buffer = gtk_text_view_get_buffer (text_view);
gtk_text_buffer_get_start_iter (buffer, &start);
gtk_text_buffer_get_end_iter (buffer, &end);
return gtk_text_buffer_get_text (buffer, &start, &end, TRUE);
}
return NULL;
}
gchar *
get_tag_ui_list (metadata_editor *args, gchar *name, gchar *mode)
{
GObject *object;
GtkWidget *widget;
GtkTreeModel *treemodel;
GtkListStore *liststore;
GtkTreeIter iter;
gchar *xmldata;
gint number_of_rows;
gint row;
gint has_data;
gchar *tagdata[256][256];
has_data = FALSE;
xmldata = (gchar*)g_malloc(262144);
object = gtk_builder_get_object (args->builder, name);
widget = GTK_WIDGET(object);
liststore = GTK_LIST_STORE(gtk_tree_view_get_model((GtkTreeView *)widget));
treemodel = GTK_TREE_MODEL (liststore);
number_of_rows =
gtk_tree_model_iter_n_children(GTK_TREE_MODEL(liststore), NULL);
for (row = 0; row < number_of_rows; row++)
{
if (gtk_tree_model_iter_nth_child(treemodel, &iter, NULL, row))
{
if (!strcmp ("Xmp.plus.Licensor", name))
{
gtk_tree_model_get (treemodel, &iter,
COL_LICENSOR_NAME, &tagdata[row][0],
COL_LICENSOR_ID, &tagdata[row][1],
COL_LICENSOR_PHONE1, &tagdata[row][2],
COL_LICENSOR_PHONE_TYPE1, &tagdata[row][3],
COL_LICENSOR_PHONE2, &tagdata[row][4],
COL_LICENSOR_PHONE_TYPE2, &tagdata[row][5],
COL_LICENSOR_EMAIL, &tagdata[row][6],
COL_LICENSOR_WEB, &tagdata[row][7],
-1);
if ((tagdata[row][0] != NULL && strlen(tagdata[row][0]) > 0) ||
(tagdata[row][1] != NULL && strlen(tagdata[row][1]) > 0) ||
(tagdata[row][2] != NULL && strlen(tagdata[row][2]) > 0) ||
(tagdata[row][3] != NULL && strlen(tagdata[row][3]) > 0) ||
(tagdata[row][4] != NULL && strlen(tagdata[row][4]) > 0) ||
(tagdata[row][5] != NULL && strlen(tagdata[row][5]) > 0) ||
(tagdata[row][6] != NULL && strlen(tagdata[row][6]) > 0) ||
(tagdata[row][7] != NULL && strlen(tagdata[row][7]) > 0))
{
gint types;
has_data = TRUE;
xmldata = g_strconcat (xmldata, "\t\t\t<list-element>\n", NULL);
for (types = 0; types < 8; types++)
{
xmldata = g_strconcat (xmldata, "\t\t\t\t<element>", NULL);
xmldata = g_strconcat (xmldata, tagdata[row][types], NULL);
xmldata = g_strconcat (xmldata, "</element>\n", NULL);
}
xmldata = g_strconcat (xmldata, "\t\t\t</list-element>\n", NULL);
}
}
else if (!strcmp ("Xmp.plus.CopyrightOwner", name))
{
gtk_tree_model_get (treemodel, &iter,
COL_CR_OWNER_NAME, &tagdata[row][0],
COL_CR_OWNER_ID, &tagdata[row][1],
-1);
if ((tagdata[row][0] != NULL && strlen(tagdata[row][0]) > 0) ||
(tagdata[row][1] != NULL && strlen(tagdata[row][1]) > 0))
{
has_data = TRUE;
xmldata = g_strconcat (xmldata, "\t\t\t<list-element>\n", NULL);
xmldata = g_strconcat (xmldata, "\t\t\t\t<element>", NULL);
xmldata = g_strconcat (xmldata, tagdata[row][0], NULL);
xmldata = g_strconcat (xmldata, "</element>\n", NULL);
xmldata = g_strconcat (xmldata, "\t\t\t\t<element>", NULL);
xmldata = g_strconcat (xmldata, tagdata[row][1], NULL);
xmldata = g_strconcat (xmldata, "</element>\n", NULL);
xmldata = g_strconcat (xmldata, "\t\t\t</list-element>\n", NULL);
}
}
else if (!strcmp ("Xmp.plus.ImageCreator", name))
{
gtk_tree_model_get (treemodel, &iter,
COL_IMG_CR8_NAME, &tagdata[row][0],
COL_IMG_CR8_ID, &tagdata[row][1],
-1);
if ((tagdata[row][0] != NULL && strlen(tagdata[row][0]) > 0) ||
(tagdata[row][1] != NULL && strlen(tagdata[row][1]) > 0))
{
gint types;
has_data = TRUE;
xmldata = g_strconcat (xmldata, "\t\t\t<list-element>\n", NULL);
for (types = 0; types < 2; types++)
{
xmldata = g_strconcat (xmldata, "\t\t\t\t<element>", NULL);
xmldata = g_strconcat (xmldata, tagdata[row][types], NULL);
xmldata = g_strconcat (xmldata, "</element>\n", NULL);
}
xmldata = g_strconcat (xmldata, "\t\t\t</list-element>\n", NULL);
}
}
else if (!strcmp ("Xmp.iptcExt.ArtworkOrObject", name))
{
gtk_tree_model_get (treemodel, &iter,
COL_AOO_TITLE, &tagdata[row][0],
COL_AOO_DATE_CREAT, &tagdata[row][1],
COL_AOO_CREATOR, &tagdata[row][2],
COL_AOO_SOURCE, &tagdata[row][3],
COL_AOO_SRC_INV_ID, &tagdata[row][4],
COL_AOO_CR_NOT, &tagdata[row][5],
-1);
if ((tagdata[row][0] != NULL && strlen(tagdata[row][0]) > 0) ||
(tagdata[row][1] != NULL && strlen(tagdata[row][1]) > 0) ||
(tagdata[row][2] != NULL && strlen(tagdata[row][2]) > 0) ||
(tagdata[row][3] != NULL && strlen(tagdata[row][3]) > 0) ||
(tagdata[row][4] != NULL && strlen(tagdata[row][4]) > 0) ||
(tagdata[row][5] != NULL && strlen(tagdata[row][5]) > 0))
{
gint types;
has_data = TRUE;
xmldata = g_strconcat (xmldata, "\t\t\t<list-element>\n", NULL);
for (types = 0; types < 6; types++)
{
xmldata = g_strconcat (xmldata, "\t\t\t\t<element>", NULL);
xmldata = g_strconcat (xmldata, tagdata[row][types], NULL);
xmldata = g_strconcat (xmldata, "</element>\n", NULL);
}
xmldata = g_strconcat (xmldata, "\t\t\t</list-element>\n", NULL);
}
}
else if (!strcmp ("Xmp.iptcExt.RegistryId", name))
{
gtk_tree_model_get (treemodel, &iter,
COL_REGSITRY_ORG_ID, &tagdata[row][0],
COL_REGSITRY_ITEM_ID, &tagdata[row][1],
-1);
if ((tagdata[row][0] != NULL && strlen(tagdata[row][0]) > 0) ||
(tagdata[row][1] != NULL && strlen(tagdata[row][1]) > 0))
{
gint types;
has_data = TRUE;
xmldata = g_strconcat (xmldata, "\t\t\t<list-element>\n", NULL);
for (types = 0; types < 2; types++)
{
xmldata = g_strconcat (xmldata, "\t\t\t\t<element>", NULL);
xmldata = g_strconcat (xmldata, tagdata[row][types], NULL);
xmldata = g_strconcat (xmldata, "</element>\n", NULL);
}
xmldata = g_strconcat (xmldata, "\t\t\t</list-element>\n", NULL);
}
}
else if (!strcmp ("Xmp.iptcExt.LocationShown", name))
{
gtk_tree_model_get (treemodel, &iter,
COL_LOC_SHO_SUB_LOC, &tagdata[row][0],
COL_LOC_SHO_CITY, &tagdata[row][1],
COL_LOC_SHO_STATE_PROV, &tagdata[row][2],
COL_LOC_SHO_CNTRY, &tagdata[row][3],
COL_LOC_SHO_CNTRY_ISO, &tagdata[row][4],
COL_LOC_SHO_CNTRY_WRLD_REG, &tagdata[row][5],
-1);
if ((tagdata[row][0] != NULL && strlen(tagdata[row][0]) > 0) ||
(tagdata[row][1] != NULL && strlen(tagdata[row][1]) > 0) ||
(tagdata[row][2] != NULL && strlen(tagdata[row][2]) > 0) ||
(tagdata[row][3] != NULL && strlen(tagdata[row][3]) > 0) ||
(tagdata[row][4] != NULL && strlen(tagdata[row][4]) > 0) ||
(tagdata[row][5] != NULL && strlen(tagdata[row][5]) > 0))
{
gint types;
has_data = TRUE;
xmldata = g_strconcat (xmldata, "\t\t\t<list-element>\n", NULL);
for (types = 0; types < 6; types++)
{
xmldata = g_strconcat (xmldata, "\t\t\t\t<element>", NULL);
xmldata = g_strconcat (xmldata, tagdata[row][types], NULL);
xmldata = g_strconcat (xmldata, "</element>\n", NULL);
}
xmldata = g_strconcat (xmldata, "\t\t\t</list-element>\n", NULL);
}
}
else if (!strcmp ("Xmp.iptcExt.OrganisationInImageName", name))
{
gtk_tree_model_get (treemodel, &iter,
COL_ORG_IMG_NAME, &tagdata[row][0],
-1);
if ((tagdata[row][0] != NULL && strlen(tagdata[row][0]) > 0))
{
has_data = TRUE;
xmldata = g_strconcat (xmldata, "\t\t\t<list-element>\n", NULL);
xmldata = g_strconcat (xmldata, "\t\t\t\t<element>", NULL);
xmldata = g_strconcat (xmldata, tagdata[row][0], NULL);
xmldata = g_strconcat (xmldata, "</element>\n", NULL);
xmldata = g_strconcat (xmldata, "\t\t\t</list-element>\n", NULL);
}
}
else if (!strcmp ("Xmp.iptcExt.OrganisationInImageCode", name))
{
gtk_tree_model_get (treemodel, &iter,
COL_ORG_IMG_CODE, &tagdata[row][0],
-1);
if ((tagdata[row][0] != NULL && strlen(tagdata[row][0]) > 0))
{
has_data = TRUE;
xmldata = g_strconcat (xmldata, "\t\t\t<list-element>\n", NULL);
xmldata = g_strconcat (xmldata, "\t\t\t\t<element>", NULL);
xmldata = g_strconcat (xmldata, tagdata[row][0], NULL);
xmldata = g_strconcat (xmldata, "</element>\n", NULL);
xmldata = g_strconcat (xmldata, "\t\t\t</list-element>\n", NULL);
}
}
else if (!strcmp ("Xmp.plus.PropertyReleaseID", name))
{
gtk_tree_model_get (treemodel, &iter,
COL_PROP_REL_ID, &tagdata[row][0],
-1);
if ((tagdata[row][0] != NULL && strlen(tagdata[row][0]) > 0))
{
has_data = TRUE;
xmldata = g_strconcat (xmldata, "\t\t\t<list-element>\n", NULL);
xmldata = g_strconcat (xmldata, "\t\t\t\t<element>", NULL);
xmldata = g_strconcat (xmldata, tagdata[row][0], NULL);
xmldata = g_strconcat (xmldata, "</element>\n", NULL);
xmldata = g_strconcat (xmldata, "\t\t\t</list-element>\n", NULL);
}
}
else if (!strcmp ("Xmp.plus.ModelReleaseID", name))
{
gtk_tree_model_get (treemodel, &iter,
COL_MOD_REL_ID, &tagdata[row][0],
-1);
if ((tagdata[row][0] != NULL && strlen(tagdata[row][0]) > 0))
{
has_data = TRUE;
xmldata = g_strconcat (xmldata, "\t\t\t<list-element>\n", NULL);
xmldata = g_strconcat (xmldata, "\t\t\t\t<element>", NULL);
xmldata = g_strconcat (xmldata, tagdata[row][0], NULL);
xmldata = g_strconcat (xmldata, "</element>\n", NULL);
xmldata = g_strconcat (xmldata, "\t\t\t</list-element>\n", NULL);
}
}
}
}
if (has_data == TRUE)
{
return xmldata;
}
g_free(xmldata);
return NULL;
}
gint
get_tag_ui_combo (metadata_editor *args, gchar *name, gchar *mode)
{
GObject *object;
GtkComboBoxText *combo;
gint value;
object = gtk_builder_get_object (args->builder, name);
combo = GTK_COMBO_BOX_TEXT (object);
value = gtk_combo_box_get_active (GTK_COMBO_BOX(combo));
return value;
}
void
xml_parser_end_element (GMarkupParseContext *context,
const gchar *element_name,
gpointer user_data,
GError **error)
{
metadata_editor *args;
int i;
args = user_data;
if (strcmp (element_name, "gimp-metadata") == 0)
{
gimpmetadata = FALSE;
}
else if (strcmp (element_name, "iptc-tag") == 0)
{
iptctag = FALSE;
#ifdef _ENABLE_IPTC_TAG_
if (str_tag_name && str_tag_value)
{
/* make sure to only allow supported tags */
for (i = 0; i < G_N_ELEMENTS (equivalent_metadata_tags); i++)
{
if (strcmp(equivalent_metadata_tags[i].tag, str_tag_name) == 0)
{
#ifdef _SET_IPTC_TAG_
set_tag_ui (args, i, str_tag_name, str_tag_value,
equivalent_metadata_tags[i].mode);
#endif
if (force_write == TRUE)
gexiv2_metadata_set_tag_string (args->metadata,
str_tag_name,
str_tag_value);
break;
}
}
}
#endif
}
else if (strcmp (element_name, "xmp-tag") == 0)
{
xmptag = FALSE;
if (strcmp (str_tag_mode, "list") != 0)
{
if (str_tag_name && str_tag_value)
{
/* make sure to only allow supported tags */
for (i = 0; i < G_N_ELEMENTS (default_metadata_tags); i++)
{
if (strcmp(default_metadata_tags[i].tag, str_tag_name) == 0)
{
set_tag_ui (args, i, str_tag_name, str_tag_value,
default_metadata_tags[i].mode);
#ifdef _ENABLE_FORCE_WRITE_
if (force_write == TRUE)
gexiv2_metadata_set_tag_string (args->metadata,
str_tag_name,
str_tag_value);
#endif
break;
}
}
}
}
else if (strcmp (str_tag_mode, "list") == 0)
{
if (row_count > 0)
{
/* make sure to only allow supported tags */
for (i = 0; i < G_N_ELEMENTS (default_metadata_tags); i++)
{
if (strcmp(default_metadata_tags[i].tag, str_tag_name) == 0)
{
set_tag_ui (args, i, str_tag_name, str_tag_value,
default_metadata_tags[i].mode);
#ifdef _ENABLE_FORCE_WRITE_
if (force_write == TRUE)
gexiv2_metadata_set_tag_string (args->metadata,
str_tag_name,
str_tag_value);
#endif
break;
}
}
}
row_count = 0;
item_count = 0;
}
}
else if (strcmp (element_name, "tag-value") == 0)
{
tagvalue = FALSE;
}
else if (strcmp (element_name, "tag-list-value") == 0)
{
taglistvalue = FALSE;
}
else if (strcmp (element_name, "tag-name") == 0)
{
tagname = FALSE;
}
else if (strcmp (element_name, "tag-mode") == 0)
{
tagmode = FALSE;
}
else if (strcmp (element_name, "list-element") == 0)
{
listelement = FALSE;
item_count = 0;
}
else if (strcmp (element_name, "element") == 0)
{
element = FALSE;
list_tag_data[row_count][item_count] = g_strdup(str_element);
}
}
gboolean
xml_parser_parse_file (GimpXmlParser *parser,
const gchar *filename,
GError **error)
{
GIOChannel *io;
gboolean success;
g_return_val_if_fail (parser != NULL, FALSE);
g_return_val_if_fail (filename != NULL, FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
io = g_io_channel_new_file (filename, "r", error);
if (!io)
return FALSE;
success = xml_parser_parse_io_channel (parser, io, error);
g_io_channel_unref (io);
return success;
}
GimpXmlParser *
xml_parser_new (const GMarkupParser *markup_parser,
gpointer user_data)
{
GimpXmlParser *parser;
g_return_val_if_fail (markup_parser != NULL, NULL);
parser = g_slice_new (GimpXmlParser);
parser->context = g_markup_parse_context_new (markup_parser,
0, user_data, NULL);
return parser;
}
void
xml_parser_free (GimpXmlParser *parser)
{
g_return_if_fail (parser != NULL);
g_markup_parse_context_free (parser->context);
g_slice_free (GimpXmlParser, parser);
}
gboolean
parse_encoding (const gchar *text,
gint text_len,
gchar **encoding)
{
const gchar *start;
const gchar *end;
gint i;
g_return_val_if_fail (text, FALSE);
if (text_len < 20)
return FALSE;
start = g_strstr_len (text, text_len, "<?xml");
if (!start)
return FALSE;
end = g_strstr_len (start, text_len - (start - text), "?>");
if (!end)
return FALSE;
*encoding = NULL;
text_len = end - start;
if (text_len < 12)
return TRUE;
start = g_strstr_len (start + 1, text_len - 1, "encoding");
if (!start)
return TRUE;
start += 8;
while (start < end && *start == ' ')
start++;
if (*start != '=')
return TRUE;
start++;
while (start < end && *start == ' ')
start++;
if (*start != '\"' && *start != '\'')
return TRUE;
text_len = end - start;
if (text_len < 1)
return TRUE;
for (i = 1; i < text_len; i++)
if (start[i] == start[0])
break;
if (i == text_len || i < 3)
return TRUE;
*encoding = g_strndup (start + 1, i - 1);
return TRUE;
}
gboolean
xml_parser_parse_io_channel (GimpXmlParser *parser,
GIOChannel *io,
GError **error)
{
GIOStatus status;
gchar buffer[4096];
gsize len = 0;
gsize bytes;
const gchar *io_encoding;
gchar *encoding = NULL;
g_return_val_if_fail (parser != NULL, FALSE);
g_return_val_if_fail (io != NULL, FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
io_encoding = g_io_channel_get_encoding (io);
if (g_strcmp0 (io_encoding, "UTF-8"))
{
g_warning ("xml_parser_parse_io_channel():\n"
"The encoding has already been set on this GIOChannel!");
return FALSE;
}
/* try to determine the encoding */
g_io_channel_set_encoding (io, NULL, NULL);
while (len < sizeof (buffer))
{
status = g_io_channel_read_chars (io, buffer + len, 1, &bytes, error);
len += bytes;
if (status == G_IO_STATUS_ERROR)
return FALSE;
if (status == G_IO_STATUS_EOF)
break;
if (parse_encoding (buffer, len, &encoding))
break;
}
if (encoding)
{
if (! g_io_channel_set_encoding (io, encoding, error))
return FALSE;
if (encoding)
g_free (encoding);
}
else
{
g_io_channel_set_encoding (io, "UTF-8", NULL);
}
while (TRUE)
{
if (!g_markup_parse_context_parse (parser->context, buffer, len, error))
return FALSE;
status = g_io_channel_read_chars (io,
buffer, sizeof (buffer), &len, error);
switch (status)
{
case G_IO_STATUS_ERROR:
return FALSE;
case G_IO_STATUS_EOF:
return g_markup_parse_context_end_parse (parser->context, error);
case G_IO_STATUS_NORMAL:
case G_IO_STATUS_AGAIN:
break;
}
}
}