Commit 43c7faef authored by Paolo Bacchilega's avatar Paolo Bacchilega

fixed crash when embedded data contains invalid utf8 values

parent b2f87bae
......@@ -638,8 +638,12 @@ gth_comment_update_from_general_attributes (GthFileData *file_data)
if (metadata != NULL) {
text = g_file_info_get_attribute_string (file_data->info, "comment::note");
if (! dom_str_equal (gth_metadata_get_formatted (metadata), text)) {
gth_comment_set_note (comment, gth_metadata_get_formatted (metadata));
write_comment = TRUE;
char *value = _g_utf8_try_from_any (gth_metadata_get_formatted (metadata));
if (value != NULL) {
gth_comment_set_note (comment, value);
g_free (value);
write_comment = TRUE;
}
}
}
......@@ -647,8 +651,12 @@ gth_comment_update_from_general_attributes (GthFileData *file_data)
if (metadata != NULL) {
text = g_file_info_get_attribute_string (file_data->info, "comment::caption");
if (! dom_str_equal (gth_metadata_get_formatted (metadata), text)) {
gth_comment_set_caption (comment, gth_metadata_get_formatted (metadata));
write_comment = TRUE;
char *value = _g_utf8_try_from_any (gth_metadata_get_formatted (metadata));
if (value != NULL) {
gth_comment_set_caption (comment, value);
g_free (value);
write_comment = TRUE;
}
}
}
......@@ -656,8 +664,12 @@ gth_comment_update_from_general_attributes (GthFileData *file_data)
if (metadata != NULL) {
text = g_file_info_get_attribute_string (file_data->info, "comment::place");
if (! dom_str_equal (gth_metadata_get_formatted (metadata), text)) {
gth_comment_set_place (comment, gth_metadata_get_formatted (metadata));
write_comment = TRUE;
char *value = _g_utf8_try_from_any (gth_metadata_get_formatted (metadata));
if (value != NULL) {
gth_comment_set_place (comment, value);
g_free (value);
write_comment = TRUE;
}
}
}
......@@ -680,12 +692,17 @@ gth_comment_update_from_general_attributes (GthFileData *file_data)
if (categories != NULL) {
metadata = (GthMetadata *) g_file_info_get_attribute_object (file_data->info, "comment::categories");
comment_categories = gth_metadata_get_string_list (metadata);
if (! gth_string_list_equal (categories, comment_categories)) {
if (! gth_string_list_equal_custom (categories, comment_categories, (GCompareFunc) dom_str_find)) {
GList *scan;
gth_comment_clear_categories (comment);
for (scan = gth_string_list_get_list (categories); scan; scan = scan->next)
gth_comment_add_category (comment, scan->data);
for (scan = gth_string_list_get_list (categories); scan; scan = scan->next) {
char *value = _g_utf8_try_from_any (scan->data);
if (value != NULL) {
gth_comment_add_category (comment, value);
g_free (value);
}
}
write_comment = TRUE;
}
}
......
......@@ -39,7 +39,7 @@
using namespace std;
#define INVALID_VALUE "---"
#define INVALID_VALUE N_("(invalid value)")
/* Some bits of information may be contained in more than one metadata tag.
......@@ -451,6 +451,8 @@ set_attribute_from_metadata (GFileInfo *info,
char *formatted_value;
char *raw_value;
char *type_name;
char *formatted_value_utf8;
char *raw_value_utf8;
if (metadata == NULL)
return;
......@@ -462,14 +464,19 @@ set_attribute_from_metadata (GFileInfo *info,
"value-type", &type_name,
NULL);
formatted_value_utf8 = _g_utf8_try_from_any (formatted_value);
raw_value_utf8 = _g_utf8_try_from_any (raw_value);
set_file_info (info,
attribute,
description,
formatted_value,
raw_value,
formatted_value_utf8,
raw_value_utf8,
NULL,
type_name);
g_free (raw_value_utf8);
g_free (formatted_value_utf8);
g_free (description);
g_free (formatted_value);
g_free (raw_value);
......@@ -528,11 +535,16 @@ set_string_list_attribute_from_tagset (GFileInfo *info,
if (GTH_IS_METADATA (metadata) && (gth_metadata_get_data_type (GTH_METADATA (metadata)) != GTH_METADATA_TYPE_STRING_LIST)) {
char *raw;
char *utf8_raw;
char **keywords;
GthStringList *string_list;
g_object_get (metadata, "raw", &raw, NULL);
keywords = g_strsplit (raw, ",", -1);
utf8_raw = _g_utf8_try_from_any (raw);
if (utf8_raw == NULL)
return;
keywords = g_strsplit (utf8_raw, ",", -1);
string_list = gth_string_list_new_from_strv (keywords);
metadata = (GObject *) gth_metadata_new_for_string_list (string_list);
g_file_info_set_attribute_object (info, attribute, metadata);
......@@ -541,6 +553,7 @@ set_string_list_attribute_from_tagset (GFileInfo *info,
g_object_unref (string_list);
g_strfreev (keywords);
g_free (raw);
g_free (utf8_raw);
}
else
g_file_info_set_attribute_object (info, attribute, metadata);
......
......@@ -71,7 +71,22 @@ _g_xml_attribute_quote (char *value)
g_return_val_if_fail (value != NULL, NULL);
escaped = g_markup_escape_text (value, -1);
if (! g_utf8_validate (value, -1, NULL)) {
char *temp;
temp = g_locale_to_utf8 (value, -1, NULL, NULL, NULL);
if (temp == NULL)
temp = g_utf16_to_utf8 ((gunichar2 *) value, -1, NULL, NULL, NULL);
if (temp != NULL) {
escaped = g_markup_escape_text (temp, -1);
g_free (temp);
}
else
escaped = g_strdup (value);
}
else
escaped = g_markup_escape_text (value, -1);
dest = g_string_new ("\"");
for (p = escaped; (*p); p++) {
......@@ -700,12 +715,20 @@ dom_domizable_load_from_element (DomDomizable *self,
/* GMarkupParser converts \r into \n, this function compares two strings
* treating \r characters as they were equal to \n */
* treating \r characters as they were equal to \n. Furthermore treats invalid
* utf8 strings as null values. */
gboolean
dom_str_equal (const char *a,
const char *b)
{
const char *ai, *bi;
gboolean a_valid, b_valid;
if ((a != NULL) && ! g_utf8_validate (a, -1, NULL))
a = NULL;
if ((b != NULL) && ! g_utf8_validate (b, -1, NULL))
b = NULL;
if ((a == NULL) && (b == NULL))
return TRUE;
......@@ -713,6 +736,9 @@ dom_str_equal (const char *a,
if ((a == NULL) || (b == NULL))
return FALSE;
if (g_utf8_collate (a, b) == 0)
return TRUE;
ai = a;
bi = b;
while ((*ai != '\0') && (*bi != '\0')) {
......@@ -728,12 +754,12 @@ dom_str_equal (const char *a,
/* \r\n equal to \n */
if ((*ai == '\r') && (*(ai + 1) == '\n') && (*bi == '\n') && (*(bi + 1) != '\n'))
ai++;
ai = g_utf8_next_char (ai);
if ((*bi == '\r') && (*(bi + 1) == '\n') && (*ai == '\n') && (*(ai + 1) != '\n'))
ai++;
ai = g_utf8_next_char (ai);
}
ai++;
bi++;
ai = g_utf8_next_char (ai);
bi = g_utf8_next_char (bi);
}
/* 'end of string' equal to \n and to \r\n */
......@@ -744,3 +770,11 @@ dom_str_equal (const char *a,
|| ((*ai == '\0') && (*bi == '\r') && (*(bi + 1) == '\n') && (*(bi + 2) == '\0'))
|| ((*bi == '\0') && (*ai == '\r') && (*(ai + 1) == '\n') && (*(ai + 2) == '\0')));
}
int
dom_str_find (const char *a,
const char *b)
{
return dom_str_equal (a, b) ? 0 : -1;
}
......@@ -187,6 +187,8 @@ void dom_domizable_load_from_element (DomDomizable *self,
gboolean dom_str_equal (const char *a,
const char *b);
int dom_str_find (const char *a,
const char *b);
G_END_DECLS
......
......@@ -1029,6 +1029,42 @@ _g_utf8_remove_extension (const char *str)
}
char *
_g_utf8_try_from_any (const char *str)
{
char *utf8_str;
if (str == NULL)
return NULL;
if (! g_utf8_validate (str, -1, NULL)) {
utf8_str = g_locale_to_utf8 (str, -1, NULL, NULL, NULL);
if (utf8_str == NULL)
utf8_str = g_utf16_to_utf8 ((gunichar2 *) str, -1, NULL, NULL, NULL);
}
else
utf8_str = g_strdup (str);
return utf8_str;
}
char *
_g_utf8_from_any (const char *str)
{
char *utf8_str;
if (str == NULL)
return NULL;
utf8_str = _g_utf8_try_from_any (str);
if (utf8_str == NULL)
utf8_str = g_strdup (_("(invalid value)"));
return utf8_str;
}
static int
remove_from_file_list_and_get_position (GList **file_list,
GFile *file)
......
......@@ -191,6 +191,8 @@ char ** _g_utf8_strsplit (const char *string,
char * _g_utf8_strstrip (const char *str);
gboolean _g_utf8_all_spaces (const char *utf8_string);
char * _g_utf8_remove_extension (const char *str);
char * _g_utf8_try_from_any (const char *str);
char * _g_utf8_from_any (const char *str);
GList * _g_list_insert_list_before (GList *list1,
GList *sibling,
GList *list2);
......
......@@ -526,8 +526,9 @@ char *
gth_file_data_get_attribute_as_string (GthFileData *file_data,
const char *id)
{
char *value = NULL;
GObject *obj;
char *value = NULL;
char *utf8_value;
switch (g_file_info_get_attribute_type (file_data->info, id)) {
case G_FILE_ATTRIBUTE_TYPE_OBJECT:
......
......@@ -171,13 +171,17 @@ gth_file_properties_real_set_file (GthPropertyView *base,
}
if (value != NULL) {
char *utf8_value;
char *tmp_value;
if (g_utf8_strlen (value, -1) > MAX_ATTRIBUTE_LENGTH)
g_utf8_strncpy (g_utf8_offset_to_pointer (value, MAX_ATTRIBUTE_LENGTH - 1), "…", 1);
tmp_value = _g_utf8_replace (value, "[\r\n]", " ");
utf8_value = _g_utf8_from_any (value);
if (g_utf8_strlen (utf8_value, -1) > MAX_ATTRIBUTE_LENGTH)
g_utf8_strncpy (g_utf8_offset_to_pointer (utf8_value, MAX_ATTRIBUTE_LENGTH - 1), "…", 1);
tmp_value = _g_utf8_replace (utf8_value, "[\r\n]", " ");
g_free (value);
value = tmp_value;
g_free (utf8_value);
}
tooltip = g_markup_printf_escaped ("%s: %s", _(info->display_name), value);
......
......@@ -148,6 +148,15 @@ gth_string_list_join (GthStringList *list,
gboolean
gth_string_list_equal (GthStringList *list1,
GthStringList *list2)
{
return gth_string_list_equal_custom (list1, list2, (GCompareFunc) strcmp);
}
gboolean
gth_string_list_equal_custom (GthStringList *list1,
GthStringList *list2,
GCompareFunc compare_func)
{
GList *keys1;
GList *keys2;
......@@ -165,7 +174,7 @@ gth_string_list_equal (GthStringList *list1,
return FALSE;
for (scan = keys1; scan; scan = scan->next)
if (! g_list_find_custom (keys2, scan->data, (GCompareFunc) strcmp))
if (! g_list_find_custom (keys2, scan->data, compare_func))
return FALSE;
return TRUE;
......
......@@ -58,6 +58,9 @@ char * gth_string_list_join (GthStringList *list,
const char *separator);
gboolean gth_string_list_equal (GthStringList *list1,
GthStringList *list2);
gboolean gth_string_list_equal_custom (GthStringList *list1,
GthStringList *list2,
GCompareFunc compare_func);
void gth_string_list_append (GthStringList *list1,
GthStringList *list2);
void gth_string_list_concat (GthStringList *list1,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment