2007-08-13 [paul] 2.10.0cvs117
[claws.git] / src / common / utils.c
index 533c1f93bd232b0f761620bff4aafad6f04667da..3724dca1ed1cf633c75135a668ae78e0e96df702 100644 (file)
@@ -4,7 +4,7 @@
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
+ * the Free Software Foundation; either version 3 of the License, or
  * (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
@@ -13,8 +13,8 @@
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * 
  */
 
 #ifdef HAVE_CONFIG_H
@@ -31,6 +31,7 @@
 #include <string.h>
 #include <ctype.h>
 #include <errno.h>
+#include <sys/param.h>
 
 #if (HAVE_WCTYPE_H && HAVE_WCHAR_H)
 #  include <wchar.h>
 #  include <direct.h>
 #  include <io.h>
 #  include <fcntl.h>
+#  include <w32lib.h>
+#endif
+
+#ifdef MAEMO
+#include <libosso.h>
+#include <osso-browser-interface.h>
 #endif
 
 #include "utils.h"
@@ -69,6 +76,18 @@ static gboolean debug_mode = FALSE;
 static GSList *tempfiles=NULL;
 #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  
+}
+
+
 
 #if !GLIB_CHECK_VERSION(2, 7, 0) && !defined(G_OS_UNIX)
 gint g_chdir(const gchar *path)
@@ -1611,7 +1630,7 @@ gint get_uri_len(const gchar *str)
 /* Decodes URL-Encoded strings (i.e. strings in which spaces are replaced by
  * plusses, and escape characters are used)
  */
-void decode_uri(gchar *decoded_uri, const gchar *encoded_uri)
+void decode_uri_with_plus(gchar *decoded_uri, const gchar *encoded_uri, gboolean with_plus)
 {
        gchar *dec = decoded_uri;
        const gchar *enc = encoded_uri;
@@ -1626,7 +1645,7 @@ void decode_uri(gchar *decoded_uri, const gchar *encoded_uri)
                                enc += 2;
                        }
                } else {
-                       if (*enc == '+')
+                       if (with_plus && *enc == '+')
                                *dec = ' ';
                        else
                                *dec = *enc;
@@ -1638,6 +1657,11 @@ void decode_uri(gchar *decoded_uri, const gchar *encoded_uri)
        *dec = '\0';
 }
 
+void decode_uri(gchar *decoded_uri, const gchar *encoded_uri)
+{
+       decode_uri_with_plus(decoded_uri, encoded_uri, TRUE);
+}
+
 gint scan_mailto_url(const gchar *mailto, gchar **to, gchar **cc, gchar **bcc,
                     gchar **subject, gchar **body, gchar **attach)
 {
@@ -1910,24 +1934,77 @@ const gchar *get_mail_base_dir(void)
 #endif
 }
 
+#ifdef MAEMO
+const gchar *prefs_common_get_data_root(void);
+gchar *last_data_root = NULL;
+#endif
+
 const gchar *get_news_cache_dir(void)
 {
        static gchar *news_cache_dir = NULL;
-
+#ifdef MAEMO
+       const gchar *data_root = prefs_common_get_data_root();
+       if (strcmp2(data_root, last_data_root)) {
+               g_free(news_cache_dir);
+               news_cache_dir = NULL;
+       }
+#endif
        if (!news_cache_dir)
+#ifndef MAEMO
                news_cache_dir = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
                                             NEWS_CACHE_DIR, NULL);
-
+#else
+       {
+               if (data_root) {
+                       news_cache_dir = g_strconcat(data_root, G_DIR_SEPARATOR_S,
+                                            "Claws", G_DIR_SEPARATOR_S, 
+                                            g_get_user_name(), G_DIR_SEPARATOR_S,
+                                            NEWS_CACHE_DIR, NULL);
+                       g_free(last_data_root);
+                       last_data_root = g_strdup(last_data_root);
+               } else {
+                       news_cache_dir = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
+                                            NEWS_CACHE_DIR, NULL);
+                       g_free(last_data_root);
+                       last_data_root = NULL;
+               }
+       }
+#endif
        return news_cache_dir;
 }
 
 const gchar *get_imap_cache_dir(void)
 {
        static gchar *imap_cache_dir = NULL;
+#ifdef MAEMO
+       const gchar *data_root = prefs_common_get_data_root();
+       if (strcmp2(data_root, last_data_root)) {
+               g_free(imap_cache_dir);
+               imap_cache_dir = NULL;
+       }
+#endif
 
        if (!imap_cache_dir)
+#ifndef MAEMO
                imap_cache_dir = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
                                             IMAP_CACHE_DIR, NULL);
