sync with 0.8.1cvs17
[claws.git] / src / utils.c
index cf1fdd7aa201d69f0379757983752b789325cd87..0ba94c97152ed235e7bd40e133359b3f11ff83ab 100644 (file)
@@ -28,7 +28,6 @@
 #include <string.h>
 #include <ctype.h>
 #include <errno.h>
-#include <netdb.h>
 
 #if (HAVE_WCTYPE_H && HAVE_WCHAR_H)
 #  include <wchar.h>
@@ -45,6 +44,7 @@
 
 #include "intl.h"
 #include "utils.h"
+#include "socket.h"
 #include "statusbar.h"
 #include "logwindow.h"
 
@@ -1471,26 +1471,25 @@ gchar *get_tmp_file(void)
 gchar *get_domain_name(void)
 {
        static gchar *domain_name = NULL;
-        struct hostent *myfqdn = NULL;
 
        if (!domain_name) {
-               gchar buf[BUFFSIZE] = "";
+               gchar buf[128] = "";
+               struct hostent *hp;
 
                if (gethostname(buf, sizeof(buf)) < 0) {
                        perror("gethostname");
-                       strcpy(buf, "unknown");
-               }  else  {
-                myfqdn = gethostbyname(buf);
-                if (myfqdn != NULL)  {
-                  memset(buf, '\0', strlen(buf));
-                  strcpy(buf, myfqdn->h_name);
-                  }  else  {
-                  perror("gethostbyname");
-                  strcpy(buf, "unknown");
-                  }
-                }
+                       domain_name = "unknown";
+               } else {
+                       buf[sizeof(buf) - 1] = '\0';
+                       if ((hp = my_gethostbyname(buf)) == NULL) {
+                               perror("gethostbyname");
+                               domain_name = g_strdup(buf);
+                       } else {
+                               domain_name = g_strdup(hp->h_name);
+                       }
+               }
 
-               domain_name = g_strdup(buf);
+               debug_print("domain name = %s\n", domain_name);
        }
 
        return domain_name;
@@ -1627,6 +1626,18 @@ gint change_dir(const gchar *dir)
        return 0;
 }
 
