Fix printf formats for size_t and goffset arguments.
[claws.git] / src / common / utils.c
index 51729821fa8ca1ecf214bad94ffd5e74892e65ac..ec87994ec0024d59da919a792d8c0aa46a557934 100644 (file)
 #include <ctype.h>
 #include <errno.h>
 #include <sys/param.h>
-#ifndef G_OS_WIN32
-#include <sys/socket.h>
+#ifdef G_OS_WIN32
+#  include <ws2tcpip.h>
+#else
+#  include <sys/socket.h>
 #endif
 
 #if (HAVE_WCTYPE_H && HAVE_WCHAR_H)
 
 #include "utils.h"
 #include "socket.h"
-#include "../codeconv.h"
+#include "codeconv.h"
 #include "tlds.h"
+#include "timing.h"
+#include "file-utils.h"
 
 #define BUFFSIZE       8192
 
 static gboolean debug_mode = FALSE;
 
-#if !GLIB_CHECK_VERSION(2, 26, 0)
-guchar *g_base64_decode_wa(const gchar *text, gsize *out_len)
-{
-       guchar *ret;
-       gsize input_length;
-       gint state = 0;
-       guint save = 0;
-
-       input_length = strlen(text);
-
-       ret = g_malloc0((input_length / 4) * 3 + 1);
-
-       *out_len = g_base64_decode_step(text, input_length, ret, &state, &save);
-
-       return ret;
-}
-#endif
-
-/* Return true if we are running as root.  This function should beused
-   instead of getuid () == 0.  */
-gboolean superuser_p (void)
-{
-#ifdef G_OS_WIN32
-  return w32_is_administrator ();
-#else
-  return !getuid();
-#endif  
-}
-
 GSList *slist_copy_deep(GSList *list, GCopyFunc func)
 {
 #if GLIB_CHECK_VERSION(2, 34, 0)
@@ -173,19 +148,6 @@ guint str_case_hash(gconstpointer key)
        return h;
 }
 
