static void escape_string (GString *string) { const char *p = string->str; gunichar wc; while (p < string->str + string->len) { gboolean safe; wc = g_utf8_get_char_validated (p, -1); if (wc == (gunichar)-1 || wc == (gunichar)-2) { gchar *tmp; guint pos; pos = p - string->str; /* Emit invalid UTF-8 as hex escapes */ tmp = g_strdup_printf ("\\x%02x", (guint)(guchar)*p); g_string_erase (string, pos, 1); g_string_insert (string, pos, tmp); p = string->str + (pos + 4); /* Skip over escape sequence */ g_free (tmp); continue; } if (wc == '\r') { safe = *(p + 1) == '\n'; } else { safe = CHAR_IS_SAFE (wc); } if (!safe) { gchar *tmp; guint pos; pos = p - string->str; /* Largest char we escape is 0x0a, so we don't have to worry * about 8-digit \Uxxxxyyyy */ tmp = g_strdup_printf ("\\u%04x", wc); g_string_erase (string, pos, g_utf8_next_char (p) - p); g_string_insert (string, pos, tmp); g_free (tmp); p = string->str + (pos + 6); /* Skip over escape sequence */ } else p = g_utf8_next_char (p); } }
static gchar* strdup_convert (const gchar *string, const gchar *charset) { if (!g_utf8_validate (string, -1, NULL)) { GString *gstring = g_string_new ("[Invalid UTF-8] "); guchar *p; for (p = (guchar *)string; *p; p++) { if (CHAR_IS_SAFE(*p) && !(*p == '\r' && *(p + 1) != '\n') && *p < 0x80) g_string_append_c (gstring, *p); else g_string_append_printf (gstring, "\\x%02x", (guint)(guchar)*p); } return g_string_free (gstring, FALSE); } else { GError *err = NULL; gchar *result = g_convert_with_fallback (string, -1, charset, "UTF-8", "?", NULL, NULL, &err); if (result) return result; else { #ifdef USE_LIBICONV_GNU /* No libiconv in Android, so we only duplicate message if no * USE_LIBICONV_GNU */ /* Not thread-safe, but doesn't matter if we print the warning twice */ static gboolean warned = FALSE; if (!warned) { warned = TRUE; _g_fprintf (stderr, "GLib: Cannot convert message: %s\n", err->message); } g_error_free (err); #endif return g_strdup (string); } } }