+
+gchar *
+modest_text_utils_simplify_recipients (const gchar *recipients)
+{
+ GSList *addresses, *node;
+ GString *result;
+ gboolean is_first = TRUE;
+
+ if (recipients == NULL)
+ return g_strdup ("");
+
+ addresses = modest_text_utils_split_addresses_list (recipients);
+ result = g_string_new ("");
+
+ for (node = addresses; node != NULL; node = g_slist_next (node)) {
+ const gchar *address = (const gchar *) node->data;
+ gchar *left_limit, *right_limit;
+
+ left_limit = strstr (address, "<");
+ right_limit = g_strrstr (address, ">");
+
+ if (is_first)
+ is_first = FALSE;
+ else
+ result = g_string_append (result, ", ");
+
+ if ((left_limit == NULL)||(right_limit == NULL)|| (left_limit > right_limit)) {
+ result = g_string_append (result, address);
+ } else {
+ gchar *name_side;
+ gchar *email_side;
+ name_side = g_strndup (address, left_limit - address);
+ name_side = g_strstrip (name_side);
+ remove_quotes (&name_side);
+ email_side = get_email_from_address (address);
+ if (name_side && email_side && !strcmp (name_side, email_side)) {
+ result = g_string_append (result, email_side);
+ } else {
+ result = g_string_append (result, address);
+ }
+ g_free (name_side);
+ g_free (email_side);
+ }
+
+ }
+ g_slist_foreach (addresses, (GFunc)g_free, NULL);
+ g_slist_free (addresses);
+
+ return g_string_free (result, FALSE);
+
+}
+
+GSList *
+modest_text_utils_remove_duplicate_addresses_list (GSList *address_list)
+{
+ GSList *new_list, *iter;
+ GHashTable *table;
+
+ g_return_val_if_fail (address_list, NULL);
+
+ table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+
+ new_list = address_list;
+ iter = address_list;
+ while (iter) {
+ const gchar* address = (const gchar*)iter->data;
+
+ /* We need only the email to just compare it and not
+ the full address which would make "a <a@a.com>"
+ different from "a@a.com" */
+ const gchar *email = get_email_from_address (address);
+
+ /* ignore the address if already seen */
+ if (g_hash_table_lookup (table, email) == 0) {
+ g_hash_table_insert (table, (gchar*)email, GINT_TO_POINTER(1));
+ iter = g_slist_next (iter);
+ } else {
+ GSList *tmp = g_slist_next (iter);
+ new_list = g_slist_delete_link (new_list, iter);
+ iter = tmp;
+ }
+ }
+
+ g_hash_table_unref (table);
+
+ return new_list;
+}
+
+gchar *
+modest_text_utils_get_secure_header (const gchar *value,
+ const gchar *header)
+{
+ const gint max_len = 16384;
+ gchar *new_value = NULL;
+ gchar *needle = g_strrstr (value, header);
+
+ if (needle && value != needle)
+ new_value = g_strdup (needle + strlen (header));
+
+ if (!new_value)
+ new_value = g_strdup (value);
+
+ /* Do a max length check to prevent DoS attacks caused by huge
+ malformed headers */
+ if (g_utf8_validate (new_value, -1, NULL)) {
+ if (g_utf8_strlen (new_value, -1) > max_len) {
+ gchar *tmp = g_malloc0 (max_len * 4);
+ g_utf8_strncpy (tmp, (const gchar *) new_value, max_len);
+ g_free (new_value);
+ new_value = tmp;
+ }
+ } else {
+ if (strlen (new_value) > max_len) {
+ gchar *tmp = g_malloc0 (max_len);
+ strncpy (new_value, tmp, max_len);
+ g_free (new_value);
+ new_value = tmp;
+ }
+ }
+
+ return new_value;
+}
+
+static gboolean
+is_quoted (const char *start, const gchar *end)
+{
+ gchar *c;
+
+ c = (gchar *) start;
+ while (*c == ' ')
+ c = g_utf8_next_char (c);
+
+ if (*c == '\0' || *c != '\"')
+ return FALSE;
+
+ c = (gchar *) end;
+ while (*c == ' ' && c != start)
+ c = g_utf8_prev_char (c);
+
+ if (c == start || *c != '\"')
+ return FALSE;
+
+ return TRUE;
+}
+
+
+static void
+quote_name_part (GString **str, gchar **cur, gchar **start)
+{
+ gchar *blank;
+ gint str_len = *cur - *start;
+
+ while (**start == ' ') {
+ *start = g_utf8_next_char (*start);
+ str_len--;
+ }
+
+ blank = g_utf8_strrchr (*start, str_len, g_utf8_get_char (" "));
+ if (blank && (blank != *start)) {
+ if (is_quoted (*start, blank - 1)) {
+ *str = g_string_append_len (*str, *start, str_len);
+ *str = g_string_append (*str, ";");
+ *start = g_utf8_next_char (*cur);
+ } else {
+ *str = g_string_append_c (*str, '"');
+ *str = g_string_append_len (*str, *start, (blank - *start));
+ *str = g_string_append_c (*str, '"');
+ *str = g_string_append_len (*str, blank, (*cur - blank));
+ *str = g_string_append (*str, ";");
+ *start = g_utf8_next_char (*cur);
+ }
+ } else {
+ *str = g_string_append_len (*str, *start, str_len);
+ *str = g_string_append (*str, ";");
+ *start = g_utf8_next_char (*cur);
+ }
+}
+
+gchar *
+modest_text_utils_quote_names (const gchar *recipients)
+{
+ GString *str;
+ gchar *start, *cur;
+
+ str = g_string_new ("");
+ start = (gchar*) recipients;
+ cur = (gchar*) recipients;
+
+ for (cur = start; *cur != '\0'; cur = g_utf8_next_char (cur)) {
+ if (*cur == ',' || *cur == ';') {
+ if (!g_utf8_strchr (start, (cur - start + 1), g_utf8_get_char ("@")))
+ continue;
+ quote_name_part (&str, &cur, &start);
+ }
+ }
+
+ quote_name_part (&str, &cur, &start);
+
+ return g_string_free (str, FALSE);
+}
+
+/* Returns TRUE if there is no recipients in the text buffer. Note
+ that strings like " ; , " contain only separators and thus no
+ recipients */
+gboolean
+modest_text_utils_no_recipient (GtkTextBuffer *buffer)
+{
+ gboolean retval = TRUE;
+ gchar *text, *tmp;
+ GtkTextIter start, end;
+
+ if (gtk_text_buffer_get_char_count (buffer) == 0)
+ return TRUE;
+
+ gtk_text_buffer_get_start_iter (buffer, &start);
+ gtk_text_buffer_get_end_iter (buffer, &end);
+
+ text = g_strstrip (gtk_text_buffer_get_text (buffer, &start, &end, FALSE));
+ if (!g_strcmp0 (text, ""))
+ return TRUE;
+
+ tmp = text;
+ while (tmp && *tmp != '\0') {
+ if ((*tmp != ',') && (*tmp != ';') &&
+ (*tmp != '\r') && (*tmp != '\n') &&
+ (*tmp != ' ')) {
+ retval = FALSE;
+ break;
+ } else {
+ tmp++;
+ }
+ }
+ g_free (text);
+
+ return retval;
+}
+
+gchar *
+modest_text_utils_create_colored_signature (const gchar *signature)
+{
+ gchar *gray_color_markup = NULL, *retval;
+ GdkColor color;
+ GtkWidget *widget;
+
+ /* Get color from widgets */
+ widget = (GtkWidget *) modest_window_mgr_get_current_top (modest_runtime_get_window_mgr ());
+ if (widget && gtk_style_lookup_color (gtk_widget_get_style (widget), "SecondaryTextColor", &color))
+ gray_color_markup = modest_text_utils_get_color_string (&color);
+
+ retval = g_strdup_printf ("<br/>\n<font color=\"%s\">%s<br/>\n%s<br/>\n</font>",
+ (gray_color_markup) ? gray_color_markup : "#babababababa",
+ MODEST_TEXT_UTILS_SIGNATURE_MARKER,
+ signature);
+
+ if (gray_color_markup)
+ g_free (gray_color_markup);
+
+ return retval;
+}
+
+gboolean
+modest_text_utils_live_search_find (const gchar *haystack, const gchar *needles)
+{
+ gchar *haystack_fold;
+ gchar *needles_fold;
+ gchar **needle, **current;
+ gboolean match;
+
+ match = FALSE;
+
+ haystack_fold = g_utf8_casefold (haystack, -1);
+ needles_fold = g_utf8_casefold (needles, -1);
+
+ needle = g_strsplit (needles_fold, " ", -1);
+
+ current = needle;
+ while (current && *current != NULL) {
+
+ if (g_strstr_len (haystack_fold, -1, *current) != NULL) {
+ match = TRUE;
+ } else {
+ match = FALSE;
+ break;
+ }
+ current++;
+ }
+
+ g_strfreev (needle);
+ g_free (needles_fold);
+ g_free (haystack_fold);
+
+ return match;
+}