* remove some annoying debug warnings
[modest] / src / modest-text-utils.c
index 3b497bb..e42cfee 100644 (file)
  */
 
 
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif /*_GNU_SOURCE*/
+#include <string.h> /* for strcasestr */
+
+
 #include <glib.h>
-#include <string.h>
 #include <stdlib.h>
 #include <glib/gi18n.h>
 #include <regex.h>
 #endif /*HAVE_CONFIG_H */
 
 /* defines */
-#define FORWARD_STRING _("-----Forwarded Message-----")
-#define FROM_STRING _("From:")
-#define SENT_STRING _("Sent:")
-#define TO_STRING _("To:")
-#define        SUBJECT_STRING _("Subject:")
+#define FORWARD_STRING _("mcen_ia_editor_original_message")
+#define FROM_STRING _("mail_va_from")
+#define SENT_STRING _("mcen_fi_message_properties_sent")
+#define TO_STRING _("mail_va_to")
+#define        SUBJECT_STRING _("mail_va_subject")
 #define EMPTY_STRING ""
 
 /*
@@ -79,7 +85,7 @@ struct _url_match_t {
        { "(file|rtsp|http|ftp|https)://[-A-Za-z0-9_$.+!*(),;:@%&=?/~#]+[-A-Za-z0-9_$%&=?/~#]",\
          NULL, NULL },\
        { "www\\.[-a-z0-9.]+[-a-z0-9](:[0-9]*)?(/[-A-Za-z0-9_$.+!*(),;:@%&=?/~#]*[^]}\\),?!;:\"]?)?",\
-         NULL, "http://" },\
+                       NULL, "http://" },                              \
        { "ftp\\.[-a-z0-9.]+[-a-z0-9](:[0-9]*)?(/[-A-Za-z0-9_$.+!*(),;:@%&=?/~#]*[^]}\\),?!;:\"]?)?",\
          NULL, "ftp://" },\
        { "(voipto|callto|chatto|jabberto|xmpp):[-_a-z@0-9.\\+]+", \
@@ -90,6 +96,19 @@ struct _url_match_t {
          NULL, "mailto:"}\
        }
 
+const gchar account_title_forbidden_chars[] = {
+       '\\', '/', ':', '*', '?', '\'', '<', '>', '|', '^'
+};
+const gchar folder_name_forbidden_chars[] = {
+       '<', '>', ':', '\'', '/', '\\', '|', '?', '*', '^', '%', '$'
+};
+const gchar user_name_forbidden_chars[] = {
+       '<', '>'
+};
+const guint ACCOUNT_TITLE_FORBIDDEN_CHARS_LENGTH = G_N_ELEMENTS (account_title_forbidden_chars);
+const guint FOLDER_NAME_FORBIDDEN_CHARS_LENGTH = G_N_ELEMENTS (folder_name_forbidden_chars);
+const guint USER_NAME_FORBIDDEN_CHARS_LENGTH = G_N_ELEMENTS (user_name_forbidden_chars);
+
 /* private */
 static gchar*   cite                    (const time_t sent_date, const gchar *from);
 static void     hyperlinkify_plain_text (GString *txt);
@@ -242,9 +261,9 @@ modest_text_utils_derived_subject (const gchar *subject, const gchar *prefix)
        gchar *tmp;
 
        g_return_val_if_fail (prefix, NULL);
-       
-       if (!subject)
-               return g_strdup (prefix);
+
+       if (!subject || subject[0] == '\0')
+               subject = _("mail_va_no_subject");
 
        tmp = g_strchug (g_strdup (subject));
 
@@ -875,7 +894,6 @@ get_url_matches (GString *txt)
                                match->offset = offset + rm.rm_so;
                                match->len    = rm.rm_eo - rm.rm_so;
                                match->prefix = patterns[i].prefix;
-                               g_warning ("<%d, %d, %s>",  match->offset, match->len, match->prefix);
                                match_list = g_slist_prepend (match_list, match);
                        }
                                
@@ -964,7 +982,26 @@ modest_text_utils_get_display_address (gchar *address)
        return address;
 }
 
+gchar *
+modest_text_utils_get_email_address (const gchar *full_address)
+{
+       const gchar *left, *right;
+       
+       if (!full_address)
+               return NULL;
+       
+       g_return_val_if_fail (g_utf8_validate (full_address, -1, NULL), NULL);
+       
+       left = g_strrstr_len (full_address, strlen(full_address), "<");
+       if (left == NULL)
+               return g_strdup (full_address);
+
+       right = g_strstr_len (left, strlen(left), ">");
+       if (right == NULL)
+               return g_strdup (full_address);
 
+       return g_strndup (left + 1, right - left - 1);
+}
 
 gint 
 modest_text_utils_get_subject_prefix_len (const gchar *sub)
@@ -1050,6 +1087,77 @@ modest_text_utils_get_display_date (time_t date)
        return g_strdup(date_buf);
 }
 
