2008-09-22 [colin] 3.5.0cvs122
[claws.git] / src / common / utils.c
index 5099be405160815495b15a777b6afccedfe5e3ac..2c500dc1024953d2bf785d8ea4dbb30400cfc053 100644 (file)
 #include <sys/utsname.h>
 #endif
 
+#include <fcntl.h>
+
 #ifdef G_OS_WIN32
 #  include <direct.h>
 #  include <io.h>
-#  include <fcntl.h>
 #  include <w32lib.h>
 #endif
 
@@ -183,11 +184,23 @@ gint g_chmod(const gchar *path, gint mode)
        return chmod(path, mode);
 #endif
 }
+
+FILE* g_fopen(const gchar *filename, const gchar *mode)
+{
+#ifdef G_OS_WIN32
+       char *name = g_win32_locale_filename_from_utf8(filename);
+       FILE* fp = fopen(name, mode);
+       g_free(name);
+       return fp;
+#else
+       return fopen(filename, mode);
+#endif
+}
 #endif /* GLIB_CHECK_VERSION && G_OS_UNIX */
 
 
 #ifdef G_OS_WIN32
-gint mkstemp_name(const gchar *template, gchar **name_used)
+gint mkstemp_name(gchar *template, gchar **name_used)
 {
        static gulong count=0; /* W32-_mktemp only supports up to 27
                                  tempfiles... */
@@ -208,7 +221,7 @@ gint mkstemp_name(const gchar *template, gchar **name_used)
 #endif /* G_OS_WIN32 */
 
 #ifdef G_OS_WIN32
-gint mkstemp(const gchar *template)
+gint mkstemp(gchar *template)
 {
        gchar *dummyname;
        gint res = mkstemp_name(template, &dummyname);
@@ -322,7 +335,7 @@ gchar *itos(gint n)
        d = (d*100) >> divisor;         \
 }
 
-gchar *to_human_readable(size_t size)
+gchar *to_human_readable(goffset size)
 {
        static gchar str[14];
        static gchar *b_format = NULL, *kb_format = NULL, 
@@ -334,20 +347,20 @@ gchar *to_human_readable(size_t size)
                mb_format = _("%d.%02dMB");
                gb_format = _("%.2fGB");
        }
-
-       if (size < (size_t)1024) {
+       
+       if (size < (goffset)1024) {
                g_snprintf(str, sizeof(str), b_format, (gint)size);
                return str;
-       } else if (size >> 10 < (size_t)1024) {
+       } else if (size >> 10 < (goffset)1024) {
                divide(size, 10, t, r);
                g_snprintf(str, sizeof(str), kb_format, t, r);
                return str;
-       } else if (size >> 20 < (size_t)1024) {
+       } else if (size >> 20 < (goffset)1024) {
                divide(size, 20, t, r);
                g_snprintf(str, sizeof(str), mb_format, t, r);
                return str;
        } else {
-               g_snprintf(str, sizeof(str), gb_format, (gfloat)(size) / (1 << 30));
+               g_snprintf(str, sizeof(str), gb_format, (gfloat)(size >> 30));
                return str;
        }
 }
@@ -483,6 +496,7 @@ gint file_strip_crs(const gchar *file)
        if (rename_force(out, file) < 0)
                goto unlinkout;
        
+       g_free(out);
        return 0;
 unlinkout:
        claws_unlink(out);
@@ -1619,7 +1633,6 @@ gint scan_mailto_url(const gchar *mailto, gchar **from, gchar **to, gchar **cc,
                        if (tmp) {
                                /* attach is correct */
                                num_attach++;
-                               printf("realloc my_att %d\n", (num_attach+1));
                                my_att = g_realloc(my_att, (sizeof(char *))*(num_attach+1));
                                my_att[num_attach-1] = tmp;
                                my_att[num_attach] = NULL;
@@ -2924,7 +2937,9 @@ FILE *my_tmpfile(void)
        gchar *fname;
        gint fd;
        FILE *fp;
+#ifndef G_OS_WIN32
        gchar buf[2]="\0";
+#endif
 
        tmpdir = get_tmp_dir();
        tmplen = strlen(tmpdir);
@@ -3089,14 +3104,76 @@ static gchar *file_read_to_str_full(const gchar *file, gboolean recode)
 {
        FILE *fp;
        gchar *str;
+       struct stat s;
+#ifndef G_OS_WIN32
+       gint fd, err;
+       struct timeval timeout = {1, 0};
+       fd_set fds;
+       int fflags = 0;
+#endif
 
        g_return_val_if_fail(file != NULL, NULL);
 
-       if ((fp = g_fopen(file, "rb")) == NULL) {
-               FILE_OP_ERROR(file, "fopen");
+       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\n", file);
+               return NULL;
+       }
+
+#ifdef G_OS_WIN32
+       fp = fopen (file, "rb");
+       if (fp == NULL) {
+               FILE_OP_ERROR(file, "open");
+               return NULL;
+       }
+#else    
+       /* test whether the file is readable without blocking */
+       fd = open(file, O_RDONLY | O_NONBLOCK);
+       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\n", 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);
@@ -3390,7 +3467,9 @@ time_t tzoffset_sec(time_t *now)
 {
        struct tm gmt, *lt;
        gint off;
+#ifndef G_OS_WIN32
        struct tm buf1, buf2;
+#endif
        
        gmt = *gmtime_r(now, &buf1);
        lt = localtime_r(now, &buf2);
@@ -3421,7 +3500,9 @@ gchar *tzoffset(time_t *now)
        struct tm gmt, *lt;
        gint off;
        gchar sign = '+';
+#ifndef G_OS_WIN32
        struct tm buf1, buf2;
+#endif
 
        gmt = *gmtime_r(now, &buf1);
        lt = localtime_r(now, &buf2);
@@ -3456,8 +3537,10 @@ void get_rfc822_date(gchar *buf, gint len)
        time_t t;
        gchar day[4], mon[4];
        gint dd, hh, mm, ss, yyyy;
+#ifndef G_OS_WIN32
        struct tm buf1;
        gchar buf2[BUFFSIZE];
+#endif
 
        t = time(NULL);
        lt = localtime_r(&t, &buf1);
@@ -3562,6 +3645,7 @@ int subject_get_prefix_length(const gchar *subject)
                "Antwort\\:",                   /* "Antwort:" (German Lotus Notes) */
                "Res\\:",                       /* "Res:" (Brazilian Outlook) */
                "Fw\\:",                        /* "Fw:" Forward */
+               "Fwd\\:",                       /* "Fwd:" Forward */
                "Enc\\:",                       /* "Enc:" Forward (Brazilian Outlook) */
                "Odp\\:",                       /* "Odp:" Re (Polish Outlook) */
                "Rif\\:",                       /* "Rif:" (Italian Outlook) */
@@ -3642,7 +3726,9 @@ gchar *generate_msgid(gchar *buf, gint len)
        struct tm *lt;
        time_t t;
        gchar *addr;
+#ifndef G_OS_WIN32
        struct tm buft;
+#endif
 
        t = time(NULL);
        lt = localtime_r(&t, &buft);
@@ -4684,10 +4770,23 @@ const gchar *monthnames[] = {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, 
                             NULL, NULL, NULL, NULL, NULL, NULL};
+
+gint daynames_len[] =     {0,0,0,0,0,0,0};
+gint monthnames_len[] =   {0,0,0,0,0,0,
+                                0,0,0,0,0,0};
+gint s_daynames_len[] =   {0,0,0,0,0,0,0};
+gint s_monthnames_len[] = {0,0,0,0,0,0,
+                                0,0,0,0,0,0};
 const gchar *s_am_up = NULL;
 const gchar *s_pm_up = NULL;
 const gchar *s_am_low = NULL;
 const gchar *s_pm_low = NULL;
+
+gint s_am_up_len = 0;
+gint s_pm_up_len = 0;
+gint s_am_low_len = 0;
+gint s_pm_low_len = 0;
+
 const gchar *def_loc_format = NULL;
 const gchar *date_loc_format = NULL;
 const gchar *time_loc_format = NULL;
@@ -4697,6 +4796,8 @@ static gboolean time_names_init_done = FALSE;
 
 static void init_time_names(void)
 {
+       int i = 0;
+
        daynames[0] = Q_("Complete day name for use by strftime|Sunday");
        daynames[1] = Q_("Complete day name for use by strftime|Monday");
        daynames[2] = Q_("Complete day name for use by strftime|Tuesday");
@@ -4704,7 +4805,7 @@ static void init_time_names(void)
        daynames[4] = Q_("Complete day name for use by strftime|Thursday");
        daynames[5] = Q_("Complete day name for use by strftime|Friday");
        daynames[6] = Q_("Complete day name for use by strftime|Saturday");
-       
+
        monthnames[0] = Q_("Complete month name for use by strftime|January");
        monthnames[1] = Q_("Complete month name for use by strftime|February");
        monthnames[2] = Q_("Complete month name for use by strftime|March");
@@ -4739,11 +4840,25 @@ static void init_time_names(void)
        s_monthnames[10] = Q_("Abbr. month name for use by strftime|Nov");
        s_monthnames[11] = Q_("Abbr. month name for use by strftime|Dec");
 
+       for (i = 0; i < 7; i++) {
+               daynames_len[i] = strlen(daynames[i]);
+               s_daynames_len[i] = strlen(s_daynames[i]);
+       }
+       for (i = 0; i < 12; i++) {
+               monthnames_len[i] = strlen(monthnames[i]);
+               s_monthnames_len[i] = strlen(s_monthnames[i]);
+       }
+
        s_am_up = Q_("For use by strftime (morning)|AM");
        s_pm_up = Q_("For use by strftime (afternoon)|PM");
        s_am_low = Q_("For use by strftime (morning, lowercase)|am");
        s_pm_low = Q_("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);
+       s_pm_low_len = strlen(s_pm_low);
+       
        def_loc_format = Q_("For use by strftime (default date+time format)|%a %b %e %H:%M:%S %Y");
        date_loc_format = Q_("For use by strftime (default date format)|%m/%d/%y");
        time_loc_format = Q_("For use by strftime (default time format)|%H:%M:%S");
@@ -4788,20 +4903,20 @@ size_t fast_strftime(gchar *buf, gint buflen, const gchar *format, struct tm *lt
                                *curpos = '%';
                                break;
                        case 'a':
-                               len = strlen(s_daynames[lt->tm_wday]); CHECK_SIZE();
+                               len = s_daynames_len[lt->tm_wday]; CHECK_SIZE();
                                strncpy2(curpos, s_daynames[lt->tm_wday], buflen - total_done);
                                break;
                        case 'A':
-                               len = strlen(daynames[lt->tm_wday]); CHECK_SIZE();
+                               len = daynames_len[lt->tm_wday]; CHECK_SIZE();
                                strncpy2(curpos, daynames[lt->tm_wday], buflen - total_done);
                                break;
                        case 'b':
                        case 'h':
-                               len = strlen(s_monthnames[lt->tm_mon]); CHECK_SIZE();
+                               len = s_monthnames_len[lt->tm_mon]; CHECK_SIZE();
                                strncpy2(curpos, s_monthnames[lt->tm_mon], buflen - total_done);
                                break;
                        case 'B':
-                               len = strlen(monthnames[lt->tm_mon]); CHECK_SIZE();
+                               len = monthnames_len[lt->tm_mon]; CHECK_SIZE();
                                strncpy2(curpos, monthnames[lt->tm_mon], buflen - total_done);
                                break;
                        case 'c':
@@ -4890,20 +5005,20 @@ size_t fast_strftime(gchar *buf, gint buflen, const gchar *format, struct tm *lt
                                break;
                        case 'p':
                                if (lt->tm_hour >= 12) {
-                                       len = strlen(s_pm_up); CHECK_SIZE();
-                                       snprintf(curpos, buflen-total_done, s_pm_up);
+                                       len = s_pm_up_len; CHECK_SIZE();
+                                       snprintf(curpos, buflen-total_done, "%s", s_pm_up);
                                } else {
-                                       len = strlen(s_am_up); CHECK_SIZE();
-                                       snprintf(curpos, buflen-total_done, s_am_up);
+                                       len = s_am_up_len; CHECK_SIZE();
+                                       snprintf(curpos, buflen-total_done, "%s", s_am_up);
                                }
                                break;
                        case 'P':
                                if (lt->tm_hour >= 12) {
-                                       len = strlen(s_pm_low); CHECK_SIZE();
-                                       snprintf(curpos, buflen-total_done, s_pm_low);
+                                       len = s_pm_low_len; CHECK_SIZE();
+                                       snprintf(curpos, buflen-total_done, "%s", s_pm_low);
                                } else {
-                                       len = strlen(s_am_low); CHECK_SIZE();
-                                       snprintf(curpos, buflen-total_done, s_am_low);
+                                       len = s_am_low_len; CHECK_SIZE();
+                                       snprintf(curpos, buflen-total_done, "%s", s_am_low);
                                }
                                break;
                        case 'r':
@@ -4920,7 +5035,7 @@ size_t fast_strftime(gchar *buf, gint buflen, const gchar *format, struct tm *lt
                                *curpos++ = '0'+(lt->tm_min % 10);
                                break;
                        case 's':
-                               snprintf(subbuf, buflen - total_done, "%ld", mktime(lt));
+                               snprintf(subbuf, 64, "%ld", mktime(lt));
                                len = strlen(subbuf); CHECK_SIZE();
                                strncpy2(curpos, subbuf, buflen - total_done);
                                break;
@@ -4996,7 +5111,8 @@ size_t fast_strftime(gchar *buf, gint buflen, const gchar *format, struct tm *lt
                                format++;
                                break;
                        default:
-                               g_warning("format error (%c)", *format);
+                               if (format && *format)
+                                       g_warning("format error (%c)", *format);
                                *curpos = '\0';
                                return total_done;
                        }
@@ -5013,6 +5129,11 @@ size_t fast_strftime(gchar *buf, gint buflen, const gchar *format, struct tm *lt
 
 gboolean prefs_common_get_use_shred(void);
 
+
+#ifdef G_OS_WIN32
+#define WEXITSTATUS(x) (x)
+#endif
+
 int claws_unlink(const gchar *filename) 
 {
        struct stat s;
@@ -5022,24 +5143,27 @@ int claws_unlink(const gchar *filename)
        if (filename == NULL)
                return 0;
 
-       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 && prefs_common_get_use_shred()) {
-               if (is_file_exist(filename) && g_stat(filename, &s) == 0) {
-                       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));
-                               truncate(filename, 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");
+                               }
                        }
                }
        }