+#else
+       {
+               if (data_root) {
+                       imap_cache_dir = g_strconcat(data_root, G_DIR_SEPARATOR_S,
+                                            "Claws", G_DIR_SEPARATOR_S, 
+                                            g_get_user_name(), G_DIR_SEPARATOR_S,
+                                            IMAP_CACHE_DIR, NULL);
+                       g_free(last_data_root);
+                       last_data_root = g_strdup(last_data_root);
+               } else {
+                       imap_cache_dir = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
+                                            IMAP_CACHE_DIR, NULL);
+                       g_free(last_data_root);
+                       last_data_root = NULL;
+               }
+       }
+#endif
 
        return imap_cache_dir;
 }
@@ -1935,10 +2012,34 @@ const gchar *get_imap_cache_dir(void)
 const gchar *get_mbox_cache_dir(void)
 {
        static gchar *mbox_cache_dir = NULL;
-
+#ifdef MAEMO
+       const gchar *data_root = prefs_common_get_data_root();
+       if (strcmp2(data_root, last_data_root)) {
+               g_free(mbox_cache_dir);
+               mbox_cache_dir = NULL;
+       }
+#endif
        if (!mbox_cache_dir)
+#ifndef MAEMO
                mbox_cache_dir = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
                                             MBOX_CACHE_DIR, NULL);
+#else
+       {
+               if (data_root) {
+                       mbox_cache_dir = g_strconcat(data_root, G_DIR_SEPARATOR_S,
+                                            "Claws", G_DIR_SEPARATOR_S, 
+                                            g_get_user_name(), G_DIR_SEPARATOR_S,
+                                            MBOX_CACHE_DIR, NULL);
+                       g_free(last_data_root);
+                       last_data_root = g_strdup(last_data_root);
+               } else {
+                       mbox_cache_dir = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
+                                            MBOX_CACHE_DIR, NULL);
+                       g_free(last_data_root);
+                       last_data_root = NULL;
+               }
+       }
+#endif
 
        return mbox_cache_dir;
 }