+gint make_dir(const gchar *dir)
+{
+       if (mkdir(dir, S_IRWXU) < 0) {
+               FILE_OP_ERROR(dir, "mkdir");
+               return -1;
+       }
+       if (chmod(dir, S_IRWXU) < 0)
+               FILE_OP_ERROR(dir, "chmod");
+
+       return 0;
+}
+
 gint make_dir_hier(const gchar *dir)
 {
        gchar *parent_dir;
@@ -1636,24 +1647,18 @@ gint make_dir_hier(const gchar *dir)
                parent_dir = g_strndup(dir, p - dir);
                if (*parent_dir != '\0') {
                        if (!is_dir_exist(parent_dir)) {
-                               if (mkdir(parent_dir, S_IRWXU) < 0) {
-                                       FILE_OP_ERROR(parent_dir, "mkdir");
+                               if (make_dir(parent_dir) < 0) {
                                        g_free(parent_dir);
                                        return -1;
                                }
-                               if (chmod(parent_dir, S_IRWXU) < 0)
-                                       FILE_OP_ERROR(parent_dir, "chmod");
                        }
                }
                g_free(parent_dir);
        }
+
        if (!is_dir_exist(dir)) {
-               if (mkdir(dir, S_IRWXU) < 0) {
-                       FILE_OP_ERROR(dir, "mkdir");
+               if (make_dir(dir) < 0)
                        return -1;
-               }
-               if (chmod(dir, S_IRWXU) < 0)
-                       FILE_OP_ERROR(dir, "chmod");
        }
 
        return 0;
@@ -1721,6 +1726,8 @@ gint remove_numbered_files(const gchar *dir, guint first, guint last)
        while ((d = readdir(dp)) != NULL) {
                fileno = to_number(d->d_name);
                if (fileno >= 0 && first <= fileno && fileno <= last) {
+                       if (is_dir_exist(d->d_name))
+                               continue;
                        if (unlink(d->d_name) < 0)
                                FILE_OP_ERROR(d->d_name, "unlink");
                }
@@ -1744,6 +1751,60 @@ gint remove_all_numbered_files(const gchar *dir)
        return remove_numbered_files(dir, 0, UINT_MAX);
 }
 
+gint remove_expired_files(const gchar *dir, guint hours)
+{
+       DIR *dp;
+       struct dirent *d;
+       struct stat s;
+       gchar *prev_dir;
+       gint fileno;
+       time_t mtime, now, expire_time;
+
+       prev_dir = g_get_current_dir();
+
+       if (chdir(dir) < 0) {
+               FILE_OP_ERROR(dir, "chdir");
+               return -1;
+       }
+
+       if ((dp = opendir(".")) == NULL) {
+               FILE_OP_ERROR(dir, "opendir");
+               return -1;
+       }
+
+       now = time(NULL);
+       expire_time = hours * 60 * 60;
+
+       while ((d = readdir(dp)) != NULL) {
+               fileno = to_number(d->d_name);
+               if (fileno >= 0) {
+                       if (stat(d->d_name, &s) < 0) {
+                               FILE_OP_ERROR(d->d_name, "stat");
+                               continue;
+                       }
+                       if (S_ISDIR(s.st_mode))
+                               continue;
+                       mtime = MAX(s.st_mtime, s.st_atime);
+                       if (now - mtime > expire_time) {
+                               if (unlink(d->d_name) < 0)
+                                       FILE_OP_ERROR(d->d_name, "unlink");
+                       }
+               }
+       }
+
+       closedir(dp);
+
+       if (chdir(prev_dir) < 0) {
+               FILE_OP_ERROR(prev_dir, "chdir");
+               g_free(prev_dir);
+               return -1;
+       }
+
+       g_free(prev_dir);
+
+       return 0;
+}
+
 gint remove_dir_recursive(const gchar *dir)
 {
        struct stat s;
@@ -2014,6 +2075,106 @@ gint move_file(const gchar *src, const gchar *dest)
        return 0;
 }
 
+/* convert line endings into CRLF. If the last line doesn't end with
+ * linebreak, add it.
+ */
+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_fp = fopen(src, "rb")) == NULL) {
+               FILE_OP_ERROR(src, "fopen");
+               return -1;
+       }
+
+       if ((dest_fp = fopen(dest, "wb")) == NULL) {
+               FILE_OP_ERROR(dest, "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\n");
+       }
+
+       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, len - 1, 1, dest_fp);
+                               if (r != 1)
+                                       r = EOF;
+                       }
+                       if (r != EOF)
+                               r = fputs("\r\n", dest_fp);
+               }
+
+               if (r == EOF) {
+                       g_warning("writing to %s failed.\n", dest);
+                       fclose(dest_fp);
+                       fclose(src_fp);
+                       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, "fread");
+               err = TRUE;
+       }
+       fclose(src_fp);
+       if (fclose(dest_fp) == EOF) {
+               FILE_OP_ERROR(dest, "fclose");
+               err = TRUE;
+       }
+
+       if (err) {
+               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)
+               return -1;
+
+       unlink(file);
+       if (rename(tmp_file, file) < 0) {
+               FILE_OP_ERROR(file, "rename");
+               unlink(tmp_file);
+               return -1;
+       }
+
+       return 0;
+}
+
 gint change_file_mode_rw(FILE *fp, const gchar *file)
 {
 #if HAVE_FCHMOD
@@ -2480,66 +2641,74 @@ void debug_print_real(const gchar *format, ...)
        fputs(buf, stdout);
 }
 