-void ptr_array_free_strings(GPtrArray *array)
-{
-       gint i;
-       gchar *str;
-
-       cm_return_if_fail(array != NULL);
-
-       for (i = 0; i < array->len; i++) {
-               str = g_ptr_array_index(array, i);
-               g_free(str);
-       }
-}
-
 gint to_number(const gchar *nstr)
 {
        register const gchar *p;
@@ -231,7 +193,7 @@ gchar *itos(gint n)
 gchar *to_human_readable(goffset size)
 {
        static gchar str[14];
-       static gchar *b_format = NULL, *kb_format = NULL, 
+       static gchar *b_format = NULL, *kb_format = NULL,
                     *mb_format = NULL, *gb_format = NULL;
        register int t = 0, r = 0;
        if (b_format == NULL) {
@@ -240,7 +202,7 @@ gchar *to_human_readable(goffset size)
                mb_format = _("%d.%02dMB");
                gb_format = _("%.2fGB");
        }
-       
+
        if (size < (goffset)1024) {
                g_snprintf(str, sizeof(str), b_format, (gint)size);
                return str;
@@ -258,22 +220,6 @@ gchar *to_human_readable(goffset size)
        }
 }
 
-/* strcmp with NULL-checking */
-gint strcmp2(const gchar *s1, const gchar *s2)
-{
-       if (s1 == NULL || s2 == NULL)
-               return -1;
-       else
-               return strcmp(s1, s2);
-}
-/* strstr with NULL-checking */
-gchar *strstr2(const gchar *s1, const gchar *s2)
-{
-       if (s1 == NULL || s2 == NULL)
-               return NULL;
-       else
-               return strstr(s1, s2);
-}
 /* compare paths */
 gint path_cmp(const gchar *s1, const gchar *s2)
 {
@@ -354,50 +300,6 @@ gchar *strcrchomp(gchar *str)
        return str;
 }
 
-gint file_strip_crs(const gchar *file)
-{
-       FILE *fp = NULL, *outfp = NULL;
-       gchar buf[4096];
-       gchar *out = get_tmp_file();
-       if (file == NULL)
-               goto freeout;
-
-       fp = g_fopen(file, "rb");
-       if (!fp)
-               goto freeout;
-
-       outfp = g_fopen(out, "wb");
-       if (!outfp) {
-               fclose(fp);
-               goto freeout;
-       }
-
-       while (fgets(buf, sizeof (buf), fp) != NULL) {
-               strcrchomp(buf);
-               if (fputs(buf, outfp) == EOF) {
-                       fclose(fp);
-                       fclose(outfp);
-                       goto unlinkout;
-               }
-       }
-
-       fclose(fp);
-       if (fclose(outfp) == EOF) {
-               goto unlinkout;
-       }
-       
-       if (move_file(out, file, TRUE) < 0)
-               goto unlinkout;
-       
-       g_free(out);
-       return 0;
-unlinkout:
-       claws_unlink(out);
-freeout:
-       g_free(out);
-       return -1;
-}
-
 /* Similar to `strstr' but this function ignores the case of both strings.  */
 gchar *strcasestr(const gchar *haystack, const gchar *needle)
 {
@@ -924,7 +826,7 @@ GList *add_history(GList *list, const gchar *str)
 
        cm_return_val_if_fail(str != NULL, list);
 
-       old = g_list_find_custom(list, (gpointer)str, (GCompareFunc)strcmp2);
+       old = g_list_find_custom(list, (gpointer)str, (GCompareFunc)g_strcmp0);
        if (old) {
                oldstr = old->data;
                list = g_list_remove(list, old->data);
@@ -1755,7 +1657,7 @@ const gchar *get_locale_dir(void)
 #endif
        if (!loc_dir)
                loc_dir = LOCALEDIR;
-       
+
        return loc_dir;
 }
 
@@ -1818,11 +1720,11 @@ void set_rc_dir(const gchar *dir)
                rc_dir_alt = TRUE;
 
                claws_rc_dir = canonical_dir;
-               
+
                len = strlen(claws_rc_dir);
                if (claws_rc_dir[len - 1] == G_DIR_SEPARATOR)
                        claws_rc_dir[len - 1] = '\0';
-               
+
                debug_print("set rc_dir to %s\n", claws_rc_dir);
                if (!is_dir_exist(claws_rc_dir)) {
                        if (make_dir_hier(claws_rc_dir) != 0) {
@@ -1894,7 +1796,7 @@ const gchar *w32_get_cert_file(void)
                cert_file = g_strconcat(w32_get_module_dir(),
                                 "\\share\\claws-mail\\",
                                "ca-certificates.crt",
-                               NULL);  
+                               NULL);
        return cert_file;
 }
 #endif
@@ -1926,10 +1828,10 @@ const gchar *get_plugin_dir(void)
        else {
                static gchar *plugin_dir = NULL;
                if (!plugin_dir)
-                       plugin_dir = g_strconcat(get_rc_dir(), 
-                               G_DIR_SEPARATOR_S, "plugins", 
+                       plugin_dir = g_strconcat(get_rc_dir(),
+                               G_DIR_SEPARATOR_S, "plugins",
                                G_DIR_SEPARATOR_S, NULL);
-               return plugin_dir;                      
+               return plugin_dir;
        }
 #endif
 }
@@ -2008,6 +1910,29 @@ const gchar *get_domain_name(void)
 #endif
 }
 
+/* Tells whether the given host address string is a valid representation of a
+ * numerical IP (v4 or, if supported, v6) address.
+ */
+gboolean is_numeric_host_address(const gchar *hostaddress)
+{
+       struct addrinfo hints, *res;
+       int err;
+
+       /* See what getaddrinfo makes of the string when told that it is a
+        * numeric IP address representation. */
+       memset(&hints, 0, sizeof(struct addrinfo));
+       hints.ai_family = AF_UNSPEC;
+       hints.ai_socktype = 0;
+       hints.ai_flags = AI_NUMERICHOST;
+       hints.ai_protocol = 0;
+
+       err = getaddrinfo(hostaddress, NULL, &hints, &res);
+       if (err == 0)
+               freeaddrinfo(res);
+
+       return (err == 0);
+}
+
 off_t get_file_size(const gchar *file)
 {
 #ifdef G_OS_WIN32
@@ -2432,249 +2357,6 @@ gint remove_dir_recursive(const gchar *dir)
        return 0;
 }
 
-gint rename_force(const gchar *oldpath, const gchar *newpath)
-{
-#ifndef G_OS_UNIX
-       if (!is_file_entry_exist(oldpath)) {
-               errno = ENOENT;
-               return -1;
-       }
-       if (is_file_exist(newpath)) {
-               if (claws_unlink(newpath) < 0)
-                       FILE_OP_ERROR(newpath, "unlink");
-       }
-#endif
-       return g_rename(oldpath, newpath);
-}
-
-/*
- * Append src file body to the tail of dest file.
- * Now keep_backup has no effects.
- */
-gint append_file(const gchar *src, const gchar *dest, gboolean keep_backup)
-{
-       FILE *src_fp, *dest_fp;
-       gint n_read;
-       gchar buf[BUFSIZ];
-
-       gboolean err = FALSE;
-
-       if ((src_fp = g_fopen(src, "rb")) == NULL) {
-               FILE_OP_ERROR(src, "g_fopen");
-               return -1;
-       }
-
-       if ((dest_fp = g_fopen(dest, "ab")) == NULL) {
-               FILE_OP_ERROR(dest, "g_fopen");
-               fclose(src_fp);
-               return -1;
-       }
-
-       if (change_file_mode_rw(dest_fp, dest) < 0) {
-               FILE_OP_ERROR(dest, "chmod");
-               g_warning("can't change file mode: %s", dest);
-       }
-
-       while ((n_read = fread(buf, sizeof(gchar), sizeof(buf), src_fp)) > 0) {
-               if (n_read < sizeof(buf) && ferror(src_fp))
-                       break;
-               if (fwrite(buf, 1, n_read, dest_fp) < n_read) {
-                       g_warning("writing to %s failed.", dest);
-                       fclose(dest_fp);
-                       fclose(src_fp);
-                       claws_unlink(dest);
-                       return -1;
-               }
-       }
-
-       if (ferror(src_fp)) {
-               FILE_OP_ERROR(src, "fread");
-               err = TRUE;
-       }
-       fclose(src_fp);
-       if (fclose(dest_fp) == EOF) {
-               FILE_OP_ERROR(dest, "fclose");
-               err = TRUE;
-       }
-
-       if (err) {
-               claws_unlink(dest);
-               return -1;
-       }
-
-       return 0;
-}
-
-gint copy_file(const gchar *src, const gchar *dest, gboolean keep_backup)
-{
-       FILE *src_fp, *dest_fp;
-       gint n_read;
-       gchar buf[BUFSIZ];
-       gchar *dest_bak = NULL;
-       gboolean err = FALSE;
-
-       if ((src_fp = g_fopen(src, "rb")) == NULL) {
-               FILE_OP_ERROR(src, "g_fopen");
-               return -1;
-       }
-       if (is_file_exist(dest)) {
-               dest_bak = g_strconcat(dest, ".bak", NULL);
-               if (rename_force(dest, dest_bak) < 0) {
-                       FILE_OP_ERROR(dest, "rename");
-                       fclose(src_fp);
-                       g_free(dest_bak);
-                       return -1;
-               }
-       }
-
-       if ((dest_fp = g_fopen(dest, "wb")) == NULL) {
-               FILE_OP_ERROR(dest, "g_fopen");
-               fclose(src_fp);
-               if (dest_bak) {
-                       if (rename_force(dest_bak, dest) < 0)
-                               FILE_OP_ERROR(dest_bak, "rename");
-                       g_free(dest_bak);
-               }
-               return -1;
-       }
-
-       if (change_file_mode_rw(dest_fp, dest) < 0) {
-               FILE_OP_ERROR(dest, "chmod");
-               g_warning("can't change file mode: %s", dest);
-       }
-
-       while ((n_read = fread(buf, sizeof(gchar), sizeof(buf), src_fp)) > 0) {
-               if (n_read < sizeof(buf) && ferror(src_fp))
-                       break;
-               if (fwrite(buf, 1, n_read, dest_fp) < n_read) {
-                       g_warning("writing to %s failed.", dest);
-                       fclose(dest_fp);
-                       fclose(src_fp);
-                       claws_unlink(dest);
-                       if (dest_bak) {
-                               if (rename_force(dest_bak, dest) < 0)
-                                       FILE_OP_ERROR(dest_bak, "rename");
-                               g_free(dest_bak);
-                       }
-                       return -1;
-               }
-       }
-
-       if (ferror(src_fp)) {
-               FILE_OP_ERROR(src, "fread");
-               err = TRUE;
-       }
-       fclose(src_fp);
-       if (fclose(dest_fp) == EOF) {
-               FILE_OP_ERROR(dest, "fclose");
-               err = TRUE;
-       }
-
-       if (err) {
-               claws_unlink(dest);
-               if (dest_bak) {
-                       if (rename_force(dest_bak, dest) < 0)
-                               FILE_OP_ERROR(dest_bak, "rename");
-                       g_free(dest_bak);
-               }
-               return -1;
-       }
-
-       if (keep_backup == FALSE && dest_bak)
-               claws_unlink(dest_bak);
-
-       g_free(dest_bak);
-
-       return 0;
-}
-
-gint move_file(const gchar *src, const gchar *dest, gboolean overwrite)
-{
-       if (overwrite == FALSE && is_file_exist(dest)) {
-               g_warning("move_file(): file %s already exists.", dest);
-               return -1;
-       }
-
-       if (rename_force(src, dest) == 0) return 0;
-
-       if (EXDEV != errno) {
-               FILE_OP_ERROR(src, "rename");
-               return -1;
-       }
-
-       if (copy_file(src, dest, FALSE) < 0) return -1;
-
-       claws_unlink(src);
-
-       return 0;
-}
-
-gint copy_file_part_to_fp(FILE *fp, off_t offset, size_t length, FILE *dest_fp)
-{
-       gint n_read;
-       gint bytes_left, to_read;
-       gchar buf[BUFSIZ];
-
-       if (fseek(fp, offset, SEEK_SET) < 0) {
-               perror("fseek");
-               return -1;
-       }
-
-       bytes_left = length;
-       to_read = MIN(bytes_left, sizeof(buf));
-
-       while ((n_read = fread(buf, sizeof(gchar), to_read, fp)) > 0) {
-               if (n_read < to_read && ferror(fp))
-                       break;
-               if (fwrite(buf, 1, n_read, dest_fp) < n_read) {
-                       return -1;
-               }
-               bytes_left -= n_read;
-               if (bytes_left == 0)
-                       break;
-               to_read = MIN(bytes_left, sizeof(buf));
-       }
-
-       if (ferror(fp)) {
-               perror("fread");
-               return -1;
-       }
-
-       return 0;
-}
-
-gint copy_file_part(FILE *fp, off_t offset, size_t length, const gchar *dest)
-{
-       FILE *dest_fp;
-       gboolean err = FALSE;
-
-       if ((dest_fp = g_fopen(dest, "wb")) == NULL) {
-               FILE_OP_ERROR(dest, "g_fopen");
-               return -1;
-       }
-
-       if (change_file_mode_rw(dest_fp, dest) < 0) {
-               FILE_OP_ERROR(dest, "chmod");
-               g_warning("can't change file mode: %s", dest);
-       }
-
-       if (copy_file_part_to_fp(fp, offset, length, dest_fp) < 0)
-               err = TRUE;
-
-       if (!err && fclose(dest_fp) == EOF) {
-               FILE_OP_ERROR(dest, "fclose");
-               err = TRUE;
-       }
-
-       if (err) {
-               g_warning("writing to %s failed.", dest);
-               claws_unlink(dest);
-               return -1;
-       }
-
-       return 0;
-}
-
 /* convert line endings into CRLF. If the last line doesn't end with
  * linebreak, add it.
  */
@@ -2711,109 +2393,6 @@ gchar *canonicalize_str(const gchar *str)
        return out;
 }
 
-gint canonicalize_file(const gchar *src, const gchar *dest)
-{
-       FILE *src_fp, *dest_fp;
-       gchar buf[BUFFSIZE];
-       gint len;
-       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;
-       }
-
-       if ((dest_fp = g_fopen(dest, "wb")) == NULL) {
-               FILE_OP_ERROR(dest, "g_fopen");
-               fclose(src_fp);
-               return -1;
-       }
-
-       if (change_file_mode_rw(dest_fp, dest) < 0) {
-               FILE_OP_ERROR(dest, "chmod");
-               g_warning("can't change file mode: %s", dest);
-       }
-
-       while (fgets(buf, sizeof(buf), src_fp) != NULL) {
-               gint r = 0;
-
-               len = strlen(buf);
-               if (len == 0) break;
-               last_linebreak = FALSE;
-
-               if (buf[len - 1] != '\n') {
-                       last_linebreak = TRUE;
-                       r = fputs(buf, dest_fp);
-               } else if (len > 1 && buf[len - 1] == '\n' && buf[len - 2] == '\r') {
-                       r = fputs(buf, dest_fp);
-               } else {
-                       if (len > 1) {
-                               r = fwrite(buf, 1, len - 1, dest_fp);
-                               if (r != (len -1))
-                                       r = EOF;
-                       }
-                       if (r != EOF)
-                               r = fputs("\r\n", dest_fp);
-               }
-
-               if (r == EOF) {
-                       g_warning("writing to %s failed.", dest);
-                       fclose(dest_fp);
-                       fclose(src_fp);
-                       claws_unlink(dest);
-                       return -1;
-               }
-       }
-
-       if (last_linebreak == TRUE) {
-               if (fputs("\r\n", dest_fp) == EOF)
-                       err = TRUE;
-       }
-
-       if (ferror(src_fp)) {
-               FILE_OP_ERROR(src, "fgets");
-               err = TRUE;
-       }
-       fclose(src_fp);
-       if (fclose(dest_fp) == EOF) {
-               FILE_OP_ERROR(dest, "fclose");
-               err = TRUE;
-       }
-
-       if (err) {
-               claws_unlink(dest);
-               return -1;
-       }
-
-       return 0;
-}
-
-gint canonicalize_file_replace(const gchar *file)
-{
-       gchar *tmp_file;
-
-       tmp_file = get_tmp_file();
-
-       if (canonicalize_file(file, tmp_file) < 0) {
-               g_free(tmp_file);
-               return -1;
-       }
-
-       if (move_file(tmp_file, file, TRUE) < 0) {
-               g_warning("can't replace file: %s", file);
-               claws_unlink(tmp_file);
-               g_free(tmp_file);
-               return -1;
-       }
-
-       g_free(tmp_file);
-       return 0;
-}
-
 gchar *normalize_newlines(const gchar *str)
 {
        const gchar *p;
@@ -2842,7 +2421,7 @@ gchar *get_outgoing_rfc2822_str(FILE *fp)
        str = g_string_new(NULL);
 
        /* output header part */
-       while (fgets(buf, sizeof(buf), fp) != NULL) {
+       while (claws_fgets(buf, sizeof(buf), fp) != NULL) {
                strretchomp(buf);
                if (!g_ascii_strncasecmp(buf, "Bcc:", 4)) {
                        gint next;
@@ -2855,7 +2434,7 @@ gchar *get_outgoing_rfc2822_str(FILE *fp)
                                        ungetc(next, fp);
                                        break;
                                }
-                               if (fgets(buf, sizeof(buf), fp) == NULL)
+                               if (claws_fgets(buf, sizeof(buf), fp) == NULL)
                                        break;
                        }
                } else {
@@ -2867,7 +2446,7 @@ gchar *get_outgoing_rfc2822_str(FILE *fp)
        }
 
        /* output body part */
-       while (fgets(buf, sizeof(buf), fp) != NULL) {
+       while (claws_fgets(buf, sizeof(buf), fp) != NULL) {
                strretchomp(buf);
                if (buf[0] == '.')
                        g_string_append_c(str, '.');
@@ -2914,280 +2493,6 @@ gchar *generate_mime_boundary(const gchar *prefix)
                               buf_uniq);
 }
 
-gint change_file_mode_rw(FILE *fp, const gchar *file)
-{
-#if HAVE_FCHMOD
-       return fchmod(fileno(fp), S_IRUSR|S_IWUSR);
-#else
-       return g_chmod(file, S_IRUSR|S_IWUSR);
-#endif
-}
-
-FILE *my_tmpfile(void)
-{
-       const gchar suffix[] = ".XXXXXX";
-       const gchar *tmpdir;
-       guint tmplen;
-       const gchar *progname;
-       guint proglen;
-       gchar *fname;
-       gint fd;
-       FILE *fp;
-#ifndef G_OS_WIN32
-       gchar buf[2]="\0";
-#endif
-
-       tmpdir = get_tmp_dir();
-       tmplen = strlen(tmpdir);
-       progname = g_get_prgname();
-       if (progname == NULL)
-               progname = "claws-mail";
-       proglen = strlen(progname);
-       Xalloca(fname, tmplen + 1 + proglen + sizeof(suffix),
-               return tmpfile());
-
-       memcpy(fname, tmpdir, tmplen);
-       fname[tmplen] = G_DIR_SEPARATOR;
-       memcpy(fname + tmplen + 1, progname, proglen);
-       memcpy(fname + tmplen + 1 + proglen, suffix, sizeof(suffix));
-
-       fd = g_mkstemp(fname);
-       if (fd < 0)
-               return tmpfile();
-
-#ifndef G_OS_WIN32
-       claws_unlink(fname);
-       
-       /* verify that we can write in the file after unlinking */
-       if (write(fd, buf, 1) < 0) {
-               close(fd);
-               return tmpfile();
-       }
-       
-#endif
-
-       fp = fdopen(fd, "w+b");
-       if (!fp)
-               close(fd);
-       else {
-               rewind(fp);
-               return fp;
-       }
-
-       return tmpfile();
-}
-
-FILE *get_tmpfile_in_dir(const gchar *dir, gchar **filename)
-{
-       int fd;
-       *filename = g_strdup_printf("%s%cclaws.XXXXXX", dir, G_DIR_SEPARATOR);
-       fd = g_mkstemp(*filename);
-       if (fd < 0)
-               return NULL;
-       return fdopen(fd, "w+");
-}
-
-FILE *str_open_as_stream(const gchar *str)
-{
-       FILE *fp;
-       size_t len;
-
-       cm_return_val_if_fail(str != NULL, NULL);
-
-       fp = my_tmpfile();
-       if (!fp) {
-               FILE_OP_ERROR("str_open_as_stream", "my_tmpfile");
-               return NULL;
-       }
-
-       len = strlen(str);
-       if (len == 0) return fp;
-
-       if (fwrite(str, 1, len, fp) != len) {
-               FILE_OP_ERROR("str_open_as_stream", "fwrite");
-               fclose(fp);
-               return NULL;
-       }
-
-       rewind(fp);
-       return fp;
-}
-
-gint str_write_to_file(const gchar *str, const gchar *file)
-{
-       FILE *fp;
-       size_t len;
-
-       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");
-               return -1;
-       }
-
-       len = strlen(str);
-       if (len == 0) {
-               fclose(fp);
-               return 0;
-       }
-
-       if (fwrite(str, 1, len, fp) != len) {
-               FILE_OP_ERROR(file, "fwrite");
-               fclose(fp);
-               claws_unlink(file);
-               return -1;
-       }
-
-       if (fclose(fp) == EOF) {
-               FILE_OP_ERROR(file, "fclose");
-               claws_unlink(file);
-               return -1;
-       }
-
-       return 0;
-}
-
-static gchar *file_read_stream_to_str_full(FILE *fp, gboolean recode)
-{
-       GByteArray *array;
-       guchar buf[BUFSIZ];
-       gint n_read;
-       gchar *str;
-
-       cm_return_val_if_fail(fp != NULL, NULL);
-
-       array = g_byte_array_new();
-
-       while ((n_read = fread(buf, sizeof(gchar), sizeof(buf), fp)) > 0) {
-               if (n_read < sizeof(buf) && ferror(fp))
-                       break;
-               g_byte_array_append(array, buf, n_read);
-       }
-
-       if (ferror(fp)) {
-               FILE_OP_ERROR("file stream", "fread");
-               g_byte_array_free(array, TRUE);
-               return NULL;
-       }
-
-       buf[0] = '\0';
-       g_byte_array_append(array, buf, 1);
-       str = (gchar *)array->data;
-       g_byte_array_free(array, FALSE);
-
-       if (recode && !g_utf8_validate(str, -1, NULL)) {
-               const gchar *src_codeset, *dest_codeset;
-               gchar *tmp = NULL;
-               src_codeset = conv_get_locale_charset_str();
-               dest_codeset = CS_UTF_8;
-               tmp = conv_codeset_strdup(str, src_codeset, dest_codeset);
-               g_free(str);
-               str = tmp;
-       }
-
-       return str;
-}
-
-static gchar *file_read_to_str_full(const gchar *file, gboolean recode)
-{
-       FILE *fp;
-       gchar *str;
-       GStatBuf s;
-#ifndef G_OS_WIN32
-       gint fd, err;
-       struct timeval timeout = {1, 0};
-       fd_set fds;
-       int fflags = 0;
-#endif
-
-       cm_return_val_if_fail(file != NULL, NULL);
-
-       if (g_stat(file, &s) != 0) {
-               FILE_OP_ERROR(file, "stat");
-               return NULL;
-       }
-       if (S_ISDIR(s.st_mode)) {
-               g_warning("%s: is a directory", file);
-               return NULL;
-       }
-
-#ifdef G_OS_WIN32
-       fp = g_fopen (file, "rb");
-       if (fp == NULL) {
-               FILE_OP_ERROR(file, "open");
-               return NULL;
-       }
-#else    
-       /* test whether the file is readable without blocking */
-       fd = g_open(file, O_RDONLY | O_NONBLOCK, 0);
-       if (fd == -1) {
-               FILE_OP_ERROR(file, "open");
-               return NULL;
-       }
-
-       FD_ZERO(&fds);
-       FD_SET(fd, &fds);
-
-       /* allow for one second */
-       err = select(fd+1, &fds, NULL, NULL, &timeout);
-       if (err <= 0 || !FD_ISSET(fd, &fds)) {
-               if (err < 0) {
-                       FILE_OP_ERROR(file, "select");
-               } else {
-                       g_warning("%s: doesn't seem readable", file);
-               }
-               close(fd);
-               return NULL;
-       }
-       
-       /* Now clear O_NONBLOCK */
-       if ((fflags = fcntl(fd, F_GETFL)) < 0) {
-               FILE_OP_ERROR(file, "fcntl (F_GETFL)");
-               close(fd);
-               return NULL;
-       }
-       if (fcntl(fd, F_SETFL, (fflags & ~O_NONBLOCK)) < 0) {
-               FILE_OP_ERROR(file, "fcntl (F_SETFL)");
-               close(fd);
-               return NULL;
-       }
-       
-       /* get the FILE pointer */
-       fp = fdopen(fd, "rb");
-
-       if (fp == NULL) {
-               FILE_OP_ERROR(file, "fdopen");
-               close(fd); /* if fp isn't NULL, we'll use fclose instead! */
-               return NULL;
-       }
-#endif
-
-       str = file_read_stream_to_str_full(fp, recode);
-
-       fclose(fp);
-
-       return str;
-}
-
-gchar *file_read_to_str(const gchar *file)
-{
-       return file_read_to_str_full(file, TRUE);
-}
-gchar *file_read_stream_to_str(FILE *fp)
-{
-       return file_read_stream_to_str_full(fp, TRUE);
-}
-
-gchar *file_read_to_str_no_recode(const gchar *file)
-{
-       return file_read_to_str_full(file, FALSE);
-}
-gchar *file_read_stream_to_str_no_recode(FILE *fp)
-{
-       return file_read_stream_to_str_full(fp, FALSE);
-}
-
 char *fgets_crlf(char *buf, int size, FILE *stream)
 {
        gboolean is_cr = FALSE;
@@ -3216,7 +2521,7 @@ char *fgets_crlf(char *buf, int size, FILE *stream)
 
        *cs = '\0';
 
-       return buf;     
+       return buf;
 }
 
 static gint execute_async(gchar *const argv[], const gchar *working_directory)