@@ -2030,20 +2131,20 @@ const gchar *get_domain_name(void)
 
        if (!domain_name) {
                struct hostent *hp;
-               struct utsname uts;
+               char hostname[256];
 
-               if (uname(&uts) < 0) {
-                       perror("uname");
+               if (gethostname(hostname, sizeof(hostname)) != 0) {
+                       perror("gethostname");
                        domain_name = "unknown";
                } else {
-                       if ((hp = my_gethostbyname(uts.nodename)) == NULL) {
+                       hostname[sizeof(hostname) - 1] = '\0';
+                       if ((hp = my_gethostbyname(hostname)) == NULL) {
                                perror("gethostbyname");
-                               domain_name = g_strdup(uts.nodename);
+                               domain_name = g_strdup(hostname);
                        } else {
                                domain_name = g_strdup(hp->h_name);
                        }
                }
-
                debug_print("domain name = %s\n", domain_name);
        }
 
@@ -2190,7 +2291,7 @@ gboolean is_file_entry_exist(const gchar *file)
 
 gboolean dirent_is_regular_file(struct dirent *d)
 {
-#ifdef HAVE_DIRENT_D_TYPE
+#if !defined(G_OS_WIN32) && !defined(MAEMO) && defined(HAVE_DIRENT_D_TYPE)
        if (d->d_type == DT_REG)
                return TRUE;
        else if (d->d_type != DT_UNKNOWN)
@@ -2202,7 +2303,7 @@ gboolean dirent_is_regular_file(struct dirent *d)
 
 gboolean dirent_is_directory(struct dirent *d)
 {
-#ifdef HAVE_DIRENT_D_TYPE
+#if !defined(G_OS_WIN32) && !defined(MAEMO) && defined(HAVE_DIRENT_D_TYPE)
        if (d->d_type == DT_DIR)
                return TRUE;
        else if (d->d_type != DT_UNKNOWN)
@@ -3294,7 +3395,39 @@ gchar *file_read_stream_to_str(FILE *fp)
        return str;
 }
 
-gint execute_async(gchar *const argv[])
+
+char *fgets_crlf(char *buf, int size, FILE *stream)
+{
+       gboolean is_cr = FALSE;
+       gboolean last_was_cr = FALSE;
+       int c = 0;
+       char *cs;
+
+       cs = buf;
+       while (--size > 0 && (c = getc(stream)) != EOF)
+       {
+               *cs++ = c;
+               is_cr = (c == '\r');
+               if (c == '\n') {
+                       break;
+               }
+               if (last_was_cr) {
+                       *(--cs) = '\n';
+                       cs++;
+                       ungetc(c, stream);
+                       break;
+               }
+               last_was_cr = is_cr;
+       }
+       if (c == EOF && cs == buf)
+               return NULL;
+
+       *cs = '\0';
+
+       return buf;     
+}
+
+static gint execute_async(gchar *const argv[])
 {
        g_return_val_if_fail(argv != NULL && argv[0] != NULL, -1);
 
@@ -3307,7 +3440,7 @@ gint execute_async(gchar *const argv[])
        return 0;
 }
 
-gint execute_sync(gchar *const argv[])
+static gint execute_sync(gchar *const argv[])
 {
        gint status;
 
@@ -3371,14 +3504,13 @@ static gint is_unchanged_uri_char(char c)
        switch (c) {
                case '(':
                case ')':
-               case ',':
                        return 0;
                default:
                        return 1;
        }
 }
 
-void encode_uri(gchar *encoded_uri, gint bufsize, const gchar *uri)
+static void encode_uri(gchar *encoded_uri, gint bufsize, const gchar *uri)
 {
        int i;
        int k;
@@ -3405,10 +3537,10 @@ void encode_uri(gchar *encoded_uri, gint bufsize, const gchar *uri)
 
 gint open_uri(const gchar *uri, const gchar *cmdline)
 {
+#ifndef MAEMO
        gchar buf[BUFFSIZE];
        gchar *p;
        gchar encoded_uri[BUFFSIZE];
-
        g_return_val_if_fail(uri != NULL, -1);
 
        /* an option to choose whether to use encode_uri or not ? */
@@ -3427,7 +3559,12 @@ gint open_uri(const gchar *uri, const gchar *cmdline)
        }
 
        execute_command_line(buf, TRUE);
-
+#else
+       extern osso_context_t *get_osso_context(void);
+       osso_rpc_run_with_defaults(get_osso_context(), "osso_browser",
+                                       OSSO_BROWSER_OPEN_NEW_WINDOW_REQ, NULL, 
+                                       DBUS_TYPE_STRING, uri, DBUS_TYPE_INVALID);
+#endif
        return 0;
 }
 
@@ -3527,9 +3664,10 @@ time_t tzoffset_sec(time_t *now)
 {
        struct tm gmt, *lt;
        gint off;
-
-       gmt = *gmtime(now);
-       lt = localtime(now);
+       struct tm buf1, buf2;
+       
+       gmt = *gmtime_r(now, &buf1);
+       lt = localtime_r(now, &buf2);
 
        off = (lt->tm_hour - gmt.tm_hour) * 60 + lt->tm_min - gmt.tm_min;
 
@@ -3557,9 +3695,10 @@ gchar *tzoffset(time_t *now)
        struct tm gmt, *lt;
        gint off;
        gchar sign = '+';
+       struct tm buf1, buf2;
 
-       gmt = *gmtime(now);
-       lt = localtime(now);
+       gmt = *gmtime_r(now, &buf1);
+       lt = localtime_r(now, &buf2);
 
        off = (lt->tm_hour - gmt.tm_hour) * 60 + lt->tm_min - gmt.tm_min;
 
@@ -3591,12 +3730,19 @@ void get_rfc822_date(gchar *buf, gint len)
        time_t t;
        gchar day[4], mon[4];
        gint dd, hh, mm, ss, yyyy;
+       struct tm buf1;
+       gchar buf2[BUFFSIZE];
 
        t = time(NULL);
-       lt = localtime(&t);
+       lt = localtime_r(&t, &buf1);
 
-       sscanf(asctime(lt), "%3s %3s %d %d:%d:%d %d\n",
+#ifdef SOLARIS
+       sscanf(asctime_r(lt, buf2, sizeof(buf2)), "%3s %3s %d %d:%d:%d %d\n",
+              day, mon, &dd, &hh, &mm, &ss, &yyyy);
+#else
+       sscanf(asctime_r(lt, buf2), "%3s %3s %d %d:%d:%d %d\n",
               day, mon, &dd, &hh, &mm, &ss, &yyyy);
+#endif
        g_snprintf(buf, len, "%s, %d %s %d %02d:%02d:%02d %s",
                   day, dd, mon, yyyy, hh, mm, ss, tzoffset(&t));
 }
@@ -3772,9 +3918,10 @@ gchar *generate_msgid(gchar *buf, gint len)
        struct tm *lt;
        time_t t;
        gchar *addr;
+       struct tm buft;
 
        t = time(NULL);
-       lt = localtime(&t);
+       lt = localtime_r(&t, &buft);
 
        addr = g_strconcat("@", get_domain_name(), NULL);
 
@@ -4714,7 +4861,12 @@ gint copy_dir(const gchar *src, const gchar *dst)
                                g_dir_close(dir);
                                return r;
                        }
-               } else if (g_file_test(old_file, G_FILE_TEST_IS_SYMLINK)) {
+                }
+#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;
                        gint r = 0;
                        gchar *target = g_file_read_link(old_file, &error);
@@ -4725,7 +4877,9 @@ gint copy_dir(const gchar *src, const gchar *dst)
                                g_dir_close(dir);
                                return r;
                        }
-               } else if (g_file_test(old_file, G_FILE_TEST_IS_DIR)) {
+                 }
+#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);
@@ -4857,30 +5011,6 @@ static void init_time_names(void)
        time_am_pm = Q_("For use by strftime (default 12-hour time format)|%I:%M:%S %p");
 
        time_names_init_done = TRUE;
