| 2977 purple_normalize(const PurpleAccount *account, const char *str) |
2977 purple_normalize(const PurpleAccount *account, const char *str) |
| 2978 { |
2978 { |
| 2979 const char *ret = NULL; |
2979 const char *ret = NULL; |
| 2980 static char buf[BUF_LEN]; |
2980 static char buf[BUF_LEN]; |
| 2981 |
2981 |
| |
2982 /* This should prevent a crash if purple_normalize gets called with NULL str, see #10115 */ |
| |
2983 g_return_val_if_fail(str != NULL, ""); |
| |
2984 |
| 2982 if (account != NULL) |
2985 if (account != NULL) |
| 2983 { |
2986 { |
| 2984 PurplePlugin *prpl = purple_find_prpl(purple_account_get_protocol_id(account)); |
2987 PurplePlugin *prpl = purple_find_prpl(purple_account_get_protocol_id(account)); |
| 2985 |
2988 |
| 2986 if (prpl != NULL) |
2989 if (prpl != NULL) |
| 4206 iter = str; |
4209 iter = str; |
| 4207 for (; *iter && j < (BUF_LEN - 1) ; iter = g_utf8_next_char(iter)) { |
4210 for (; *iter && j < (BUF_LEN - 1) ; iter = g_utf8_next_char(iter)) { |
| 4208 gunichar c = g_utf8_get_char(iter); |
4211 gunichar c = g_utf8_get_char(iter); |
| 4209 /* If the character is an ASCII character and is alphanumeric |
4212 /* If the character is an ASCII character and is alphanumeric |
| 4210 * no need to escape */ |
4213 * no need to escape */ |
| 4211 if (c < 128 && isalnum(c)) { |
4214 if (c < 128 && (isalnum(c) || c == '-' || c == '.' || c == '_' || c == '~')) { |
| 4212 buf[j++] = c; |
4215 buf[j++] = c; |
| 4213 } else { |
4216 } else { |
| 4214 int bytes = g_unichar_to_utf8(c, utf_char); |
4217 int bytes = g_unichar_to_utf8(c, utf_char); |
| 4215 for (i = 0; i < bytes; i++) { |
4218 for (i = 0; i < bytes; i++) { |
| 4216 if (j > (BUF_LEN - 4)) |
4219 if (j > (BUF_LEN - 4)) |
| 4217 break; |
4220 break; |
| 4218 sprintf(buf + j, "%%%02x", utf_char[i] & 0xff); |
4221 sprintf(buf + j, "%%%02X", utf_char[i] & 0xff); |
| 4219 j += 3; |
4222 j += 3; |
| 4220 } |
4223 } |
| 4221 } |
4224 } |
| 4222 } |
4225 } |
| 4223 |
4226 |
| 4483 |
4486 |
| 4484 gchar * |
4487 gchar * |
| 4485 purple_utf8_strip_unprintables(const gchar *str) |
4488 purple_utf8_strip_unprintables(const gchar *str) |
| 4486 { |
4489 { |
| 4487 gchar *workstr, *iter; |
4490 gchar *workstr, *iter; |
| |
4491 const gchar *bad; |
| 4488 |
4492 |
| 4489 if (str == NULL) |
4493 if (str == NULL) |
| 4490 /* Act like g_strdup */ |
4494 /* Act like g_strdup */ |
| 4491 return NULL; |
4495 return NULL; |
| 4492 |
4496 |
| 4493 g_return_val_if_fail(g_utf8_validate(str, -1, NULL), NULL); |
4497 if (!g_utf8_validate(str, -1, &bad)) { |
| |
4498 purple_debug_error("util", "purple_utf8_strip_unprintables(%s) failed; " |
| |
4499 "first bad character was %02x (%c)\n", |
| |
4500 str, *bad, *bad); |
| |
4501 g_return_val_if_reached(NULL); |
| |
4502 } |
| 4494 |
4503 |
| 4495 workstr = iter = g_new(gchar, strlen(str) + 1); |
4504 workstr = iter = g_new(gchar, strlen(str) + 1); |
| 4496 while (*str) { |
4505 for ( ; *str; ++str) { |
| 4497 gunichar c = g_utf8_get_char(str); |
4506 guchar c = *str; |
| 4498 const gchar *next = g_utf8_next_char(str); |
4507 if (c >= 0x20 || c == '\t' || c == '\n' || c == '\r') { |
| 4499 size_t len = next - str; |
4508 *iter = c; |
| 4500 |
4509 ++iter; |
| 4501 if (g_unichar_isprint(c)) { |
4510 } |
| 4502 memcpy(iter, str, len); |
|
| 4503 iter += len; |
|
| 4504 } |
|
| 4505 |
|
| 4506 str = next; |
|
| 4507 } |
4511 } |
| 4508 |
4512 |
| 4509 /* nul-terminate the new string */ |
4513 /* nul-terminate the new string */ |
| 4510 *iter = '\0'; |
4514 *iter = '\0'; |
| 4511 |
4515 |