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

1138 lines
36 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 <gexiv2/gexiv2.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"
#include "metadata-editor.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;
static void get_list_elements (GString *xmldata,
int element_count,
gchar **rowtagdata);
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,
MetadataMode mode)
{
GtkWidget *widget = NULL;
widget = GTK_WIDGET (metadata_editor_get_widget (args, str_tag_name));
if (mode == MODE_SINGLE)
{
GtkEntry *entry_widget;
gchar *value_utf;
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);
g_free (value_utf);
}
else if (mode == MODE_MULTI)
{
GtkTextView *text_view;
GtkTextBuffer *buffer;
gchar *value_utf;
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);
g_free (value_utf);
}
else if (mode == MODE_COMBO)
{
gint32 value;
gchar *value_utf;
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);
g_free (value_utf);
}
else if (mode == MODE_LIST)
{
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 (LICENSOR_HEADER, 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 < n_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 (IMAGECREATOR_HEADER, 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 < n_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 (ARTWORKOROBJECT_HEADER, 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 < n_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 (REGISTRYID_HEADER, name))
{
for (row = 1; row < row_count+1; row++)
{
gtk_list_store_append (liststore, &iter);
gtk_list_store_set (liststore, &iter,
COL_REGISTRY_ORG_ID, list_tag_data[row][1],
COL_REGISTRY_ITEM_ID, list_tag_data[row][2],
-1);
for (item = 1; item < n_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_REGISTRY_ORG_ID, NULL,
COL_REGISTRY_ITEM_ID, NULL,
-1);
}
}
}
else if (!strcmp (COPYRIGHTOWNER_HEADER, 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 < n_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 (LOCATIONSHOWN_HEADER, 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 < n_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,
MetadataMode mode)
{
GtkWidget *widget = NULL;
widget = metadata_editor_get_widget (args, name);
if (mode == MODE_SINGLE)
{
GtkEntry *entry = GTK_ENTRY (widget);
return gtk_entry_get_text (entry);
}
else if (mode == MODE_MULTI)
{
GtkTextView *text_view = GTK_TEXT_VIEW (widget);
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;
}
static void
get_list_elements (GString *xmldata, int element_count, gchar **rowtagdata)
{
gint list_idx;
g_string_append (xmldata, "\t\t\t<list-element>\n");
for (list_idx = 0; list_idx < element_count; list_idx++)
{
g_string_append (xmldata, "\t\t\t\t<element>");
if (rowtagdata && rowtagdata[list_idx] && strlen(rowtagdata[list_idx]) > 0)
{
g_string_append (xmldata, rowtagdata[list_idx]);
}
g_string_append (xmldata, "</element>\n");
}
g_string_append (xmldata, "\t\t\t</list-element>\n");
}
gchar *
get_tag_ui_list (metadata_editor *args, gchar *name, MetadataMode mode)
{
GtkWidget *widget = NULL;
GtkTreeModel *treemodel;
GtkListStore *liststore;
GtkTreeIter iter;
GString *xmldata;
gint number_of_rows;
gint row;
gint has_data;
gchar *tagdata[256][256];
has_data = FALSE;
xmldata = g_string_new ("");
widget = metadata_editor_get_widget (args, name);
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 (LICENSOR_HEADER, 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))
{
has_data = TRUE;
get_list_elements (xmldata, 8, tagdata[row]);
}
}
else if (!strcmp (COPYRIGHTOWNER_HEADER, 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;
g_string_append (xmldata, "\t\t\t<list-element>\n");
g_string_append (xmldata, "\t\t\t\t<element>");
g_string_append (xmldata, tagdata[row][0]);
g_string_append (xmldata, "</element>\n");
g_string_append (xmldata, "\t\t\t\t<element>");
g_string_append (xmldata, tagdata[row][1]);
g_string_append (xmldata, "</element>\n");
g_string_append (xmldata, "\t\t\t</list-element>\n");
}
}
else if (!strcmp (IMAGECREATOR_HEADER, 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))
{
has_data = TRUE;
get_list_elements (xmldata, 2, tagdata[row]);
}
}
else if (!strcmp (ARTWORKOROBJECT_HEADER, 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))
{
has_data = TRUE;
get_list_elements (xmldata, 6, tagdata[row]);
}
}
else if (!strcmp (REGISTRYID_HEADER, name))
{
gtk_tree_model_get (treemodel, &iter,
COL_REGISTRY_ORG_ID, &tagdata[row][0],
COL_REGISTRY_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))
{
has_data = TRUE;
get_list_elements (xmldata, 2, tagdata[row]);
}
}
else if (!strcmp (LOCATIONSHOWN_HEADER, 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))
{
has_data = TRUE;
get_list_elements (xmldata, 6, tagdata[row]);
}
}
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;
get_list_elements (xmldata, 1, tagdata[row]);
}
}
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;
get_list_elements (xmldata, 1, tagdata[row]);
}
}
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;
get_list_elements (xmldata, 1, tagdata[row]);
}
}
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;
get_list_elements (xmldata, 1, tagdata[row]);
}
}
}
}
if (has_data == TRUE)
{
gchar *xml;
xml = g_strdup (xmldata->str);
g_string_free(xmldata, TRUE);
return xml;
}
g_string_free(xmldata, TRUE);
return NULL;
}
gint
get_tag_ui_combo (metadata_editor *args, gchar *name, MetadataMode mode)
{
return gtk_combo_box_get_active (GTK_COMBO_BOX(metadata_editor_get_widget (args, name)));
}
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 < n_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 < n_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 < n_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;
}
}
}