2010-02-08 [pawel] 3.7.5cvs8
[claws.git] / src / common / utils.c
index 55634b7a9a0d58239e7ee1ae0847e97b10f779e9..2dccd111f810c1e1727a86fb9a7536da3d691704 100644 (file)
@@ -293,7 +293,7 @@ void ptr_array_free_strings(GPtrArray *array)
        gint i;
        gchar *str;
 
-       g_return_if_fail(array != NULL);
+       cm_return_if_fail(array != NULL);
 
        for (i = 0; i < array->len; i++) {
                str = g_ptr_array_index(array, i);
@@ -346,6 +346,13 @@ gchar *itos(gint n)
        d = (d*100) >> divisor;         \
 }
 
+
+/*!
+ * \brief Convert a given size in bytes in a human-readable string
+ *
+ * \param size  The size expressed in bytes to convert in string
+ * \return      The string that respresents the size in an human-readable way
+ */
 gchar *to_human_readable(goffset size)
 {
        static gchar str[14];
@@ -504,7 +511,7 @@ gint file_strip_crs(const gchar *file)
                goto unlinkout;
        }
        
-       if (rename_force(out, file) < 0)
+       if (move_file(out, file, TRUE) < 0)
                goto unlinkout;
        
        g_free(out);
@@ -991,7 +998,7 @@ GList *add_history(GList *list, const gchar *str)
 {
        GList *old;
 
-       g_return_val_if_fail(str != NULL, list);
+       cm_return_val_if_fail(str != NULL, list);
 
        old = g_list_find_custom(list, (gpointer)str, (GCompareFunc)strcmp2);
        if (old) {
@@ -1159,8 +1166,8 @@ gint get_quote_level(const gchar *str, const gchar *quote_chars)
                if (strchr(quote_chars, *p))
                        quote_level++;
                else if (*p != '-' && !g_ascii_isspace(*p) && p <= last_pos) {
-                       /* any characters are allowed except '-' and space */
-                       while (*p != '-'
+                       /* any characters are allowed except '-','<' and space */
+                       while (*p != '-' && *p != '<'
                               && !strchr(quote_chars, *p)
                               && !g_ascii_isspace(*p)
                               && p < last_pos)
@@ -1265,8 +1272,8 @@ gchar **strsplit_with_quote(const gchar *str, const gchar *delim,
        gchar **str_array, *s, *new_str;
        guint i, n = 1, len;
 
-       g_return_val_if_fail(str != NULL, NULL);
-       g_return_val_if_fail(delim != NULL, NULL);
+       cm_return_val_if_fail(str != NULL, NULL);
+       cm_return_val_if_fail(delim != NULL, NULL);
 
        if (max_tokens < 1)
                max_tokens = G_MAXINT;
@@ -1325,7 +1332,7 @@ gchar *get_abbrev_newsgroup_name(const gchar *group, gint len)
        const gchar *p = group;
        const gchar *last;
 
-       g_return_val_if_fail(group != NULL, NULL);
+       cm_return_val_if_fail(group != NULL, NULL);
 
        last = group + strlen(group);
        abbrev_group = ap = g_malloc(strlen(group) + 1);
@@ -1544,7 +1551,7 @@ static gchar *decode_uri_gdup(const gchar *encoded_uri)
 }
 
 gint scan_mailto_url(const gchar *mailto, gchar **from, gchar **to, gchar **cc, gchar **bcc,
-                    gchar **subject, gchar **body, gchar ***attach)
+                    gchar **subject, gchar **body, gchar ***attach, gchar **inreplyto)
 {
        gchar *tmp_mailto;
        gchar *p;
@@ -1628,8 +1635,8 @@ gint scan_mailto_url(const gchar *mailto, gchar **from, gchar **to, gchar **cc,
                        *body = decode_uri_gdup(value);
                } else if (body && !*body && !g_ascii_strcasecmp(field, "insert")) {
                        gchar *tmp = decode_uri_gdup(value);
-                       if (!g_file_get_contents(value, body, NULL, NULL)) {
-                               g_error("Error: couldn't set insert file '%s' in body\n", value);
+                       if (!g_file_get_contents(tmp, body, NULL, NULL)) {
+                               g_warning("Error: couldn't set insert file '%s' in body\n", value);
                        }
                        g_free(tmp);
                        tmp = NULL;
@@ -1652,6 +1659,9 @@ gint scan_mailto_url(const gchar *mailto, gchar **from, gchar **to, gchar **cc,
                                my_att[num_attach-1] = tmp;
                                my_att[num_attach] = NULL;
                        }
+               } else if (inreplyto && !*inreplyto &&
+                          !g_ascii_strcasecmp(field, "in-reply-to")) {
+                       *inreplyto = decode_uri_gdup(value);
                }
        }
 
@@ -1986,6 +1996,16 @@ const gchar *get_cert_file(void)
 }
 #endif
 
+/* Return the filepath of the claws-mail.desktop file */
+const gchar *get_desktop_file(void)
+{
+#ifdef DESKTOPFILEPATH
+  return DESKTOPFILEPATH;
+#else
+  return NULL;
+#endif
+}
+
 /* Return the default directory for Plugins. */
 const gchar *get_plugin_dir(void)
 {
@@ -2759,6 +2779,9 @@ gint canonicalize_file(const gchar *src, const gchar *dest)
        gboolean err = FALSE;
        gboolean last_linebreak = FALSE;
 
+       if (src == NULL || dest == NULL)
+               return -1;
+
        if ((src_fp = g_fopen(src, "rb")) == NULL) {
                FILE_OP_ERROR(src, "g_fopen");
                return -1;
@@ -3037,7 +3060,7 @@ FILE *str_open_as_stream(const gchar *str)
        FILE *fp;
        size_t len;
 
-       g_return_val_if_fail(str != NULL, NULL);
+       cm_return_val_if_fail(str != NULL, NULL);
 
        fp = my_tmpfile();
        if (!fp) {
@@ -3063,8 +3086,8 @@ gint str_write_to_file(const gchar *str, const gchar *file)
        FILE *fp;
        size_t len;
 
-       g_return_val_if_fail(str != NULL, -1);
-       g_return_val_if_fail(file != NULL, -1);
+       cm_return_val_if_fail(str != NULL, -1);
+       cm_return_val_if_fail(file != NULL, -1);
 
        if ((fp = g_fopen(file, "wb")) == NULL) {
                FILE_OP_ERROR(file, "g_fopen");
@@ -3100,7 +3123,7 @@ static gchar *file_read_stream_to_str_full(FILE *fp, gboolean recode)
        gint n_read;
        gchar *str;
 
-       g_return_val_if_fail(fp != NULL, NULL);
+       cm_return_val_if_fail(fp != NULL, NULL);
 
        array = g_byte_array_new();
 
@@ -3146,7 +3169,7 @@ static gchar *file_read_to_str_full(const gchar *file, gboolean recode)
        int fflags = 0;
 #endif
 
-       g_return_val_if_fail(file != NULL, NULL);
+       cm_return_val_if_fail(file != NULL, NULL);
 
        if (g_stat(file, &s) != 0) {
                FILE_OP_ERROR(file, "stat");
@@ -3165,7 +3188,7 @@ static gchar *file_read_to_str_full(const gchar *file, gboolean recode)
        }
 #else    
        /* test whether the file is readable without blocking */
-       fd = g_open(file, O_RDONLY | O_NONBLOCK);
+       fd = g_open(file, O_RDONLY | O_NONBLOCK, 0);
        if (fd == -1) {
                FILE_OP_ERROR(file, "open");
                return NULL;
@@ -3266,7 +3289,7 @@ char *fgets_crlf(char *buf, int size, FILE *stream)
 
 static gint execute_async(gchar *const argv[])
 {
-       g_return_val_if_fail(argv != NULL && argv[0] != NULL, -1);
+       cm_return_val_if_fail(argv != NULL && argv[0] != NULL, -1);
 
        if (g_spawn_async(NULL, (gchar **)argv, NULL, G_SPAWN_SEARCH_PATH,
                          NULL, NULL, NULL, FALSE) == FALSE) {
@@ -3281,20 +3304,27 @@ static gint execute_sync(gchar *const argv[])
 {
        gint status;
 
-       g_return_val_if_fail(argv != NULL && argv[0] != NULL, -1);
+       cm_return_val_if_fail(argv != NULL && argv[0] != NULL, -1);
 
+#ifdef G_OS_UNIX
        if (g_spawn_sync(NULL, (gchar **)argv, NULL, G_SPAWN_SEARCH_PATH,
                         NULL, NULL, NULL, NULL, &status, NULL) == FALSE) {
                g_warning("Couldn't execute command: %s\n", argv[0]);
                return -1;
        }
 
-#ifdef G_OS_UNIX
        if (WIFEXITED(status))
                return WEXITSTATUS(status);
        else
                return -1;
 #else
+       if (g_spawn_sync(NULL, (gchar **)argv, NULL, G_SPAWN_SEARCH_PATH| 
+                        G_SPAWN_CHILD_INHERITS_STDIN|G_SPAWN_LEAVE_DESCRIPTORS_OPEN,
+                        NULL, NULL, NULL, NULL, &status, NULL) == FALSE) {
+               g_warning("Couldn't execute command: %s\n", argv[0]);
+               return -1;
+       }
+
        return status;
 #endif
 }
@@ -3323,7 +3353,7 @@ gchar *get_command_output(const gchar *cmdline)
        gchar *child_stdout;
        gint status;
 
-       g_return_val_if_fail(cmdline != NULL, NULL);
+       cm_return_val_if_fail(cmdline != NULL, NULL);
 
        debug_print("get_command_output(): executing: %s\n", cmdline);
 
@@ -3379,7 +3409,7 @@ gint open_uri(const gchar *uri, const gchar *cmdline)
        gchar buf[BUFFSIZE];
        gchar *p;
        gchar encoded_uri[BUFFSIZE];
-       g_return_val_if_fail(uri != NULL, -1);
+       cm_return_val_if_fail(uri != NULL, -1);
 
        /* an option to choose whether to use encode_uri or not ? */
        encode_uri(encoded_uri, BUFFSIZE, uri);
@@ -3414,7 +3444,7 @@ gint open_txt_editor(const gchar *filepath, const gchar *cmdline)
        gchar buf[BUFFSIZE];
        gchar *p;
 
-       g_return_val_if_fail(filepath != NULL, -1);
+       cm_return_val_if_fail(filepath != NULL, -1);
 
        if (cmdline &&
            (p = strchr(cmdline, '%')) && *(p + 1) == 's' &&
@@ -3656,18 +3686,6 @@ void subject_table_remove(GHashTable *subject_table, gchar * subject)
        g_hash_table_remove(subject_table, subject);
 }
 
-/*!
- *\brief       Check if a string is prefixed with known (combinations)
- *             of prefixes. The function assumes that each prefix
- *             is terminated by zero or exactly _one_ space.
- *
- *\param       str String to check for a prefixes
- *
- *\return      int Number of chars in the prefix that should be skipped
- *             for a "clean" subject line. If no prefix was found, 0
- *             is returned.
- */
 #ifndef G_OS_WIN32
 static regex_t u_regex;
 static gboolean u_init_;
@@ -3683,6 +3701,17 @@ void utils_free_regex(void)
 #endif
 }
 
+/*!
+ *\brief       Check if a string is prefixed with known (combinations)
+ *             of prefixes. The function assumes that each prefix
+ *             is terminated by zero or exactly _one_ space.
+ *
+ *\param       str String to check for a prefixes
+ *
+ *\return      int Number of chars in the prefix that should be skipped
+ *             for a "clean" subject line. If no prefix was found, 0
+ *             is returned.
+ */
 int subject_get_prefix_length(const gchar *subject)
 {
 #ifndef G_OS_WIN32
@@ -3702,7 +3731,9 @@ int subject_get_prefix_length(const gchar *subject)
                "Sv\\:",                        /* "Sv" (Norwegian) */
                "Vs\\:",                        /* "Vs" (Norwegian) */
                "Ad\\:",                        /* "Ad" (Norwegian) */
-               "\347\255\224\345\244\215\\:"   /* "Re" (Chinese, UTF-8) */
+               "\347\255\224\345\244\215\\:",  /* "Re" (Chinese, UTF-8) */
+               "R\303\251f\\. \\:",            /* "Réf. :" (French Lotus Notes) */
+               "Re \\:",                       /* "Re :" (French Yahoo Mail) */
                /* add more */
        };
        const int PREFIXES = sizeof prefixes / sizeof prefixes[0];
@@ -3760,6 +3791,8 @@ int subject_get_prefix_length(const gchar *subject)
                "sv:",                  /* "Sv" (Norwegian) */
                "vs:",                  /* "Vs" (Norwegian) */
                "ad:",                  /* "Ad" (Norwegian) */
+               "R\303\251f. :",        /* "Réf. :" (French Lotus Notes) */
+               "Re :",                 /* "Re :" (French Yahoo Mail) */
                /* add more */
        };
        const int PREFIXES = sizeof prefixes / sizeof prefixes[0];
@@ -3770,8 +3803,12 @@ int subject_get_prefix_length(const gchar *subject)
 
        for (n = 0; n < PREFIXES; n++) {
                int len = strlen(prefixes[n]);
-               if (!strncasecmp(subject, prefixes[n], len))
-                       return len;
+               if (!strncasecmp(subject, prefixes[n], len)) {
+                       if (subject[len] == ' ')
+                               return len+1;
+                       else
+                               return len;
+               }
        }
        return 0;
 #endif
@@ -3801,7 +3838,7 @@ gint g_int_compare(gconstpointer a, gconstpointer b)
        return GPOINTER_TO_INT(a) - GPOINTER_TO_INT(b);
 }
 
-gchar *generate_msgid(gchar *buf, gint len)
+gchar *generate_msgid(gchar *buf, gint len, gchar *user_addr)
 {
        struct tm *lt;
        time_t t;
@@ -3814,10 +3851,20 @@ gchar *generate_msgid(gchar *buf, gint len)
        lt = localtime_r(&t, &buft);
 
        if (strcmp(buf, "") == 0) {
-               addr = g_strconcat("@", get_domain_name(), NULL);
+               if (user_addr != NULL) {
+                       addr = g_strconcat(user_addr, "@", get_domain_name(), NULL);
+               }
+               else {
+                       addr = g_strconcat("@", get_domain_name(), NULL);
+               }
        }
        else {
-               addr = g_strconcat("@", buf, NULL);
+               if (user_addr != NULL) {
+                       addr = g_strconcat(user_addr, "@", buf, NULL);
+               }
+               else {
+                       addr = g_strconcat("@", buf, NULL);
+               }
        }
 
        g_snprintf(buf, len, "%04d%02d%02d%02d%02d%02d.%08x%s",
@@ -3918,8 +3965,8 @@ GNode *g_node_map(GNode *node, GNodeMapFunc func, gpointer data)
        GNode *root;
        GNodeMapData mapdata;
 
-       g_return_val_if_fail(node != NULL, NULL);
-       g_return_val_if_fail(func != NULL, NULL);
+       cm_return_val_if_fail(node != NULL, NULL);
+       cm_return_val_if_fail(func != NULL, NULL);
 
        root = g_node_new(func(node->data, data));
 
@@ -4196,10 +4243,10 @@ gboolean get_uri_part(const gchar *start, const gchar *scanpos,
        const gchar *ep_;
        gint parenthese_cnt = 0;
 
-       g_return_val_if_fail(start != NULL, FALSE);
-       g_return_val_if_fail(scanpos != NULL, FALSE);
-       g_return_val_if_fail(bp != NULL, FALSE);
-       g_return_val_if_fail(ep != NULL, FALSE);
+       cm_return_val_if_fail(start != NULL, FALSE);
+       cm_return_val_if_fail(scanpos != NULL, FALSE);
+       cm_return_val_if_fail(bp != NULL, FALSE);
+       cm_return_val_if_fail(ep != NULL, FALSE);
 
        *bp = scanpos;
 
@@ -4225,7 +4272,7 @@ gboolean get_uri_part(const gchar *start, const gchar *scanpos,
         * should pass some URI type to this function and decide on that whether
         * to perform punctuation stripping */
 
-#define IS_REAL_PUNCT(ch)      (g_ascii_ispunct(ch) && !strchr("/?=-)", ch))
+#define IS_REAL_PUNCT(ch)      (g_ascii_ispunct(ch) && !strchr("/?=-_)", ch))
 
        for (; ep_ - 1 > scanpos + 1 &&
               IS_REAL_PUNCT(*(ep_ - 1));
@@ -4292,7 +4339,7 @@ static GHashTable *create_domain_tab(void)
        gint n;
        GHashTable *htab = g_hash_table_new(g_stricase_hash, g_stricase_equal);
 
-       g_return_val_if_fail(htab, NULL);
+       cm_return_val_if_fail(htab, NULL);
        for (n = 0; n < sizeof toplvl_domains / sizeof toplvl_domains[0]; n++)
                g_hash_table_insert(htab, (gpointer) toplvl_domains[n], (gpointer) toplvl_domains[n]);
        return htab;
@@ -4335,10 +4382,10 @@ gboolean get_email_part(const gchar *start, const gchar *scanpos,
        gchar closure_stack[128];
        gchar *ptr = closure_stack;
 
-       g_return_val_if_fail(start != NULL, FALSE);
-       g_return_val_if_fail(scanpos != NULL, FALSE);
-       g_return_val_if_fail(bp != NULL, FALSE);
-       g_return_val_if_fail(ep != NULL, FALSE);
+       cm_return_val_if_fail(start != NULL, FALSE);
+       cm_return_val_if_fail(scanpos != NULL, FALSE);
+       cm_return_val_if_fail(bp != NULL, FALSE);
+       cm_return_val_if_fail(ep != NULL, FALSE);
 
        if (hdr) {
                const gchar *start_quote = NULL;
@@ -4404,7 +4451,7 @@ search_again:
 
        if (!dom_tab)
                dom_tab = create_domain_tab();
-       g_return_val_if_fail(dom_tab, FALSE);
+       cm_return_val_if_fail(dom_tab, FALSE);
 
        /* scan start of address */
        for (bp_ = scanpos - 1;