inital gtk2 patch
[claws.git] / src / common / utils.c
index e67da63b99cb577c03386b8d8a2d2449c5d58f3b..adb1ed8db8415c667b84528ec29c2368f888ba1a 100644 (file)
@@ -46,6 +46,7 @@
 #include "intl.h"
 #include "utils.h"
 #include "socket.h"
+#include "../codeconv.h"
 
 #define BUFFSIZE       8192
 
@@ -576,13 +577,12 @@ gint subject_compare_for_sort(const gchar *s1, const gchar *s2)
 void trim_subject_for_compare(gchar *str)
 {
        gchar *srcp;
-       int skip;
 
        eliminate_parenthesis(str, '[', ']');
        eliminate_parenthesis(str, '(', ')');
        g_strstrip(str);
 
-       srcp = str + subject_get_reply_prefix_length(str);
+       srcp = str + subject_get_prefix_length(str);
        if (srcp != str)
                memmove(str, srcp, strlen(srcp) + 1);
 }
@@ -593,7 +593,7 @@ void trim_subject_for_sort(gchar *str)
 
        g_strstrip(str);
 
-       srcp = str + subject_get_reply_prefix_length(str);
+       srcp = str + subject_get_prefix_length(str);
        if (srcp != str)        
                memmove(str, srcp, strlen(srcp) + 1);
 }
@@ -604,7 +604,7 @@ void trim_subject(gchar *str)
        gchar op, cl;
        gint in_brace;
 
-       destp = str + subject_get_reply_prefix_length(str);
+       destp = str + subject_get_prefix_length(str);
 
        if (*destp == '[') {
                op = '[';
@@ -1394,7 +1394,7 @@ GList *uri_list_extract_filenames(const gchar *uri_list)
 {
        GList *result = NULL;
        const gchar *p, *q;
-       gchar *file;
+       gchar *escaped_utf8uri;
 
        p = uri_list;
 
@@ -1402,17 +1402,36 @@ GList *uri_list_extract_filenames(const gchar *uri_list)
                if (*p != '#') {
                        while (isspace(*p)) p++;
                        if (!strncmp(p, "file:", 5)) {
-                               p += 5;
                                q = p;
+                               q += 5;
                                while (*q && *q != '\n' && *q != '\r') q++;
 
                                if (q > p) {
+                                       gchar *file, *locale_file = NULL;
                                        q--;
                                        while (q > p && isspace(*q)) q--;
-                                       file = g_malloc(q - p + 2);
-                                       strncpy(file, p, q - p + 1);
-                                       file[q - p + 1] = '\0';
-                                       result = g_list_append(result,file);
+                                       Xalloca(escaped_utf8uri, q - p + 2,
+                                               return result);
+                                       Xalloca(file, q - p + 2,
+                                               return result);
+                                       *file = '\0';
+                                       strncpy(escaped_utf8uri, p, q - p + 1);
+                                       escaped_utf8uri[q - p + 1] = '\0';
+                                       decode_uri(file, escaped_utf8uri);
+#warning FIXME_GTK2 /* should we use g_filename_from_utf8()? */
+                    /*
+                    * g_filename_from_uri() rejects escaped/locale encoded uri
+                    * string which come from Nautilus.
+                    */
+                                       if (g_utf8_validate(file, -1, NULL))
+                                               locale_file
+                                                       = conv_codeset_strdup(
+                                                               file + 5,
+                                                               CS_UTF_8,
+                                                               conv_get_current_charset_str());
+                                       if (!locale_file)
+                                               locale_file = g_strdup(file + 5);
+                                       result = g_list_append(result, locale_file);
                                }
                        }
                }
@@ -1501,7 +1520,7 @@ gint scan_mailto_url(const gchar *mailto, gchar **to, gchar **cc, gchar **bcc,
  * but as long as we are not able to do our own extensions to glibc, we do
  * it here.
  */
-gchar *get_home_dir(void)
+const gchar *get_home_dir(void)
 {
 #if HAVE_DOSISH_SYSTEM
     static gchar *home_dir;
@@ -1526,7 +1545,7 @@ gchar *get_home_dir(void)
 #endif
 }
 
-gchar *get_rc_dir(void)
+const gchar *get_rc_dir(void)
 {
        static gchar *rc_dir = NULL;
 
@@ -1537,7 +1556,7 @@ gchar *get_rc_dir(void)
        return rc_dir;
 }
 
-gchar *get_news_cache_dir(void)
+const gchar *get_news_cache_dir(void)
 {
        static gchar *news_cache_dir = NULL;
 
@@ -1548,7 +1567,7 @@ gchar *get_news_cache_dir(void)
        return news_cache_dir;
 }
 
-gchar *get_imap_cache_dir(void)
+const gchar *get_imap_cache_dir(void)
 {
        static gchar *imap_cache_dir = NULL;
 
@@ -1559,7 +1578,7 @@ gchar *get_imap_cache_dir(void)
        return imap_cache_dir;
 }
 
-gchar *get_mbox_cache_dir(void)
+const gchar *get_mbox_cache_dir(void)
 {
        static gchar *mbox_cache_dir = NULL;
 
@@ -1570,7 +1589,7 @@ gchar *get_mbox_cache_dir(void)
        return mbox_cache_dir;
 }
 
-gchar *get_mime_tmp_dir(void)
+const gchar *get_mime_tmp_dir(void)
 {
        static gchar *mime_tmp_dir = NULL;
 
@@ -1581,7 +1600,7 @@ gchar *get_mime_tmp_dir(void)
        return mime_tmp_dir;
 }
 
-gchar *get_template_dir(void)
+const gchar *get_template_dir(void)
 {
        static gchar *template_dir = NULL;
 
@@ -1592,7 +1611,7 @@ gchar *get_template_dir(void)
        return template_dir;
 }
 
-gchar *get_header_cache_dir(void)
+const gchar *get_header_cache_dir(void)
 {
        static gchar *header_dir = NULL;
 
@@ -1603,7 +1622,7 @@ gchar *get_header_cache_dir(void)
        return header_dir;
 }
 
-gchar *get_tmp_dir(void)
+const gchar *get_tmp_dir(void)
 {
        static gchar *tmp_dir = NULL;
 
@@ -1625,7 +1644,7 @@ gchar *get_tmp_file(void)
        return tmp_file;
 }
 
-gchar *get_domain_name(void)
+const gchar *get_domain_name(void)
 {
        static gchar *domain_name = NULL;
 
@@ -3230,7 +3249,7 @@ void debug_set_mode(gboolean mode)
        debug_mode = mode;
 }
 
-gboolean debug_get_mode()
+gboolean debug_get_mode(void)
 {
        return debug_mode;
 }
@@ -3254,7 +3273,7 @@ void * subject_table_lookup(GHashTable *subject_table, gchar * subject)
        if (subject == NULL)
                subject = "";
        else
-               subject += subject_get_reply_prefix_length(subject);
+               subject += subject_get_prefix_length(subject);
 
        return g_hash_table_lookup(subject_table, subject);
 }
@@ -3264,7 +3283,7 @@ void subject_table_insert(GHashTable *subject_table, gchar * subject,
 {
        if (subject == NULL || *subject == 0)
                return;
-       subject += subject_get_reply_prefix_length(subject);
+       subject += subject_get_prefix_length(subject);
        g_hash_table_insert(subject_table, subject, data);
 }
 
@@ -3273,13 +3292,13 @@ void subject_table_remove(GHashTable *subject_table, gchar * subject)
        if (subject == NULL)
                return;
 
-       subject += subject_get_reply_prefix_length(subject);    
+       subject += subject_get_prefix_length(subject);  
        g_hash_table_remove(subject_table, subject);
 }
 
 /*!
  *\brief       Check if a string is prefixed with known (combinations) 
- *             of reply prefixes. The function assumes that each prefix 
+ *             of prefixes. The function assumes that each prefix 
  *             is terminated by zero or exactly _one_ space.
  *
  *\param       str String to check for a prefixes
@@ -3288,16 +3307,21 @@ void subject_table_remove(GHashTable *subject_table, gchar * subject)
  *             for a "clean" subject line. If no prefix was found, 0
  *             is returned.
  */            
-int subject_get_reply_prefix_length(const gchar *subject)
+int subject_get_prefix_length(const gchar *subject)
 {
        /*!< Array with allowable reply prefixes regexps. */
-       static const gchar * const reply_prefixes[] = {
-               "[Rr][Ee]\\:",                  /* "Re:" */
-               "[Rr][Ee]\\[[1-9][0-9]*\\]\\:", /* Intelligent but stupidly non-conforming Re[XXX]:*/
-               "[Aa][Nn][Tt][Ww]\\:"           /* Overactive i18n / translation teams             */
+       static const gchar * const prefixes[] = {
+               "Re\\:",                        /* "Re:" */
+               "Re\\[[1-9][0-9]*\\]\\:",       /* "Re[XXX]:" (non-conforming news mail clients) */
+               "Antw\\:",                      /* "Antw:" (Dutch / German Outlook) */
+               "Aw\\:",                        /* "Aw:"   (German) */
+               "Antwort\\:",                   /* "Antwort:" (German Lotus Notes) */
+               "Res\\:",                       /* "Res:" (Brazilian Outlook) */
+               "Fw\\:",                        /* "Fw:" Forward */
+               "Enc\\:"                        /* "Enc:" Forward (Brazilian Outlook) */
                /* add more */
        };
-       const int REPLY_PREFIXES = sizeof reply_prefixes / sizeof reply_prefixes[0];
+       const int PREFIXES = sizeof prefixes / sizeof prefixes[0];
        int n;
        regmatch_t pos;
        static regex_t regex;
@@ -3309,12 +3333,12 @@ int subject_get_reply_prefix_length(const gchar *subject)
        if (!init_) {
                GString *s = g_string_new("");
                
-               for (n = 0; n < REPLY_PREFIXES; n++)
+               for (n = 0; n < PREFIXES; n++)
                        /* Terminate each prefix regexpression by a
                         * "\ ?" (zero or ONE space), and OR them */
                        g_string_sprintfa(s, "(%s\\ ?)%s",
-                                         reply_prefixes[n],
-                                         n < REPLY_PREFIXES - 1 ? 
+                                         prefixes[n],
+                                         n < PREFIXES - 1 ? 
                                          "|" : "");
                
                g_string_prepend(s, "(");
@@ -3324,7 +3348,7 @@ int subject_get_reply_prefix_length(const gchar *subject)
 
                /* We now have something like "^\ *((PREFIX1\ ?)|(PREFIX2\ ?))+" 
                 * TODO: Should this be       "^\ *(((PREFIX1)|(PREFIX2))\ ?)+" ??? */
-               if (regcomp(&regex, s->str, REG_EXTENDED)) { 
+               if (regcomp(&regex, s->str, REG_EXTENDED | REG_ICASE)) { 
                        debug_print("Error compiling regexp %s\n", s->str);
                        g_string_free(s, TRUE);
                        return 0;
@@ -3561,3 +3585,94 @@ gint g_int_compare(gconstpointer a, gconstpointer b)
 {
        return GPOINTER_TO_INT(a) - GPOINTER_TO_INT(b);
 }
+
+gchar *generate_msgid(const gchar *address, gchar *buf, gint len)
+{
+       /* steal from compose.c::compose_generate_msgid() */
+       struct tm *lt;
+       time_t t;
+       gchar *addr;
+
+       t = time(NULL);
+       lt = localtime(&t);
+
+       if (address && *address) {
+               if (strchr(address, '@'))
+                       addr = g_strdup(address);
+               else
+                       addr = g_strconcat(address, "@", get_domain_name(), NULL);
+       } else
+               addr = g_strconcat(g_get_user_name(), "@", get_domain_name(),
+                                  NULL);
+
+       g_snprintf(buf, len, "%04d%02d%02d%02d%02d%02d.%08x.%s",
+                  lt->tm_year + 1900, lt->tm_mon + 1,
+                  lt->tm_mday, lt->tm_hour,
+                  lt->tm_min, lt->tm_sec,
+                  (guint)random(), addr);
+
+       g_free(addr);
+       return buf;
+}
+
+/**
+ * Create a new boundary in a way that it is very unlikely that this
+ * will occur in the following text.  It would be easy to ensure
+ * uniqueness if everything is either quoted-printable or base64
+ * encoded (note that conversion is allowed), but because MIME bodies
+ * may be nested, it may happen that the same boundary has already
+ * been used. We avoid scanning the message for conflicts and hope the
+ * best.
+ *
+ *   boundary := 0*69<bchars> bcharsnospace
+ *   bchars := bcharsnospace / " "
+ *   bcharsnospace := DIGIT / ALPHA / "'" / "(" / ")" /
+ *                    "+" / "_" / "," / "-" / "." /
+ *                    "/" / ":" / "=" / "?"  
+ *
+ * ":" and "," removed because of buggy MTAs
+ */
+
+gchar *generate_mime_boundary(void)
+{
+       static gchar tbl[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+                            "abcdefghijklmnopqrstuvwxyz" 
+                            "1234567890'()+_./=?";
+       gchar bufuniq[17];
+       gchar bufdate[BUFFSIZE];
+       int i, equal;
+       int pid;
+
+       pid = getpid();
+
+       /* We make the boundary depend on the pid, so that all running
+        * processed generate different values even when they have been
+        * started within the same second and srand48(time(NULL)) has been
+        * used.  I can't see whether this is really an advantage but it
+        * doesn't do any harm.
+        */
+       equal = -1;
+       for (i = 0; i < sizeof(bufuniq) - 1; i++) {
+               bufuniq[i] = tbl[(lrand48() ^ pid) % (sizeof(tbl) - 1)];        /* fill with random */
+               if (bufuniq[i] == '=' && equal == -1)
+                       equal = i;
+       }
+       bufuniq[i] = 0;
+
+       /* now make sure that we do have the sequence "=." in it which cannot
+        * be matched by quoted-printable or base64 encoding */
+       if (equal != -1 && (equal + 1) < i)
+               bufuniq[equal + 1] = '.';
+       else {
+               bufuniq[0] = '=';
+               bufuniq[1] = '.';
+       }
+
+       get_rfc822_date(bufdate, sizeof(bufdate));
+       subst_char(bufdate, ' ', '_');
+       subst_char(bufdate, ',', '_');
+       subst_char(bufdate, ':', '_');
+
+       return g_strdup_printf("Multipart_%s_%s",
+                              bufdate, bufuniq);
+}