+#define TIME_LEN       11
+
 void log_print(const gchar *format, ...)
 {
        va_list args;
-       gchar buf[BUFFSIZE];
-       gchar *logbuf;
-       gchar timestr[6];
+       gchar buf[BUFFSIZE + TIME_LEN];
        time_t t;
 
+       time(&t);
+       strftime(buf, TIME_LEN + 1, "[%H:%M:%S] ", localtime(&t));
+
        va_start(args, format);
-       g_vsnprintf(buf, sizeof(buf), format, args);
+       g_vsnprintf(buf + TIME_LEN, BUFFSIZE, format, args);
        va_end(args);
-       
-       time(&t);
-       strftime(timestr, 6, "%H:%M", localtime(&t));
-       logbuf = g_strdup_printf("[%s] %s", timestr, buf);
 
-       if (debug_mode) fputs(logbuf, stdout);
-       log_window_append(logbuf, LOG_NORMAL);
+       if (debug_mode) fputs(buf, stdout);
+       log_window_append(buf, LOG_NORMAL);
        if (log_fp) {
-               fputs(logbuf, log_fp);
+               fputs(buf, log_fp);
                fflush(log_fp);
        }
        if (log_verbosity_count)
-               statusbar_puts_all(buf);
-       g_free(logbuf);
+               statusbar_puts_all(buf + TIME_LEN);
 }
 
 void log_message(const gchar *format, ...)
 {
        va_list args;
-       gchar buf[BUFFSIZE];
+       gchar buf[BUFFSIZE + TIME_LEN];
+       time_t t;
+
+       time(&t);
+       strftime(buf, TIME_LEN + 1, "[%H:%M:%S] ", localtime(&t));
 
        va_start(args, format);
-       g_vsnprintf(buf, sizeof(buf), format, args);
+       g_vsnprintf(buf + TIME_LEN, BUFFSIZE, format, args);
        va_end(args);
 
-       if (debug_mode) g_message("%s", buf);
-       log_window_append(buf, LOG_MSG);
+       if (debug_mode) g_message("%s", buf + TIME_LEN);
+       log_window_append(buf + TIME_LEN, LOG_MSG);
        if (log_fp) {
-               fputs("message: ", log_fp);
-               fputs(buf, log_fp);
+               fwrite(buf, TIME_LEN, 1, log_fp);
+               fputs("* message: ", log_fp);
+               fputs(buf + TIME_LEN, log_fp);
                fflush(log_fp);
        }
-       statusbar_puts_all(buf);
+       statusbar_puts_all(buf + TIME_LEN);
 }
 
 void log_warning(const gchar *format, ...)
 {
        va_list args;
-       gchar buf[BUFFSIZE];
+       gchar buf[BUFFSIZE + TIME_LEN];
+       time_t t;
+
+       time(&t);
+       strftime(buf, TIME_LEN + 1, "[%H:%M:%S] ", localtime(&t));
 
        va_start(args, format);
-       g_vsnprintf(buf, sizeof(buf), format, args);
+       g_vsnprintf(buf + TIME_LEN, BUFFSIZE, format, args);
        va_end(args);
 
        g_warning("%s", buf);
-       log_window_append(buf, LOG_WARN);
+       log_window_append(buf + TIME_LEN, LOG_WARN);
        if (log_fp) {
-               fputs("*** warning: ", log_fp);
-               fputs(buf, log_fp);
+               fwrite(buf, TIME_LEN, 1, log_fp);
+               fputs("** warning: ", log_fp);
+               fputs(buf + TIME_LEN, log_fp);
                fflush(log_fp);
        }
 }
@@ -2547,17 +2716,22 @@ void log_warning(const gchar *format, ...)
 void log_error(const gchar *format, ...)
 {
        va_list args;
-       gchar buf[BUFFSIZE];
+       gchar buf[BUFFSIZE + TIME_LEN];
+       time_t t;
+
+       time(&t);
+       strftime(buf, TIME_LEN + 1, "[%H:%M:%S] ", localtime(&t));
 
        va_start(args, format);
-       g_vsnprintf(buf, sizeof(buf), format, args);
+       g_vsnprintf(buf + TIME_LEN, BUFFSIZE, format, args);
        va_end(args);
 
        g_warning("%s", buf);
-       log_window_append(buf, LOG_ERROR);
+       log_window_append(buf + TIME_LEN, LOG_ERROR);
        if (log_fp) {
+               fwrite(buf, TIME_LEN, 1, log_fp);
                fputs("*** error: ", log_fp);
-               fputs(buf, log_fp);
+               fputs(buf + TIME_LEN, log_fp);
                fflush(log_fp);
        }
 }