+ g_utf8_validate(retlist[i], -1, &end);
+ retlist[i] = g_strndup(retlist[i], end-retlist[i]);
+ }
+ else if (encoding == LOCALE) {
+ gsize nvalid; /* the number of valid bytes at the front of the
+ string */
+ gchar *utf; /* the string converted into utf8 */
+
+ utf = g_locale_to_utf8(retlist[i], -1, &nvalid, NULL, NULL);
+ if (!utf)
+ utf = g_locale_to_utf8(retlist[i], nvalid, NULL, NULL, NULL);
+ g_assert(utf);
+ retlist[i] = utf;
+ }
+ else { /* encoding == LATIN1 */
+ gsize nvalid; /* the number of valid bytes at the front of the
+ string */
+ gchar *utf; /* the string converted into utf8 */
+ gchar *p; /* iterator */
+
+ /* look for invalid characters */
+ for (p = retlist[i], nvalid = 0; *p; ++p, ++nvalid) {
+ /* The only valid control characters are TAB(HT)=9 and
+ NEWLINE(LF)=10.
+ This is defined in ICCCM section 2:
+ http://tronche.com/gui/x/icccm/sec-2.html.
+ See a definition of the latin1 codepage here:
+ http://en.wikipedia.org/wiki/ISO/IEC_8859-1.
+ The above page includes control characters in the table,
+ which we must explicitly exclude, as the g_convert function
+ will happily take them.
+ */
+ const register guchar c = (guchar)*p; /* unsigned value at p */
+ if ((c < 32 && c != 9 && c != 10) || (c >= 127 && c <= 160))
+ break; /* found a control character that isn't allowed */
+
+ if (type == OBT_PROP_TEXT_STRING_NO_CC && c < 32)
+ break; /* absolutely no control characters are allowed */
+
+ if (type == OBT_PROP_TEXT_STRING_XPCS) {
+ const gboolean valid = (
+ (c >= 32 && c < 128) || c == 9 || c == 10);
+ if (!valid)
+ break; /* strict whitelisting for XPCS */
+ }
+ }
+ /* look for invalid latin1 characters */
+ utf = g_convert(retlist[i], nvalid, "utf-8", "iso-8859-1",
+ &nvalid, NULL, NULL);
+ if (!utf)
+ utf = g_convert(retlist[i], nvalid, "utf-8", "iso-8859-1",
+ NULL, NULL, NULL);
+ g_assert(utf);
+ retlist[i] = utf;