+
+gboolean
+modest_text_utils_validate_folder_name (const gchar *folder_name)
+{
+       /* based on http://msdn2.microsoft.com/en-us/library/aa365247.aspx,
+        * with some extras */
+       
+       guint len;
+       gint i;
+       const gchar **cursor = NULL;
+       const gchar *forbidden_names[] = { /* windows does not like these */
+               "CON", "PRN", "AUX", "NUL", "COM1", "COM2", "COM3", "COM4", "COM5", "COM6",
+               "COM7", "COM8", "COM9", "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9",
+               ".", "..", NULL
+       };
+       
+       /* cannot be NULL */
+       if (!folder_name) 
+               return FALSE;
+
+       /* cannot be empty */
+       len = strlen(folder_name);
+       if (len == 0)
+               return FALSE;
+       
+       /* cannot start or end with a space */
+       if (g_ascii_isspace(folder_name[0]) || g_ascii_isspace(folder_name[len - 1]))
+               return FALSE; 
+
+       /* cannot contain a forbidden char */   
+       for (i = 0; i < len; i++)
+               if (modest_text_utils_is_forbidden_char (folder_name[i], FOLDER_NAME_FORBIDDEN_CHARS))
+                       return FALSE;
+       
+       /* cannot contain a forbidden word */
+       if (len <= 4) {
+               for (cursor = forbidden_names; cursor && *cursor; ++cursor) {
+                       if (g_ascii_strcasecmp (folder_name, *cursor) == 0)
+                               return FALSE;
+               }
+       }
+       return TRUE; /* it's valid! */
+}
+
+
+
+gboolean
+modest_text_utils_validate_domain_name (const gchar *domain)
+{
+       gboolean valid = FALSE;
+       regex_t rx;
+       const gchar* domain_regex = "^[a-z0-9]([.]?[a-z0-9-])*[a-z0-9]$";
+
+       if (!domain)
+               return FALSE;
+       
+       /* domain name: all alphanum or '-' or '.',
+        * but beginning/ending in alphanum */  
+       if (regcomp (&rx, domain_regex, REG_ICASE|REG_EXTENDED|REG_NOSUB)) {
+               g_warning ("BUG: error in regexp");
+               return FALSE;
+       }
+       
+       valid = (regexec (&rx, domain, 1, NULL, 0) == 0);
+       regfree (&rx);
+               
+       return valid;
+}
+
+
+
 gboolean
 modest_text_utils_validate_email_address (const gchar *email_address, const gchar **invalid_char_position)
 {
@@ -1059,7 +1167,14 @@ modest_text_utils_validate_email_address (const gchar *email_address, const gcha
 
        if (invalid_char_position != NULL)
                *invalid_char_position = NULL;
-
+       
+       /* check that the email adress contains exactly one @ */
+       if (!strstr(email_address, "@") || 
+                       (strstr(email_address, "@") != g_strrstr(email_address, "@")))
+       {
+               return FALSE;
+       }
+       
        /* first we validate the name portion (name@domain) */
        for (c = email_address;  *c;  c++) {
                if (*c == '\"' && 
@@ -1100,7 +1215,7 @@ modest_text_utils_validate_email_address (const gchar *email_address, const gcha
                return FALSE;
        do {
                if (*c == '.') {
-                       if (c == domain || *(c - 1) == '.') 
+                       if (c == domain || *(c - 1) == '.' || *(c + 1) == '\0') 
                                return FALSE;
                        count++;
                }
@@ -1239,3 +1354,71 @@ modest_text_utils_get_color_string (GdkColor *color)
                                (color->blue >> 12)  & 0xf, (color->blue >> 8)  & 0xf,
                                (color->blue >>  4)  & 0xf, (color->blue)       & 0xf);
 }
+
+gchar *
+modest_text_utils_text_buffer_get_text (GtkTextBuffer *buffer)
+{
+       GtkTextIter start, end;
+       gchar *slice, *current;
+       GString *result = g_string_new ("");
+
+       g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
+
+       gtk_text_buffer_get_start_iter (buffer, &start);
+       gtk_text_buffer_get_end_iter (buffer, &end);
+
+       slice = gtk_text_buffer_get_slice (buffer, &start, &end, FALSE);
+       current = slice;
+
+       while (current && current != '\0') {
+               if (g_utf8_get_char (current) == 0xFFFC) {
+                       result = g_string_append_c (result, ' ');
+                       current = g_utf8_next_char (current);
+               } else {
+                       gchar *next = g_utf8_strchr (current, -1, 0xFFFC);
+                       if (next == NULL) {
+                               result = g_string_append (result, current);
+                       } else {
+                               result = g_string_append_len (result, current, next - current);
+                       }
+                       current = next;
+               }
+       }
+       g_free (slice);
+
+       return g_string_free (result, FALSE);
+       
+}
+
+gboolean
+modest_text_utils_is_forbidden_char (const gchar character,
+                                    ModestTextUtilsForbiddenCharType type)
+{
+       gint i, len;
+       const gchar *forbidden_chars = NULL;
+       
+       /* We need to get the length in the switch because the
+          compiler needs to know the size at compile time */
+       switch (type) {
+       case ACCOUNT_TITLE_FORBIDDEN_CHARS:
+               forbidden_chars = account_title_forbidden_chars;
+               len = G_N_ELEMENTS (account_title_forbidden_chars);
+               break;
+       case FOLDER_NAME_FORBIDDEN_CHARS:
+               forbidden_chars = folder_name_forbidden_chars;
+               len = G_N_ELEMENTS (folder_name_forbidden_chars);
+               break;
+       case USER_NAME_FORBIDDEN_NAMES:
+               forbidden_chars = user_name_forbidden_chars;
+               len = G_N_ELEMENTS (user_name_forbidden_chars);
+               break;
+       default:
+               g_return_val_if_reached (TRUE);
+       }
+
+       for (i = 0; i < len ; i++)
+               if (forbidden_chars[i] == character)
+                       return TRUE;
+
+       return FALSE; /* it's valid! */
+}