X-Git-Url: http://git.maemo.org/git/?p=modest;a=blobdiff_plain;f=src%2Fmodest-text-utils.c;h=f35a1271a074e6c6afb5965a331e791258a213e3;hp=db6d708f86b87ce0e7c9decad06efdf982af1c18;hb=1310c638b65414fad9be0ed2fcfb93a5cbc23433;hpb=e08627af810496c08eaedba6e64fb056f812cd3e
diff --git a/src/modest-text-utils.c b/src/modest-text-utils.c
index db6d708..f35a127 100644
--- a/src/modest-text-utils.c
+++ b/src/modest-text-utils.c
@@ -100,11 +100,16 @@ static int get_breakpoint (const gchar * s, const gint indent, con
static gchar* modest_text_utils_quote_plain_text (const gchar *text,
const gchar *cite,
+ const gchar *signature,
+ GList *attachments,
int limit);
static gchar* modest_text_utils_quote_html (const gchar *text,
- const gchar *cite,
+ const gchar *cite,
+ const gchar *signature,
+ GList *attachments,
int limit);
+static gchar* get_email_from_address (const gchar *address);
/* ******************************************************************* */
@@ -114,8 +119,10 @@ static gchar* modest_text_utils_quote_html (const gchar *text,
gchar *
modest_text_utils_quote (const gchar *text,
const gchar *content_type,
+ const gchar *signature,
const gchar *from,
const time_t sent_date,
+ GList *attachments,
int limit)
{
gchar *retval, *cited;
@@ -128,9 +135,9 @@ modest_text_utils_quote (const gchar *text,
if (content_type && strcmp (content_type, "text/html") == 0)
/* TODO: extract the
of the HTML and pass it to
the function */
- retval = modest_text_utils_quote_html (text, cited, limit);
+ retval = modest_text_utils_quote_html (text, cited, signature, attachments, limit);
else
- retval = modest_text_utils_quote_plain_text (text, cited, limit);
+ retval = modest_text_utils_quote_plain_text (text, cited, signature, attachments, limit);
g_free (cited);
@@ -141,17 +148,26 @@ modest_text_utils_quote (const gchar *text,
gchar *
modest_text_utils_cite (const gchar *text,
const gchar *content_type,
+ const gchar *signature,
const gchar *from,
time_t sent_date)
{
- gchar *tmp, *retval;
+ gchar *retval;
+ gchar *tmp_sig;
g_return_val_if_fail (text, NULL);
g_return_val_if_fail (content_type, NULL);
- tmp = cite (sent_date, from);
- retval = g_strdup_printf ("%s%s\n", tmp, text);
- g_free (tmp);
+ if (!signature)
+ tmp_sig = g_strdup ("");
+ else if (!strcmp(content_type, "text/html")) {
+ tmp_sig = modest_text_utils_convert_to_html_body(signature);
+ } else {
+ tmp_sig = g_strdup (signature);
+ }
+
+ retval = g_strdup_printf ("\n%s\n", tmp_sig);
+ g_free (tmp_sig);
return retval;
}
@@ -159,15 +175,17 @@ modest_text_utils_cite (const gchar *text,
gchar *
modest_text_utils_inline (const gchar *text,
const gchar *content_type,
+ const gchar *signature,
const gchar *from,
time_t sent_date,
const gchar *to,
const gchar *subject)
{
gchar sent_str[101];
- const gchar *plain_format = "%s\n%s %s\n%s %s\n%s %s\n%s %s\n\n%s";
+ gchar *formatted_signature;
+ const gchar *plain_format = "%s%s\n%s %s\n%s %s\n%s %s\n%s %s\n\n%s";
const gchar *html_format = \
- "%s
\n\n" \
+ "%s%s
\n\n" \
"%s | %s |
\n" \
"%s | %s |
\n" \
"%s | %s |
\n" \
@@ -188,7 +206,17 @@ modest_text_utils_inline (const gchar *text,
else
format = plain_format;
- return g_strdup_printf (format,
+ if (signature != NULL) {
+ if (!strcmp (content_type, "text/html")) {
+ formatted_signature = g_strconcat (signature, "
", NULL);
+ } else {
+ formatted_signature = g_strconcat (signature, "\n", NULL);
+ }
+ } else {
+ formatted_signature = "";
+ }
+
+ return g_strdup_printf (format, formatted_signature,
FORWARD_STRING,
FROM_STRING, (from) ? from : EMPTY_STRING,
SENT_STRING, sent_str,
@@ -203,11 +231,13 @@ modest_text_utils_inline (const gchar *text,
gsize
modest_text_utils_strftime(char *s, gsize max, const char *fmt, time_t timet)
{
- static GDate date;
+ struct tm tm;
- /* FIXME: deprecated in newer glib versions */
- g_date_set_time (&date, (GTime) timet);
- return g_date_strftime (s, max, fmt, (const GDate*) &date);
+ /* does not work on old maemo glib:
+ * g_date_set_time_t (&date, timet);
+ */
+ localtime_r (&timet, &tm);
+ return strftime(s, max, fmt, &tm);
}
gchar *
@@ -235,15 +265,20 @@ modest_text_utils_remove_address (const gchar *address_list, const gchar *addres
{
gchar *dup, *token, *ptr, *result;
GString *filtered_emails;
+ gchar *email_address;
g_return_val_if_fail (address_list, NULL);
if (!address)
return g_strdup (address_list);
+
+ email_address = get_email_from_address (address);
/* search for substring */
- if (!strstr ((const char *) address_list, (const char *) address))
+ if (!strstr ((const char *) address_list, (const char *) email_address)) {
+ g_free (email_address);
return g_strdup (address_list);
+ }
dup = g_strdup (address_list);
filtered_emails = g_string_new (NULL);
@@ -252,7 +287,7 @@ modest_text_utils_remove_address (const gchar *address_list, const gchar *addres
while (token != NULL) {
/* Add to list if not found */
- if (!strstr ((const char *) token, (const char *) address)) {
+ if (!strstr ((const char *) token, (const char *) email_address)) {
if (filtered_emails->len == 0)
g_string_append_printf (filtered_emails, "%s", g_strstrip (token));
else
@@ -263,73 +298,237 @@ modest_text_utils_remove_address (const gchar *address_list, const gchar *addres
result = filtered_emails->str;
/* Clean */
+ g_free (email_address);
g_free (dup);
g_string_free (filtered_emails, FALSE);
return result;
}
+static void
+modest_text_utils_convert_buffer_to_html (GString *html, const gchar *data)
+{
+ guint i;
+ gboolean space_seen = FALSE;
+ gsize len;
+
+ len = strlen (data);
+
+ /* replace with special html chars where needed*/
+ for (i = 0; i != len; ++i) {
+ char kar = data[i];
+
+ if (space_seen && kar != ' ') {
+ g_string_append_c (html, ' ');
+ space_seen = FALSE;
+ }
+
+ switch (kar) {
+ case 0: break; /* ignore embedded \0s */
+ case '<' : g_string_append (html, "<"); break;
+ case '>' : g_string_append (html, ">"); break;
+ case '&' : g_string_append (html, "&"); break;
+ case '"' : g_string_append (html, """); break;
+ case '\'' : g_string_append (html, "'"); break;
+ case '\n' : g_string_append (html, "
\n"); break;
+ case '\t' : g_string_append (html, " "); break; /* note the space at the end*/
+ case ' ':
+ if (space_seen) { /* second space in a row */
+ g_string_append (html, " ");
+ space_seen = FALSE;
+ } else
+ space_seen = TRUE;
+ break;
+ default:
+ g_string_append_c (html, kar);
+ }
+ }
+}
+
gchar*
modest_text_utils_convert_to_html (const gchar *data)
{
- guint i;
- gboolean first_space = TRUE;
GString *html;
gsize len;
-
+
if (!data)
return NULL;
len = strlen (data);
- html = g_string_sized_new (len + 100); /* just a guess... */
-
+ html = g_string_sized_new (1.5 * len); /* just a guess... */
+
g_string_append_printf (html,
- ""
- ""
- ""
+ ""
+ ""
""
- "");
+ "");
+
+ modest_text_utils_convert_buffer_to_html (html, data);
- /* replace with special html chars where needed*/
- for (i = 0; i != len; ++i) {
- char kar = data[i];
- switch (kar) {
-
- case 0: break; /* ignore embedded \0s */
- case '<' : g_string_append (html, "<"); break;
- case '>' : g_string_append (html, ">"); break;
- case '&' : g_string_append (html, """); break;
- case '\n': g_string_append (html, "
\n"); break;
- default:
- if (kar == ' ') {
- g_string_append (html, first_space ? " " : " ");
- first_space = FALSE;
- } else if (kar == '\t')
- g_string_append (html, " ");
- else {
- int charnum = 0;
- first_space = TRUE;
- /* optimization trick: accumulate 'normal' chars, then copy */
- do {
- kar = data [++charnum + i];
-
- } while ((i + charnum < len) &&
- (kar > '>' || (kar != '<' && kar != '>'
- && kar != '&' && kar != ' '
- && kar != '\n' && kar != '\t')));
- g_string_append_len (html, &data[i], charnum);
- i += (charnum - 1);
+ g_string_append (html, "");
+ hyperlinkify_plain_text (html);
+
+ return g_string_free (html, FALSE);
+}
+
+gchar *
+modest_text_utils_convert_to_html_body (const gchar *data)
+{
+ GString *html;
+ gsize len;
+
+ if (!data)
+ return NULL;
+
+ len = strlen (data);
+ html = g_string_sized_new (1.5 * len); /* just a guess... */
+
+ modest_text_utils_convert_buffer_to_html (html, data);
+
+ hyperlinkify_plain_text (html);
+
+ return g_string_free (html, FALSE);
+}
+
+void
+modest_text_utils_get_addresses_indexes (const gchar *addresses, GSList **start_indexes, GSList **end_indexes)
+{
+ gchar *current, *start, *last_blank;
+ gint start_offset = 0, current_offset = 0;
+
+ g_return_if_fail (start_indexes != NULL);
+ g_return_if_fail (end_indexes != NULL);
+
+ start = (gchar *) addresses;
+ current = start;
+ last_blank = start;
+
+ while (*current != '\0') {
+ if ((start == current)&&((*current == ' ')||(*current == ',')||(*current == ';'))) {
+ start = g_utf8_next_char (start);
+ start_offset++;
+ last_blank = current;
+ } else if ((*current == ',')||(*current == ';')) {
+ gint *start_index, *end_index;
+ start_index = g_new0(gint, 1);
+ end_index = g_new0(gint, 1);
+ *start_index = start_offset;
+ *end_index = current_offset;
+ *start_indexes = g_slist_prepend (*start_indexes, start_index);
+ *end_indexes = g_slist_prepend (*end_indexes, end_index);
+ start = g_utf8_next_char (current);
+ start_offset = current_offset + 1;
+ last_blank = start;
+ } else if (*current == '"') {
+ current = g_utf8_next_char (current);
+ current_offset ++;
+ while ((*current != '"')&&(*current != '\0')) {
+ current = g_utf8_next_char (current);
+ current_offset ++;
}
}
+
+ current = g_utf8_next_char (current);
+ current_offset ++;
+ }
+
+ if (start != current) {
+ gint *start_index, *end_index;
+ start_index = g_new0(gint, 1);
+ end_index = g_new0(gint, 1);
+ *start_index = start_offset;
+ *end_index = current_offset;
+ *start_indexes = g_slist_prepend (*start_indexes, start_index);
+ *end_indexes = g_slist_prepend (*end_indexes, end_index);
}
- g_string_append (html, "");
- hyperlinkify_plain_text (html);
+ *start_indexes = g_slist_reverse (*start_indexes);
+ *end_indexes = g_slist_reverse (*end_indexes);
- return g_string_free (html, FALSE);
+ return;
}
+GSList *
+modest_text_utils_split_addresses_list (const gchar *addresses)
+{
+ gchar *current, *start, *last_blank;
+ GSList *result = NULL;
+
+ start = (gchar *) addresses;
+ current = start;
+ last_blank = start;
+
+ while (*current != '\0') {
+ if ((start == current)&&((*current == ' ')||(*current == ',')||(*current == ';'))) {
+ start = g_utf8_next_char (start);
+ last_blank = current;
+ } else if ((*current == ',')||(*current == ';')) {
+ gchar *new_address = NULL;
+ new_address = g_strndup (start, current - last_blank);
+ result = g_slist_prepend (result, new_address);
+ start = g_utf8_next_char (current);
+ last_blank = start;
+ } else if (*current == '\"') {
+ if (current == start) {
+ current = g_utf8_next_char (current);
+ start = g_utf8_next_char (start);
+ }
+ while ((*current != '\"')&&(*current != '\0'))
+ current = g_utf8_next_char (current);
+ }
+
+ current = g_utf8_next_char (current);
+ }
+
+ if (start != current) {
+ gchar *new_address = NULL;
+ new_address = g_strndup (start, current - last_blank);
+ result = g_slist_prepend (result, new_address);
+ }
+
+ result = g_slist_reverse (result);
+ return result;
+
+}
+
+void
+modest_text_utils_address_range_at_position (const gchar *recipients_list,
+ gint position,
+ gint *start,
+ gint *end)
+{
+ gchar *current = NULL;
+ gint range_start = 0;
+ gint range_end = 0;
+ gint index;
+ gboolean is_quoted = FALSE;
+
+ index = 0;
+ for (current = (gchar *) recipients_list; *current != '\0'; current = g_utf8_find_next_char (current, NULL)) {
+ gunichar c = g_utf8_get_char (current);
+
+ if ((c == ',') && (!is_quoted)) {
+ if (index < position) {
+ range_start = index + 1;
+ } else {
+ break;
+ }
+ } else if (c == '\"') {
+ is_quoted = !is_quoted;
+ } else if ((c == ' ') &&(range_start == index)) {
+ range_start ++;
+ }
+ index ++;
+ range_end = index;
+ }
+
+ if (start)
+ *start = range_start;
+ if (end)
+ *end = range_end;
+}
+
+
/* ******************************************************************* */
/* ************************* UTILIY FUNCTIONS ************************ */
/* ******************************************************************* */
@@ -480,28 +679,40 @@ get_breakpoint (const gchar * s, const gint indent, const gint limit)
static gchar *
cite (const time_t sent_date, const gchar *from)
{
- gchar sent_str[101];
-
- /* format sent_date */
- modest_text_utils_strftime (sent_str, 100, "%c", sent_date);
- return g_strdup_printf (N_("On %s, %s wrote:\n"),
- sent_str,
- (from) ? from : EMPTY_STRING);
+ return g_strdup (_("mcen_ia_editor_original_message"));
}
+static gchar *
+quoted_attachments (GList *attachments)
+{
+ GList *node = NULL;
+ GString *result = g_string_new ("");
+ for (node = attachments; node != NULL; node = g_list_next (node)) {
+ gchar *filename = (gchar *) node->data;
+ g_string_append_printf ( result, "%s %s\n", _("mcen_ia_editor_attach_filename"), filename);
+ }
+
+ return g_string_free (result, FALSE);
+
+}
static gchar *
modest_text_utils_quote_plain_text (const gchar *text,
const gchar *cite,
+ const gchar *signature,
+ GList *attachments,
int limit)
{
const gchar *iter;
gint indent, breakpoint, rem_indent = 0;
GString *q, *l, *remaining;
gsize len;
+ gchar *attachments_string = NULL;
/* remaining will store the rest of the line if we have to break it */
- q = g_string_new (cite);
+ q = g_string_new ("\n");
+ q = g_string_append (q, cite);
+ q = g_string_append_c (q, '\n');
remaining = g_string_new ("");
iter = text;
@@ -544,24 +755,53 @@ modest_text_utils_quote_plain_text (const gchar *text,
g_string_free (l, TRUE);
} while ((iter < text + len) || (remaining->str[0]));
+ attachments_string = quoted_attachments (attachments);
+ q = g_string_append (q, attachments_string);
+ g_free (attachments_string);
+
+ if (signature != NULL) {
+ q = g_string_append_c (q, '\n');
+ q = g_string_append (q, signature);
+ }
+
return g_string_free (q, FALSE);
}
static gchar*
modest_text_utils_quote_html (const gchar *text,
const gchar *cite,
+ const gchar *signature,
+ GList *attachments,
int limit)
{
+ gchar *result = NULL;
+ gchar *signature_result = NULL;
const gchar *format = \
"\n" \
"\n" \
"\n" \
- "%s" \
- "\n%s\n
\n" \
+ "
%s
" \
+ "%s
%s
%s
\n" \
"\n" \
"\n";
+ gchar *attachments_string = NULL;
+ gchar *q_attachments_string = NULL;
+ gchar *html_text = NULL;
- return g_strdup_printf (format, cite, text);
+ if (signature == NULL)
+ signature_result = g_strdup ("");
+ else
+ signature_result = modest_text_utils_convert_to_html_body (signature);
+
+ attachments_string = quoted_attachments (attachments);
+ q_attachments_string = modest_text_utils_convert_to_html_body (attachments_string);
+ html_text = modest_text_utils_convert_to_html_body (text);
+ result = g_strdup_printf (format, signature_result, cite, html_text, q_attachments_string);
+ g_free (html_text);
+ g_free (attachments_string);
+ g_free (q_attachments_string);
+ g_free (signature_result);
+ return result;
}
static gint
@@ -686,9 +926,9 @@ modest_text_utils_get_display_address (gchar *address)
if (!address)
return NULL;
-
+
g_return_val_if_fail (g_utf8_validate (address, -1, NULL), NULL);
-
+
g_strchug (address); /* remove leading whitespace */
/* from display name */
@@ -774,12 +1014,13 @@ modest_text_utils_get_display_date (time_t date)
now = time (NULL);
- modest_text_utils_strftime (date_buf, BUF_SIZE, "%x", date);
- modest_text_utils_strftime (now_buf, BUF_SIZE, "%x", now); /* today */
+ /* use the localized dates */
+ modest_text_utils_strftime (date_buf, BUF_SIZE, "%x", date);
+ modest_text_utils_strftime (now_buf, BUF_SIZE, "%x", now);
/* if this is today, get the time instead of the date */
if (strcmp (date_buf, now_buf) == 0)
- modest_text_utils_strftime (date_buf, BUF_SIZE, _("%X"), date);
+ modest_text_utils_strftime (date_buf, BUF_SIZE, "%X", date);
return g_strdup(date_buf);
}
@@ -788,7 +1029,7 @@ gboolean
modest_text_utils_validate_email_address (const gchar *email_address)
{
int count = 0;
- const gchar *c, *domain;
+ const gchar *c = NULL, *domain = NULL;
static gchar *rfc822_specials = "()<>@,;:\\\"[]";
/* first we validate the name portion (name@domain) */
@@ -841,25 +1082,113 @@ modest_text_utils_validate_email_address (const gchar *email_address)
return (count >= 1) ? TRUE : FALSE;
}
+gboolean
+modest_text_utils_validate_recipient (const gchar *recipient)
+{
+ gchar *stripped, *current;
+ gchar *right_part;
+ gboolean has_error = FALSE;
+
+ if (modest_text_utils_validate_email_address (recipient))
+ return TRUE;
+ stripped = g_strdup (recipient);
+ stripped = g_strstrip (stripped);
+ current = stripped;
+
+ if (*current == '\0') {
+ g_free (stripped);
+ return FALSE;
+ }
+ /* quoted string */
+ if (*current == '\"') {
+ current = g_utf8_next_char (current);
+ has_error = TRUE;
+ for (; *current != '\0'; current = g_utf8_next_char (current)) {
+ if (*current == '\\') {
+ /* TODO: This causes a warning, which breaks the build,
+ * because a gchar cannot be < 0.
+ * murrayc.
+ if (current[1] <0) {
+ has_error = TRUE;
+ break;
+ }
+ */
+ } else if (*current == '\"') {
+ has_error = FALSE;
+ current = g_utf8_next_char (current);
+ break;
+ }
+ }
+ } else {
+ has_error = TRUE;
+ for (current = stripped ; *current != '\0'; current = g_utf8_next_char (current)) {
+ if (*current == '<') {
+ has_error = FALSE;
+ break;
+ }
+ }
+ }
+
+ if (has_error) {
+ g_free (stripped);
+ return FALSE;
+ }
+
+ right_part = g_strdup (current);
+ g_free (stripped);
+ right_part = g_strstrip (right_part);
+
+ if (g_str_has_prefix (right_part, "<") &&
+ g_str_has_suffix (right_part, ">")) {
+ gchar *address;
+ gboolean valid;
+
+ address = g_strndup (right_part+1, strlen (right_part) - 2);
+ g_free (right_part);
+ valid = modest_text_utils_validate_email_address (address);
+ g_free (address);
+ return valid;
+ } else {
+ g_free (right_part);
+ return FALSE;
+ }
+}
gchar *
-modest_text_utils_get_display_size (guint size)
+modest_text_utils_get_display_size (guint64 size)
{
const guint KB=1024;
const guint MB=1024 * KB;
const guint GB=1024 * MB;
- const guint TB=1024 * GB;
-
- if (size < KB)
- return g_strdup_printf (_("%0.1f Kb"), (double)size / KB);
- else if (size < MB)
- return g_strdup_printf (_("%d Kb"), size / KB);
- else if (size < GB)
- return g_strdup_printf (_("%d Mb"), size / MB);
- else if (size < TB)
- return g_strdup_printf (_("%d Gb"), size/ GB);
+
+ if (size == 0)
+ return g_strdup_printf(_FM("sfil_li_size_kb"), 0);
+ if (0 < size && size < KB)
+ return g_strdup_printf (_FM("sfil_li_size_kb"), 1);
+ else if (KB <= size && size < 100 * KB)
+ return g_strdup_printf (_FM("sfil_li_size_1kb_99kb"), size / KB);
+ else if (100*KB <= size && size < MB)
+ return g_strdup_printf (_FM("sfil_li_size_100kb_1mb"), (float) size / MB);
+ else if (MB <= size && size < 10*MB)
+ return g_strdup_printf (_FM("sfil_li_size_1mb_10mb"), (float) size / MB);
+ else if (10*MB <= size && size < GB)
+ return g_strdup_printf (_FM("sfil_li_size_10mb_1gb"), size / MB);
+ else
+ return g_strdup_printf (_FM("sfil_li_size_1gb_or_greater"), (float) size / GB);
+}
+
+static gchar *
+get_email_from_address (const gchar * address)
+{
+ gchar *left_limit, *right_limit;
+
+ left_limit = strstr (address, "<");
+ right_limit = g_strrstr (address, ">");
+
+ if ((left_limit == NULL)||(right_limit == NULL)|| (left_limit > right_limit))
+ return g_strdup (address);
else
- return g_strdup_printf (_("Very big"));
+ return g_strndup (left_limit + 1, (right_limit - left_limit) - 1);
}