@@ -3468,7 +2773,7 @@ time_t tzoffset_sec(time_t *now)
 #ifdef G_OS_WIN32
        if (now && *now < 0)
                return 0;
-#endif 
+#endif
        gmt = *gmtime_r(now, &buf1);
        lt = localtime_r(now, &buf2);
 
@@ -4108,9 +3413,10 @@ gboolean get_uri_part(const gchar *start, const gchar *scanpos,
        *bp = scanpos;
 
        /* find end point of URI */
-       for (ep_ = scanpos; *ep_ != '\0'; ep_++) {
-               if (!g_ascii_isgraph(*(const guchar *)ep_) ||
-                   !IS_ASCII(*(const guchar *)ep_) ||
+       for (ep_ = scanpos; *ep_ != '\0'; ep_ = g_utf8_next_char(ep_)) {
+               gunichar u = g_utf8_get_char_validated(ep_, -1);
+               if (!g_unichar_isgraph(u) ||
+                   u == (gunichar)-1 ||
                    strchr("[]{}<>\"", *ep_)) {
                        break;
                } else if (strchr("(", *ep_)) {
@@ -4230,7 +3536,7 @@ search_again:
                        start++;
 
                *bp = start;
-               
+
                /* check if there are quotes (to skip , in them) */
                if (*start == '"') {
                        start_quote = start;
@@ -4240,12 +3546,12 @@ search_again:
                        start_quote = NULL;
                        end_quote = NULL;
                }
-               
+
                /* skip anything between quotes */
                if (start_quote && end_quote) {
                        start = end_quote;
-                       
-               } 
+
+               }
 
                /* find end (either , or ; or end of line) */
                if (strstr(start, ",") && strstr(start, ";"))
@@ -4469,12 +3775,12 @@ gchar *make_http_string(const gchar *bp, const gchar *ep)
 
 static gchar *mailcap_get_command_in_file(const gchar *path, const gchar *type, const gchar *file_to_open)
 {
-       FILE *fp = g_fopen(path, "rb");
+       FILE *fp = claws_fopen(path, "rb");
        gchar buf[BUFFSIZE];
        gchar *result = NULL;
        if (!fp)
                return NULL;
-       while (fgets(buf, sizeof (buf), fp) != NULL) {
+       while (claws_fgets(buf, sizeof (buf), fp) != NULL) {
                gchar **parts = g_strsplit(buf, ";", 3);
                gchar *trimmed = parts[0];
                while (trimmed[0] == ' ' || trimmed[0] == '\t')
@@ -4500,13 +3806,13 @@ static gchar *mailcap_get_command_in_file(const gchar *path, const gchar *type,
                                        testcmd[strlen(testcmd)-1] = '\0';
                                while (testcmd[strlen(testcmd)-1] == ' ' || testcmd[strlen(testcmd)-1] == '\t')
                                        testcmd[strlen(testcmd)-1] = '\0';
-                                       
+
                                if (strstr(testcmd, "%s")) {
                                        gchar *tmp = g_strdup_printf(testcmd, file_to_open);
                                        gint res = system(tmp);
                                        g_free(tmp);
                                        g_free(orig_testcmd);
-                                       
+
                                        if (res != 0) {
                                                g_strfreev(parts);
                                                continue;
@@ -4514,14 +3820,14 @@ static gchar *mailcap_get_command_in_file(const gchar *path, const gchar *type,
                                } else {
                                        gint res = system(testcmd);
                                        g_free(orig_testcmd);
-                                       
+
                                        if (res != 0) {
                                                g_strfreev(parts);
                                                continue;
                                        }
                                }
                        }
-                       
+
                        trimmed = parts[1];
                        while (trimmed[0] == ' ' || trimmed[0] == '\t')
                                trimmed++;
@@ -4533,7 +3839,7 @@ static gchar *mailcap_get_command_in_file(const gchar *path, const gchar *type,
                                trimmed[strlen(trimmed)-1] = '\0';
                        result = g_strdup(trimmed);
                        g_strfreev(parts);
-                       fclose(fp);
+                       claws_fclose(fp);
                        if (needsterminal) {
                                gchar *tmp = g_strdup_printf("xterm -e %s", result);
                                g_free(result);
@@ -4543,7 +3849,7 @@ static gchar *mailcap_get_command_in_file(const gchar *path, const gchar *type,
                }
                g_strfreev(parts);
        }
-       fclose(fp);
+       claws_fclose(fp);
        return NULL;
 }
 gchar *mailcap_get_command_for_type(const gchar *type, const gchar *file_to_open)
@@ -4566,13 +3872,13 @@ void mailcap_update_default(const gchar *type, const gchar *command)
        gchar *path = NULL, *outpath = NULL;
        path = g_strconcat(get_home_dir(), G_DIR_SEPARATOR_S, ".mailcap", NULL);
        outpath = g_strconcat(get_home_dir(), G_DIR_SEPARATOR_S, ".mailcap.new", NULL);
-       FILE *fp = g_fopen(path, "rb");
+       FILE *fp = claws_fopen(path, "rb");
        FILE *outfp = NULL;
        gchar buf[BUFFSIZE];
        gboolean err = FALSE;
 
        if (!fp) {
-               fp = g_fopen(path, "a");
+               fp = claws_fopen(path, "a");
                if (!fp) {
                        g_warning("failed to create file %s", path);
                        g_free(path);
@@ -4588,15 +3894,15 @@ void mailcap_update_default(const gchar *type, const gchar *command)
                }
        }
 
-       outfp = g_fopen(outpath, "wb");
+       outfp = claws_fopen(outpath, "wb");
        if (!outfp) {
                g_warning("failed to create file %s", outpath);
                g_free(path);
                g_free(outpath);
-               fclose(fp);
+               claws_fclose(fp);
                return;
        }
-       while (fp && fgets(buf, sizeof (buf), fp) != NULL) {
+       while (fp && claws_fgets(buf, sizeof (buf), fp) != NULL) {
                gchar **parts = g_strsplit(buf, ";", 3);
                gchar *trimmed = parts[0];
                while (trimmed[0] == ' ')
@@ -4609,7 +3915,7 @@ void mailcap_update_default(const gchar *type, const gchar *command)
                        continue;
                }
                else {
-                       if(fputs(buf, outfp) == EOF) {
+                       if(claws_fputs(buf, outfp) == EOF) {
                                err = TRUE;
                                break;
                        }
@@ -4620,11 +3926,11 @@ void mailcap_update_default(const gchar *type, const gchar *command)
                err = TRUE;
 
        if (fp)
-               fclose(fp);
+               claws_fclose(fp);
 
-       if (fclose(outfp) == EOF)
+       if (claws_safe_fclose(outfp) == EOF)
                err = TRUE;
-               
+
        if (!err)
                g_rename(outpath, path);
 
@@ -4632,60 +3938,6 @@ void mailcap_update_default(const gchar *type, const gchar *command)
        g_free(outpath);
 }
 
-gint copy_dir(const gchar *src, const gchar *dst)
-{
-       GDir *dir;
-       const gchar *name;
-
-       if ((dir = g_dir_open(src, 0, NULL)) == NULL) {
-               g_warning("failed to open directory: %s", src);
-               return -1;
-       }
-
-       if (make_dir(dst) < 0)
-               return -1;
-
-       while ((name = g_dir_read_name(dir)) != NULL) {
-               gchar *old_file, *new_file;
-               old_file = g_strconcat(src, G_DIR_SEPARATOR_S, name, NULL);
-               new_file = g_strconcat(dst, G_DIR_SEPARATOR_S, name, NULL);
-               debug_print("copying: %s -> %s\n", old_file, new_file);
-               if (g_file_test(old_file, G_FILE_TEST_IS_REGULAR)) {
-                       gint r = copy_file(old_file, new_file, TRUE);
-                       if (r < 0) {
-                               g_dir_close(dir);
-                               return r;
-                       }
-                }
-#ifndef G_OS_WIN32
-                /* Windows has no symlinks.  Or well, Vista seems to
-                   have something like this but the semantics might be
-                   different.  Thus we don't use it under Windows. */
-                else if (g_file_test(old_file, G_FILE_TEST_IS_SYMLINK)) {
-                       GError *error = NULL;
-                       gint r = 0;
-                       gchar *target = g_file_read_link(old_file, &error);
-                       if (target)
-                               r = symlink(target, new_file);
-                       g_free(target);
-                       if (r < 0) {
-                               g_dir_close(dir);
-                               return r;
-                       }
-                 }
-#endif /*G_OS_WIN32*/
-               else if (g_file_test(old_file, G_FILE_TEST_IS_DIR)) {
-                       gint r = copy_dir(old_file, new_file);
-                       if (r < 0) {
-                               g_dir_close(dir);
-                               return r;
-                       }
-               }
-       }
-       g_dir_close(dir);
-       return 0;
-}
-
 /* crude test to see if a file is an email. */
 gboolean file_is_email (const gchar *filename)
 {
@@ -4695,10 +3947,10 @@ gboolean file_is_email (const gchar *filename)
        gint score = 0;
        if (filename == NULL)
                return FALSE;
-       if ((fp = g_fopen(filename, "rb")) == NULL)
+       if ((fp = claws_fopen(filename, "rb")) == NULL)
                return FALSE;
        while (i < 60 && score < 3
-              && fgets(buffer, sizeof (buffer), fp) != NULL) {
+              && claws_fgets(buffer, sizeof (buffer), fp) != NULL) {
                if (!strncmp(buffer, "From:", strlen("From:")))
                        score++;
                else if (!strncmp(buffer, "Date:", strlen("Date:")))
@@ -4709,7 +3961,7 @@ gboolean file_is_email (const gchar *filename)
                        score++;
                i++;
        }
-       fclose(fp);
+       claws_fclose(fp);
        return (score >= 3);
 }
 
@@ -4736,10 +3988,10 @@ gboolean sc_g_slist_bigger(GSList *list, gint max)
 }
 
 const gchar *daynames[] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL};
-const gchar *monthnames[] = {NULL, NULL, NULL, NULL, NULL, NULL, 
+const gchar *monthnames[] = {NULL, NULL, NULL, NULL, NULL, NULL,
                             NULL, NULL, NULL, NULL, NULL, NULL};
 const gchar *s_daynames[] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL};
-const gchar *s_monthnames[] = {NULL, NULL, NULL, NULL, NULL, NULL, 
+const gchar *s_monthnames[] = {NULL, NULL, NULL, NULL, NULL, NULL,
                             NULL, NULL, NULL, NULL, NULL, NULL};
 
 gint daynames_len[] =     {0,0,0,0,0,0,0};
@@ -4792,7 +4044,7 @@ static void init_time_names(void)
        s_daynames[4] = C_("Abbr. day name for use by strftime", "Thu");
        s_daynames[5] = C_("Abbr. day name for use by strftime", "Fri");
        s_daynames[6] = C_("Abbr. day name for use by strftime", "Sat");
-       
+
        s_monthnames[0] = C_("Abbr. month name for use by strftime", "Jan");
        s_monthnames[1] = C_("Abbr. month name for use by strftime", "Feb");
        s_monthnames[2] = C_("Abbr. month name for use by strftime", "Mar");
@@ -4819,7 +4071,7 @@ static void init_time_names(void)
        s_pm_up = C_("For use by strftime (afternoon)", "PM");
        s_am_low = C_("For use by strftime (morning, lowercase)", "am");
        s_pm_low = C_("For use by strftime (afternoon, lowercase)", "pm");
-       
+
        s_am_up_len = strlen(s_am_up);
        s_pm_up_len = strlen(s_pm_up);
        s_am_low_len = strlen(s_am_low);
@@ -4842,13 +4094,13 @@ size_t fast_strftime(gchar *buf, gint buflen, const gchar *format, struct tm *lt
        gint total_done = 0;
        gchar subbuf[64], subfmt[64];
        static time_t last_tzset = (time_t)0;
-       
+
        if (!time_names_init_done)
                init_time_names();
-       
+
        if (format == NULL || lt == NULL)
                return 0;
-               
+
        if (last_tzset != time(NULL)) {
                tzset();
                last_tzset = time(NULL);
@@ -4913,7 +4165,7 @@ size_t fast_strftime(gchar *buf, gint buflen, const gchar *format, struct tm *lt
                                break;
                        case 'F':
                                len = 10; CHECK_SIZE();
-                               snprintf(curpos, buflen - total_done, "%4d-%02d-%02d", 
+                               snprintf(curpos, buflen - total_done, "%4d-%02d-%02d",
                                        lt->tm_year + 1900, lt->tm_mon +1, lt->tm_mday);
                                break;
                        case 'H':
@@ -4982,7 +4234,11 @@ size_t fast_strftime(gchar *buf, gint buflen, const gchar *format, struct tm *lt
                                }
                                break;
                        case 'r':
+#ifdef G_OS_WIN32
+                               strftime(subbuf, 64, "%I:%M:%S %p", lt);
+#else
                                strftime(subbuf, 64, "%r", lt);
+#endif
                                len = strlen(subbuf); CHECK_SIZE();
                                strncpy2(curpos, subbuf, buflen - total_done);
                                break;
@@ -5079,56 +4335,17 @@ size_t fast_strftime(gchar *buf, gint buflen, const gchar *format, struct tm *lt
                        format++;
                } else {
                        int len = 1; CHECK_SIZE();
-                       *curpos++ = *format++; 
+                       *curpos++ = *format++;
                }
        }
        *curpos = '\0';
        return total_done;
 }
 
-gboolean prefs_common_get_use_shred(void);
-
-
 #ifdef G_OS_WIN32
 #define WEXITSTATUS(x) (x)
 #endif
 
-int claws_unlink(const gchar *filename) 
-{
-       GStatBuf s;
-       static int found_shred = -1;
-       static const gchar *args[4];
-
-       if (filename == NULL)
-               return 0;
-
-       if (prefs_common_get_use_shred()) {
-               if (found_shred == -1) {
-                       /* init */
-                       args[0] = g_find_program_in_path("shred");
-                       debug_print("found shred: %s\n", args[0]);
-                       found_shred = (args[0] != NULL) ? 1:0;
-                       args[1] = "-f";
-                       args[3] = NULL;
-               }
-               if (found_shred == 1) {
-                       if (g_stat(filename, &s) == 0 && S_ISREG(s.st_mode)) {
-                               if (s.st_nlink == 1) {
-                                       gint status=0;
-                                       args[2] = filename;
-                                       g_spawn_sync(NULL, (gchar **)args, NULL, 0,
-                                        NULL, NULL, NULL, NULL, &status, NULL);
-                                       debug_print("%s %s exited with status %d\n",
-                                               args[0], filename, WEXITSTATUS(status));
-                                       if (truncate(filename, 0) < 0)
-                                               g_warning("couln't truncate: %s", filename);
-                               }
-                       }
-               }
-       }
-       return g_unlink(filename);
-}
-
 GMutex *cm_mutex_new(void) {
 #if GLIB_CHECK_VERSION(2,32,0)
        GMutex *m = g_new0(GMutex, 1);
@@ -5219,7 +4436,7 @@ static GSList *cm_split_path(const gchar *filename, int depth)
                                return NULL;
                        }
                        else /* Remove the last inserted element */
-                               canonical_parts = 
+                               canonical_parts =
                                        g_slist_delete_link(canonical_parts,
                                                            canonical_parts);
                } else {
@@ -5252,7 +4469,7 @@ static GSList *cm_split_path(const gchar *filename, int depth)
 
                                if (!g_path_is_absolute(target)) {
                                        /* remove the last inserted element */
-                                       canonical_parts = 
+                                       canonical_parts =
                                                g_slist_delete_link(canonical_parts,
                                                            canonical_parts);
                                        /* add the target */
@@ -5306,7 +4523,7 @@ int cm_canonicalize_filename(const gchar *filename, gchar **canonical_name) {
                gchar *cur = g_get_current_dir();
                gchar *absolute_filename = g_strconcat(cur, G_DIR_SEPARATOR_S,
                                                       filename, NULL);
-               
+
                canonical_parts = cm_split_path(absolute_filename, 0);
                g_free(absolute_filename);
                g_free(cur);
@@ -5330,7 +4547,7 @@ guchar *g_base64_decode_zero(const gchar *text, gsize *out_len)
        g_free(tmp);
 
        if (strlen(out) != *out_len) {
-               g_warning ("strlen(out) %zd != *out_len %" G_GSIZE_FORMAT, strlen(out), *out_len);
+               g_warning ("strlen(out) %"G_GSIZE_FORMAT" != *out_len %"G_GSIZE_FORMAT, strlen(out), *out_len);
        }
 
        return out;
@@ -5400,7 +4617,7 @@ get_random_bytes(void *buf, size_t count)
        /* Read data from the source into buf. */
 #if defined G_OS_WIN32
        if (!CryptGenRandom(rnd, count, buf)) {
-               debug_print("Could not read %zd random bytes.\n", count);
+               debug_print("Could not read %"G_GSIZE_FORMAT" random bytes.\n", count);
                CryptReleaseContext(rnd, 0);
                return FALSE;
        }
@@ -5423,3 +4640,70 @@ get_random_bytes(void *buf, size_t count)
 
        return TRUE;
 }
+
+/* returns FALSE if parsing failed, otherwise returns TRUE and sets *server, *port
+   and eventually *fp from filename (if not NULL, they must be free'd by caller after
+   user.
+   filenames we expect: 'host.name.port.cert' or 'host.name.port.f:i:n:g:e:r:p:r:i:n:t.cert' */
+gboolean get_serverportfp_from_filename(const gchar *str, gchar **server, gchar **port, gchar **fp)
+{
+       const gchar *pos, *dotport_pos = NULL, *dotcert_pos = NULL, *dotfp_pos = NULL;
+
+       g_return_val_if_fail(str != NULL, FALSE);
+
+       pos = str + strlen(str) - 1;
+       while ((pos > str) && !dotport_pos) {
+               if (*pos == '.') {
+                       if (!dotcert_pos) {
+                               /* match the .cert suffix */
+                               if (strcmp(pos, ".cert") == 0) {
+                                       dotcert_pos = pos;
+                               }
+                       } else {
+                               if (!dotfp_pos) {
+                                       /* match an eventual fingerprint */
+                                       /* or the port number */
+                                       if (strncmp(pos + 3, ":", 1) == 0) {
+                                               dotfp_pos = pos;
+                                       } else {
+                                               dotport_pos = pos;
+                                       }
+                               } else {
+                                       /* match the port number */
+                                       dotport_pos = pos;
+                               }
+                       }
+               }
+               pos--;
+       }
+       if (!dotport_pos || !dotcert_pos) {
+               g_warning("could not parse filename %s", str);
+               return FALSE;
+       }
+
+       if (server != NULL)
+               *server = g_strndup(str, dotport_pos - str);
+       if (dotfp_pos) {
+               if (port != NULL)
+                       *port = g_strndup(dotport_pos + 1, dotfp_pos - dotport_pos - 1);
+               if (fp != NULL)
+                       *fp = g_strndup(dotfp_pos + 1, dotcert_pos - dotfp_pos - 1);
+       } else {
+               if (port != NULL)
+                       *port = g_strndup(dotport_pos + 1, dotcert_pos - dotport_pos - 1);
+               if (fp != NULL)
+                       *fp = NULL;
+       }
+
+       debug_print("filename='%s' => server='%s' port='%s' fp='%s'\n",
+                       str,
+                       (server ? *server : "(n/a)"),
+                       (port ? *port : "(n/a)"),
+                       (fp ? *fp : "(n/a)"));
+
+       if (!(server && *server) || !(port && *port))
+               return FALSE;
+       else
+               return TRUE;
+}
+