-#if 0
-       {
-       struct tm *lt;
-       time_t now = time(NULL), next;
-       gchar buf_a[1024], buf_b[1024];
-       
-       printf("test strftime:\n");
-       tzset();
-       for (next = now; next < now + 86400*365*2; next++) {
-               lt = localtime(&now);
-               strftime(buf_a, 1024, 
-                       "%a,%A,%b,%B,%c,%C,%d,%D,%e,%F,%G,%g,%h,%H,%I "
-                       "%j,%k,%l,%m,%M,%n,%p,%P,%r,%R,%s,%S,%t,%T,%u,%U,%V"
-                       "%w,%W,%x,%X,%y,%Y,%z,%Z,%%,%EY,%OY", lt);
-               fast_strftime(buf_b, 1024, 
-                       "%a,%A,%b,%B,%c,%C,%d,%D,%e,%F,%G,%g,%h,%H,%I "
-                       "%j,%k,%l,%m,%M,%n,%p,%P,%r,%R,%s,%S,%t,%T,%u,%U,%V"
-                       "%w,%W,%x,%X,%y,%Y,%z,%Z,%%,%EY,%OY", lt);
-               if (strcmp(buf_a, buf_b)) {
-                       printf("diff: \n%s\n%s\n", buf_a, buf_b);
-               }
-       }
-       }
-#endif
 }
 
 #define CHECK_SIZE() {                 \