/*
- * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 1999-2013 Hiroyuki Yamamoto & The Claws Mail Team
+ * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
+ * Copyright (C) 1999-2016 Hiroyuki Yamamoto & The Claws Mail Team
*
* 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 code of the g_utf8_substring function below is owned by
* Matthias Clasen <matthiasc@src.gnome.org>/<mclasen@redhat.com>
- * and is got from GLIB 2.30
- *
+ * and is got from GLIB 2.30: https://git.gnome.org/browse/glib/commit/
+ * ?h=glib-2-30&id=9eb65dd3ed5e1a9638595cbe10699c7606376511
+ *
+ * GLib 2.30 is licensed under GPL v2 or later and:
+ * Copyright (C) 1999 Tom Tromey
+ * Copyright (C) 2000 Red Hat, Inc.
+ *
+ * https://git.gnome.org/browse/glib/tree/glib/gutf8.c
+ * ?h=glib-2-30&id=9eb65dd3ed5e1a9638595cbe10699c7606376511
*/
#ifdef HAVE_CONFIG_H
#include <ctype.h>
#include <errno.h>
#include <sys/param.h>
+#ifndef G_OS_WIN32
+#include <sys/socket.h>
+#endif
#if (HAVE_WCTYPE_H && HAVE_WCHAR_H)
# include <wchar.h>
#include "utils.h"
#include "socket.h"
#include "../codeconv.h"
+#include "tlds.h"
#define BUFFSIZE 8192
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)
+#if !GLIB_CHECK_VERSION(2, 26, 0)
+guchar *g_base64_decode_wa(const gchar *text, gsize *out_len)
{
-#ifdef G_OS_WIN32
- return w32_is_administrator ();
-#else
- return !getuid();
-#endif
-}
+ guchar *ret;
+ gsize input_length;
+ gint state = 0;
+ guint save = 0;
+ input_length = strlen(text);
+ ret = g_malloc0((input_length / 4) * 3 + 1);
-#if !defined(G_OS_UNIX)
-gint g_chdir(const gchar *path)
-{
-#ifdef G_OS_WIN32
- if (G_WIN32_HAVE_WIDECHAR_API()) {
- wchar_t *wpath;
- gint retval;
- gint save_errno;
-
- wpath = g_utf8_to_utf16(path, -1, NULL, NULL, NULL);
- if (wpath == NULL) {
- errno = EINVAL;
- return -1;
- }
-
- retval = _wchdir(wpath);
- save_errno = errno;
-
- g_free(wpath);
-
- errno = save_errno;
- return retval;
- } else {
- gchar *cp_path;
- gint retval;
- gint save_errno;
-
- cp_path = g_locale_from_utf8(path, -1, NULL, NULL, NULL);
- if (cp_path == NULL) {
- errno = EINVAL;
- return -1;
- }
-
- retval = chdir(cp_path);
- save_errno = errno;
-
- g_free(cp_path);
+ *out_len = g_base64_decode_step(text, input_length, ret, &state, &save);
- errno = save_errno;
- return retval;
- }
-#else
- return chdir(path);
-#endif
+ return ret;
}
-
-gint g_chmod(const gchar *path, gint mode)
-{
-#ifdef G_OS_WIN32
- if (G_WIN32_HAVE_WIDECHAR_API()) {
- wchar_t *wpath;
- gint retval;
- gint save_errno;
-
- wpath = g_utf8_to_utf16(path, -1, NULL, NULL, NULL);
- if (wpath == NULL) {
- errno = EINVAL;
- return -1;
- }
-
- retval = _wchmod(wpath, mode);
- save_errno = errno;
-
- g_free(wpath);
-
- errno = save_errno;
- return retval;
- } else {
- gchar *cp_path;
- gint retval;
- gint save_errno;
-
- cp_path = g_locale_from_utf8(path, -1, NULL, NULL, NULL);
- if (cp_path == NULL) {
- errno = EINVAL;
- return -1;
- }
-
- retval = chmod(cp_path, mode);
- save_errno = errno;
-
- g_free(cp_path);
-
- errno = save_errno;
- return retval;
- }
-#else
- 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
-}
-int g_open(const gchar *filename, int flags, int mode)
+/* Return true if we are running as root. This function should beused
+ instead of getuid () == 0. */
+gboolean superuser_p (void)
{
#ifdef G_OS_WIN32
- char *name = g_win32_locale_filename_from_utf8(filename);
- int fd = open(name, flags, mode);
- g_free(name);
- return fp;
+ return w32_is_administrator ();
#else
- return open(filename, flags, mode);
-#endif
-}
-#endif /* G_OS_UNIX */
-
-
-#ifdef G_OS_WIN32
-gint mkstemp_name(gchar *template, gchar **name_used)
-{
- static gulong count=0; /* W32-_mktemp only supports up to 27
- tempfiles... */
- int tmpfd;
-
- *name_used = g_strdup_printf("%s.%ld",_mktemp(template),count++);
- tmpfd = g_open (*name_used, (O_CREAT | O_RDWR | O_BINARY),
- (S_IRUSR | S_IWUSR));
-
- tempfiles=g_slist_append(tempfiles, g_strdup(*name_used));
- if (tmpfd<0) {
- perror(g_strdup_printf("cant create %s",*name_used));
- return -1;
- }
- else
- return tmpfd;
-}
-#endif /* G_OS_WIN32 */
-
-#ifdef G_OS_WIN32
-gint mkstemp(gchar *template)
-{
- gchar *dummyname;
- gint res = mkstemp_name(template, &dummyname);
- g_free(dummyname);
- return res;
+ return !getuid();
+#endif
}
-#endif /* G_OS_WIN32 */
GSList *slist_copy_deep(GSList *list, GCopyFunc func)
{
void unfold_line(gchar *str)
{
- register gchar *p = str;
- register gint spc;
+ register gchar *ch;
+ register gunichar c;
+ register gint len;
- while (*p) {
- if (*p == '\n' || *p == '\r') {
- *p++ = ' ';
- spc = 0;
- while (g_ascii_isspace(*(p + spc)))
- spc++;
- if (spc)
- memmove(p, p + spc, strlen(p + spc) + 1);
- } else
- p++;
+ ch = str; /* iterator for source string */
+
+ while (*ch != 0) {
+ c = g_utf8_get_char_validated(ch, -1);
+
+ if (c == (gunichar)-1 || c == (gunichar)-2) {
+ /* non-unicode byte, move past it */
+ ch++;
+ continue;
+ }
+
+ len = g_unichar_to_utf8(c, NULL);
+
+ if (!g_unichar_isdefined(c) || !g_unichar_isprint(c) ||
+ g_unichar_isspace(c)) {
+ /* replace anything bad or whitespacey with a single space */
+ *ch = ' ';
+ ch++;
+ if (len > 1) {
+ /* move rest of the string forwards, since we just replaced
+ * a multi-byte sequence with one byte */
+ memmove(ch, ch + len-1, strlen(ch + len-1) + 1);
+ }
+ } else {
+ /* A valid unicode character, copy it. */
+ ch += len;
+ }
}
}
if (!locale_file)
locale_file = g_strdup(file + 5);
#else
- locale_file = g_filename_from_uri(file, NULL, NULL);
+ locale_file = g_filename_from_uri(escaped_utf8uri, NULL, NULL);
#endif
result = g_list_append(result, locale_file);
}
} else if (body && !*body && !g_ascii_strcasecmp(field, "insert")) {
gchar *tmp = decode_uri_gdup(value);
if (!g_file_get_contents(tmp, body, NULL, NULL)) {
- g_warning("Error: couldn't set insert file '%s' in body\n", value);
+ g_warning("couldn't set insert file '%s' in body", value);
}
g_free(tmp);
tmp = NULL;
if (w32_shgetfolderpath
(NULL, CSIDL_APPDATA|CSIDL_FLAG_CREATE,
NULL, 0, home_dir_utf16) < 0)
- strcpy (home_dir_utf16, "C:\\Sylpheed");
+ strcpy (home_dir_utf16, "C:\\Claws Mail");
home_dir_utf8 = g_utf16_to_utf8 ((const gunichar *)home_dir_utf16, -1, NULL, NULL, NULL);
}
return home_dir_utf8;
if (err) {
g_print("Error looking for %s: %d(%s)\n",
- dir, -err, strerror(-err));
+ dir, -err, g_strerror(-err));
exit(0);
}
rc_dir_alt = TRUE;
}
#ifdef G_OS_WIN32
-const gchar *get_cert_file(void)
+const gchar *w32_get_cert_file(void)
{
const gchar *cert_file = NULL;
if (!cert_file)
#ifdef G_OS_WIN32
/* Return the default directory for Themes. */
-const gchar *get_themes_dir(void)
+const gchar *w32_get_themes_dir(void)
{
static gchar *themes_dir = NULL;
{
#ifdef G_OS_UNIX
static gchar *domain_name = NULL;
+ struct addrinfo hints, *res;
+ char hostname[256];
+ int s;
if (!domain_name) {
- struct hostent *hp;
- char hostname[256];
-
if (gethostname(hostname, sizeof(hostname)) != 0) {
perror("gethostname");
domain_name = "localhost";
} else {
- hostname[sizeof(hostname) - 1] = '\0';
- if ((hp = my_gethostbyname(hostname)) == NULL) {
- perror("gethostbyname");
+ memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = 0;
+ hints.ai_flags = AI_CANONNAME;
+ hints.ai_protocol = 0;
+
+ s = getaddrinfo(hostname, NULL, &hints, &res);
+ if (s != 0) {
+ fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));
domain_name = g_strdup(hostname);
} else {
- domain_name = g_strdup(hp->h_name);
+ domain_name = g_strdup(res->ai_canonname);
+ freeaddrinfo(res);
}
}
debug_print("domain name = %s\n", domain_name);
off_t get_file_size(const gchar *file)
{
- struct stat s;
+ GStatBuf s;
if (g_stat(file, &s) < 0) {
FILE_OP_ERROR(file, "stat");
time_t get_file_mtime(const gchar *file)
{
- struct stat s;
+ GStatBuf s;
if (g_stat(file, &s) < 0) {
FILE_OP_ERROR(file, "stat");
return s.st_mtime;
}
-off_t get_file_size_as_crlf(const gchar *file)
-{
- FILE *fp;
- off_t size = 0;
- gchar buf[BUFFSIZE];
-
- if ((fp = g_fopen(file, "rb")) == NULL) {
- FILE_OP_ERROR(file, "g_fopen");
- return -1;
- }
-
- while (fgets(buf, sizeof(buf), fp) != NULL) {
- strretchomp(buf);
- size += strlen(buf) + 2;
- }
-
- if (ferror(fp)) {
- FILE_OP_ERROR(file, "fgets");
- size = -1;
- }
-
- fclose(fp);
-
- return size;
-}
-
gboolean file_exist(const gchar *file, gboolean allow_fifo)
{
- struct stat s;
+ GStatBuf s;
if (file == NULL)
return FALSE;
gint remove_all_files(const gchar *dir)
{
GDir *dp;
- const gchar *dir_name;
- gchar *prev_dir;
-
- prev_dir = g_get_current_dir();
-
- if (g_chdir(dir) < 0) {
- FILE_OP_ERROR(dir, "chdir");
- g_free(prev_dir);
- return -1;
- }
+ const gchar *file_name;
+ gchar *tmp;
- if ((dp = g_dir_open(".", 0, NULL)) == NULL) {
- g_warning("failed to open directory: %s\n", dir);
- g_free(prev_dir);
+ if ((dp = g_dir_open(dir, 0, NULL)) == NULL) {
+ g_warning("failed to open directory: %s", dir);
return -1;
}
- while ((dir_name = g_dir_read_name(dp)) != NULL) {
- if (claws_unlink(dir_name) < 0)
- FILE_OP_ERROR(dir_name, "unlink");
+ while ((file_name = g_dir_read_name(dp)) != NULL) {
+ tmp = g_strconcat(dir, G_DIR_SEPARATOR_S, file_name, NULL);
+ if (claws_unlink(tmp) < 0)
+ FILE_OP_ERROR(tmp, "unlink");
+ g_free(tmp);
}
g_dir_close(dp);
- if (g_chdir(prev_dir) < 0) {
- FILE_OP_ERROR(prev_dir, "chdir");
- g_free(prev_dir);
- return -1;
- }
-
- g_free(prev_dir);
-
return 0;
}
}
if ((dp = g_dir_open(".", 0, NULL)) == NULL) {
- g_warning("failed to open directory: %s\n", dir);
+ g_warning("failed to open directory: %s", dir);
g_free(prev_dir);
return -1;
}
gint file_no;
GHashTable *wanted_files;
GSList *cur;
+ GError *error = NULL;
if (numberlist == NULL)
return 0;
return -1;
}
- if ((dp = g_dir_open(".", 0, NULL)) == NULL) {
- FILE_OP_ERROR(dir, "opendir");
+ if ((dp = g_dir_open(".", 0, &error)) == NULL) {
+ g_message("Couldn't open current directory: %s (%d).\n",
+ error->message, error->code);
+ g_error_free(error);
g_free(prev_dir);
return -1;
}
gint remove_dir_recursive(const gchar *dir)
{
- struct stat s;
+ GStatBuf s;
GDir *dp;
const gchar *dir_name;
gchar *prev_dir;
if (g_stat(dir, &s) < 0) {
FILE_OP_ERROR(dir, "stat");
if (ENOENT == errno) return 0;
- return -1;
+ return -(errno);
}
if (!S_ISDIR(s.st_mode)) {
if (claws_unlink(dir) < 0) {
FILE_OP_ERROR(dir, "unlink");
- return -1;
+ return -(errno);
}
return 0;
g_free(prev_dir);
if (g_chdir("..") < 0) {
FILE_OP_ERROR(dir, "chdir");
- return -1;
+ return -(errno);
}
prev_dir = g_get_current_dir();
}
if (g_chdir(dir) < 0) {
FILE_OP_ERROR(dir, "chdir");
g_free(prev_dir);
- return -1;
+ return -(errno);
}
if ((dp = g_dir_open(".", 0, NULL)) == NULL) {
- g_warning("failed to open directory: %s\n", dir);
+ g_warning("failed to open directory: %s", dir);
g_chdir(prev_dir);
g_free(prev_dir);
- return -1;
+ return -(errno);
}
/* remove all files in the directory */
/* g_print("removing %s\n", dir_name); */
if (is_dir_exist(dir_name)) {
- if (remove_dir_recursive(dir_name) < 0) {
- g_warning("can't remove directory\n");
- return -1;
+ gint ret;
+
+ if ((ret = remove_dir_recursive(dir_name)) < 0) {
+ g_warning("can't remove directory: %s", dir_name);
+ return ret;
}
} else {
if (claws_unlink(dir_name) < 0)
if (g_chdir(prev_dir) < 0) {
FILE_OP_ERROR(prev_dir, "chdir");
g_free(prev_dir);
- return -1;
+ return -(errno);
}
g_free(prev_dir);
if (g_rmdir(dir) < 0) {
FILE_OP_ERROR(dir, "rmdir");
- return -1;
+ return -(errno);
}
return 0;
if (change_file_mode_rw(dest_fp, dest) < 0) {
FILE_OP_ERROR(dest, "chmod");
- g_warning("can't change file mode\n");
+ 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.\n", dest);
+ g_warning("writing to %s failed.", dest);
fclose(dest_fp);
fclose(src_fp);
claws_unlink(dest);
if (change_file_mode_rw(dest_fp, dest) < 0) {
FILE_OP_ERROR(dest, "chmod");
- g_warning("can't change file mode\n");
+ 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.\n", dest);
+ g_warning("writing to %s failed.", dest);
fclose(dest_fp);
fclose(src_fp);
claws_unlink(dest);
if (change_file_mode_rw(dest_fp, dest) < 0) {
FILE_OP_ERROR(dest, "chmod");
- g_warning("can't change file mode\n");
+ g_warning("can't change file mode: %s", dest);
}
if (copy_file_part_to_fp(fp, offset, length, dest_fp) < 0)
}
if (err) {
- g_warning("writing to %s failed.\n", dest);
+ g_warning("writing to %s failed.", dest);
claws_unlink(dest);
return -1;
}
if (change_file_mode_rw(dest_fp, dest) < 0) {
FILE_OP_ERROR(dest, "chmod");
- g_warning("can't change file mode\n");
+ g_warning("can't change file mode: %s", dest);
}
while (fgets(buf, sizeof(buf), src_fp) != NULL) {
}
if (r == EOF) {
- g_warning("writing to %s failed.\n", dest);
+ g_warning("writing to %s failed.", dest);
fclose(dest_fp);
fclose(src_fp);
claws_unlink(dest);
}
if (move_file(tmp_file, file, TRUE) < 0) {
- g_warning("can't replace %s .\n", file);
+ g_warning("can't replace file: %s", file);
claws_unlink(tmp_file);
g_free(tmp_file);
return -1;
FILE *my_tmpfile(void)
{
-#if HAVE_MKSTEMP || defined(G_OS_WIN32)
const gchar suffix[] = ".XXXXXX";
const gchar *tmpdir;
guint tmplen;
memcpy(fname + tmplen + 1, progname, proglen);
memcpy(fname + tmplen + 1 + proglen, suffix, sizeof(suffix));
- fd = mkstemp(fname);
+ fd = g_mkstemp(fname);
if (fd < 0)
return tmpfile();
return fp;
}
-#endif /* HAVE_MKSTEMP || G_OS_WIN32 */
-
return tmpfile();
}
FILE *get_tmpfile_in_dir(const gchar *dir, gchar **filename)
{
int fd;
-#ifdef G_OS_WIN32
- char *template = g_strdup_printf ("%s%cclaws.XXXXXX",
- dir, G_DIR_SEPARATOR);
- fd = mkstemp_name(template, filename);
- g_free(template);
-#else
*filename = g_strdup_printf("%s%cclaws.XXXXXX", dir, G_DIR_SEPARATOR);
- fd = mkstemp(*filename);
+ fd = g_mkstemp(*filename);
if (fd < 0)
return NULL;
-#endif
return fdopen(fd, "w+");
}
{
FILE *fp;
gchar *str;
- struct stat s;
+ GStatBuf s;
#ifndef G_OS_WIN32
gint fd, err;
struct timeval timeout = {1, 0};
return NULL;
}
if (S_ISDIR(s.st_mode)) {
- g_warning("%s: is a directory\n", file);
+ g_warning("%s: is a directory", file);
return NULL;
}
if (err < 0) {
FILE_OP_ERROR(file, "select");
} else {
- g_warning("%s: doesn't seem readable\n", file);
+ g_warning("%s: doesn't seem readable", file);
}
close(fd);
return NULL;
return buf;
}
-static gint execute_async(gchar *const argv[])
+static gint execute_async(gchar *const argv[], const gchar *working_directory)
{
cm_return_val_if_fail(argv != NULL && argv[0] != NULL, -1);
- if (g_spawn_async(NULL, (gchar **)argv, NULL, G_SPAWN_SEARCH_PATH,
+ if (g_spawn_async(working_directory, (gchar **)argv, NULL, G_SPAWN_SEARCH_PATH,
NULL, NULL, NULL, FALSE) == FALSE) {
- g_warning("Couldn't execute command: %s\n", argv[0]);
+ g_warning("couldn't execute command: %s", argv[0]);
return -1;
}
return 0;
}
-static gint execute_sync(gchar *const argv[])
+static gint execute_sync(gchar *const argv[], const gchar *working_directory)
{
gint status;
cm_return_val_if_fail(argv != NULL && argv[0] != NULL, -1);
#ifdef G_OS_UNIX
- if (g_spawn_sync(NULL, (gchar **)argv, NULL, G_SPAWN_SEARCH_PATH,
+ if (g_spawn_sync(working_directory, (gchar **)argv, NULL, G_SPAWN_SEARCH_PATH,
NULL, NULL, NULL, NULL, &status, NULL) == FALSE) {
- g_warning("Couldn't execute command: %s\n", argv[0]);
+ g_warning("couldn't execute command: %s", argv[0]);
return -1;
}
else
return -1;
#else
- if (g_spawn_sync(NULL, (gchar **)argv, NULL, G_SPAWN_SEARCH_PATH|
- G_SPAWN_CHILD_INHERITS_STDIN|G_SPAWN_LEAVE_DESCRIPTORS_OPEN,
+ if (g_spawn_sync(working_directory, (gchar **)argv, NULL,
+ G_SPAWN_SEARCH_PATH|
+ G_SPAWN_CHILD_INHERITS_STDIN|
+ G_SPAWN_LEAVE_DESCRIPTORS_OPEN,
NULL, NULL, NULL, NULL, &status, NULL) == FALSE) {
- g_warning("Couldn't execute command: %s\n", argv[0]);
+ g_warning("couldn't execute command: %s", argv[0]);
return -1;
}
#endif
}
-gint execute_command_line(const gchar *cmdline, gboolean async)
+gint execute_command_line(const gchar *cmdline, gboolean async,
+ const gchar *working_directory)
{
gchar **argv;
gint ret;
argv = strsplit_with_quote(cmdline, " ", 0);
if (async)
- ret = execute_async(argv);
+ ret = execute_async(argv, working_directory);
else
- ret = execute_sync(argv);
+ ret = execute_sync(argv, working_directory);
g_strfreev(argv);
if (g_spawn_command_line_sync(cmdline, &child_stdout, NULL, &status,
NULL) == FALSE) {
- g_warning("Couldn't execute command: %s\n", cmdline);
+ g_warning("couldn't execute command: %s", cmdline);
return NULL;
}
g_snprintf(buf, sizeof(buf), DEFAULT_BROWSER_CMD, encoded_uri);
}
- execute_command_line(buf, TRUE);
+ execute_command_line(buf, TRUE, NULL);
#else
ShellExecute(NULL, "open", uri, NULL, NULL, SW_SHOW);
#endif
g_snprintf(buf, sizeof(buf), DEFAULT_EDITOR_CMD, filepath);
}
- execute_command_line(buf, TRUE);
+ execute_command_line(buf, TRUE, NULL);
return 0;
}
if (c == '-')
remoteoffset = -remoteoffset;
} else if (!strncmp(zone, "UT" , 2) ||
- !strncmp(zone, "GMT", 2)) {
+ !strncmp(zone, "GMT", 3)) {
remoteoffset = 0;
} else if (strlen(zone3) == 3) {
for (p = ustzstr; *p != '\0'; p += 3) {
return offset_string;
}
-void get_rfc822_date(gchar *buf, gint len)
+static void _get_rfc822_date(gchar *buf, gint len, gboolean hidetz)
{
struct tm *lt;
time_t t;
day, mon, &dd, &hh, &mm, &ss, &yyyy);
g_snprintf(buf, len, "%s, %d %s %d %02d:%02d:%02d %s",
- day, dd, mon, yyyy, hh, mm, ss, tzoffset(&t));
+ day, dd, mon, yyyy, hh, mm, ss, (hidetz? "-0000": tzoffset(&t)));
+}
+
+void get_rfc822_date(gchar *buf, gint len)
+{
+ _get_rfc822_date(buf, len, FALSE);
+}
+
+void get_rfc822_date_hide_tz(gchar *buf, gint len)
+{
+ _get_rfc822_date(buf, len, TRUE);
}
void debug_set_mode(gboolean mode)
g_hash_table_remove(subject_table, subject);
}
-#ifndef G_OS_WIN32
static regex_t u_regex;
static gboolean u_init_;
-#endif
void utils_free_regex(void)
{
-#ifndef G_OS_WIN32
if (u_init_) {
regfree(&u_regex);
u_init_ = FALSE;
}
-#endif
}
/*!
*/
int subject_get_prefix_length(const gchar *subject)
{
-#ifndef G_OS_WIN32
/*!< Array with allowable reply prefixes regexps. */
static const gchar * const prefixes[] = {
"Re\\:", /* "Re:" */
return pos.rm_eo;
else
return 0;
-#else
- /*!< Array with allowable reply prefixes regexps. */
- static const gchar * const prefixes[] = {
- "re:", /* "Re:" */
- "antw:", /* "Antw:" (Dutch / German Outlook) */
- "aw:", /* "Aw:" (German) */
- "antwort:", /* "Antwort:" (German Lotus Notes) */
- "res:", /* "Res:" (Spanish/Brazilian Outlook) */
- "fw:", /* "Fw:" Forward */
- "fwd:", /* "Fwd:" Forward */
- "enc:", /* "Enc:" Forward (Brazilian Outlook) */
- "odp:", /* "Odp:" Re (Polish Outlook) */
- "rif:", /* "Rif:" (Italian Outlook) */
- "sv:", /* "Sv" (Norwegian) */
- "vs:", /* "Vs" (Norwegian) */
- "ad:", /* "Ad" (Norwegian) */
- "R\303\251f. :", /* "R�f. :" (French Lotus Notes) */
- "Re :", /* "Re :" (French Yahoo Mail) */
- /* add more */
- };
- const int PREFIXES = sizeof prefixes / sizeof prefixes[0];
- int n;
-
- if (!subject) return 0;
- if (!*subject) return 0;
-
- for (n = 0; n < PREFIXES; n++) {
- int len = strlen(prefixes[n]);
- if (!strncasecmp(subject, prefixes[n], len)) {
- if (subject[len] == ' ')
- return len+1;
- else
- return len;
- }
- }
- return 0;
-#endif
}
+
static guint g_stricase_hash(gconstpointer gptr)
{
guint hash_result = 0;
return GPOINTER_TO_INT(a) - GPOINTER_TO_INT(b);
}
-gchar *generate_msgid(gchar *buf, gint len, gchar *user_addr)
-{
- struct tm *lt;
- time_t t;
- gchar *addr;
- struct tm buft;
-
- t = time(NULL);
- lt = localtime_r(&t, &buft);
-
- if (user_addr != NULL)
- addr = g_strdup_printf(".%s", user_addr);
- else if (strlen(buf) != 0)
- addr = g_strdup_printf("@%s", buf);
- else
- addr = g_strdup_printf("@%s", get_domain_name());
-
- /* Replace all @ but the last one in addr, with underscores.
- * RFC 2822 States that msg-id syntax only allows one @.
- */
- while (strchr(addr, '@') != NULL && strchr(addr, '@') != strrchr(addr, '@'))
- *(strchr(addr, '@')) = '_';
-
- g_snprintf(buf, len, "%04d%02d%02d%02d%02d%02d.%08x%s",
- lt->tm_year + 1900, lt->tm_mon + 1,
- lt->tm_mday, lt->tm_hour,
- lt->tm_min, lt->tm_sec,
- (guint) rand(), addr);
-
- g_free(addr);
- return buf;
-}
-
/*
quote_cmd_argument()
static GHashTable *create_domain_tab(void)
{
- static const gchar *toplvl_domains [] = {
- "museum", "aero",
- "arpa", "coop", "info", "name", "biz", "com", "edu", "gov",
- "int", "mil", "net", "org", "ac", "ad", "ae", "af", "ag",
- "ai", "al", "am", "an", "ao", "aq", "ar", "as", "at", "au",
- "aw", "az", "ba", "bb", "bd", "be", "bf", "bg", "bh", "bi",
- "bj", "bm", "bn", "bo", "br", "bs", "bt", "bv", "bw", "by",
- "bz", "ca", "cc", "cd", "cf", "cg", "ch", "ci", "ck", "cl",
- "cm", "cn", "co", "cr", "cu", "cv", "cx", "cy", "cz", "de",
- "dj", "dk", "dm", "do", "dz", "ec", "ee", "eg", "eh", "er",
- "es", "et", "eu", "fi", "fj", "fk", "fm", "fo", "fr", "ga", "gd",
- "ge", "gf", "gg", "gh", "gi", "gl", "gm", "gn", "gp", "gq",
- "gr", "gs", "gt", "gu", "gw", "gy", "hk", "hm", "hn", "hr",
- "ht", "hu", "id", "ie", "il", "im", "in", "io", "iq", "ir",
- "is", "it", "je", "jm", "jo", "jp", "ke", "kg", "kh", "ki",
- "km", "kn", "kp", "kr", "kw", "ky", "kz", "la", "lb", "lc",
- "li", "lk", "lr", "ls", "lt", "lu", "lv", "ly", "ma", "mc",
- "md", "mg", "mh", "mk", "ml", "mm", "mn", "mo", "mp", "mq",
- "mr", "ms", "mt", "mu", "mv", "mw", "mx", "my", "mz", "na",
- "nc", "ne", "nf", "ng", "ni", "nl", "no", "np", "nr", "nu",
- "nz", "om", "pa", "pe", "pf", "pg", "ph", "pk", "pl", "pm",
- "pn", "pr", "ps", "pt", "pw", "py", "qa", "re", "ro", "ru",
- "rw", "sa", "sb", "sc", "sd", "se", "sg", "sh", "si", "sj",
- "sk", "sl", "sm", "sn", "so", "sr", "st", "sv", "sy", "sz",
- "tc", "td", "tf", "tg", "th", "tj", "tk", "tm", "tn", "to",
- "tp", "tr", "tt", "tv", "tw", "tz", "ua", "ug", "uk", "um",
- "us", "uy", "uz", "va", "vc", "ve", "vg", "vi", "vn", "vu",
- "wf", "ws", "ye", "yt", "yu", "za", "zm", "zw"
- };
gint n;
GHashTable *htab = g_hash_table_new(g_stricase_hash, g_stricase_equal);
* uri type later on in the button_pressed signal handler */
gchar *tmp;
gchar *result;
+ gchar *colon, *at;
tmp = g_strndup(bp, ep - bp);
- result = g_strconcat("mailto:", tmp, NULL);
- g_free(tmp);
+
+ /* If there is a colon in the username part of the address,
+ * we're dealing with an URI for some other protocol - do
+ * not prefix with mailto: in such case. */
+ colon = strchr(tmp, ':');
+ at = strchr(tmp, '@');
+ if (colon != NULL && at != NULL && colon < at) {
+ result = tmp;
+ } else {
+ result = g_strconcat("mailto:", tmp, NULL);
+ g_free(tmp);
+ }
return result;
}
result = g_strdup(trimmed);
g_strfreev(parts);
fclose(fp);
- /* if there are no single quotes around %s, add them.
- * '.*%s.*' is ok, as in display 'png:%s'
- */
- if (strstr(result, "%s")
- && !(strstr(result, "'") < strstr(result,"%s") &&
- strstr(strstr(result,"%s"), "'"))) {
- gchar *start = g_strdup(result);
- gchar *end = g_strdup(strstr(result, "%s")+2);
- gchar *tmp;
- *strstr(start, "%s") = '\0';
- tmp = g_strconcat(start,"'%s'",end, NULL);
- g_free(start);
- g_free(end);
- g_free(result);
- result = tmp;
- }
if (needsterminal) {
gchar *tmp = g_strdup_printf("xterm -e %s", result);
g_free(result);
if (!fp) {
fp = g_fopen(path, "a");
if (!fp) {
- g_warning("failed to create file %s\n", path);
+ g_warning("failed to create file %s", path);
g_free(path);
g_free(outpath);
return;
}
fp = g_freopen(path, "rb", fp);
if (!fp) {
- g_warning("failed to reopen file %s\n", path);
+ g_warning("failed to reopen file %s", path);
g_free(path);
g_free(outpath);
return;
outfp = g_fopen(outpath, "wb");
if (!outfp) {
- g_warning("failed to create file %s\n", outpath);
+ g_warning("failed to create file %s", outpath);
g_free(path);
g_free(outpath);
fclose(fp);
const gchar *name;
if ((dir = g_dir_open(src, 0, NULL)) == NULL) {
- g_warning("failed to open directory: %s\n", src);
+ g_warning("failed to open directory: %s", src);
return -1;
}
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;
+ GError *error = NULL;
gint r = 0;
gchar *target = g_file_read_link(old_file, &error);
if (target)
if ((fp = g_fopen(filename, "rb")) == NULL)
return FALSE;
while (i < 60 && score < 3
- && fgets(buffer, sizeof (buffer), fp) > 0) {
+ && fgets(buffer, sizeof (buffer), fp) != NULL) {
if (!strncmp(buffer, "From:", strlen("From:")))
score++;
else if (!strncmp(buffer, "Date:", strlen("Date:")))
*curpos++ = '0'+(lt->tm_min % 10);
break;
case 's':
- snprintf(subbuf, 64, "%ld", mktime(lt));
+ snprintf(subbuf, 64, "%lld", (long long)mktime(lt));
len = strlen(subbuf); CHECK_SIZE();
strncpy2(curpos, subbuf, buflen - total_done);
break;
int claws_unlink(const gchar *filename)
{
- struct stat s;
+ GStatBuf s;
static int found_shred = -1;
static const gchar *args[4];
debug_print("%s %s exited with status %d\n",
args[0], filename, WEXITSTATUS(status));
if (truncate(filename, 0) < 0)
- g_warning("couln't truncate");
+ g_warning("couln't truncate: %s", filename);
}
}
}
{
gchar **path_parts;
GSList *canonical_parts = NULL;
- struct stat st;
+ GStatBuf st;
int i;
gboolean follow_symlinks = TRUE;
return 0;
}
+/* Returns a decoded base64 string, guaranteed to be null-terminated. */
+guchar *g_base64_decode_zero(const gchar *text, gsize *out_len)
+{
+ gchar *tmp = g_base64_decode(text, out_len);
+ gchar *out = g_strndup(tmp, *out_len);
+
+ g_free(tmp);
+
+ if (strlen(out) != *out_len) {
+ g_warning ("strlen(out) %zd != *out_len %" G_GSIZE_FORMAT, strlen(out), *out_len);
+ }
+
+ return out;
+}
+
#if !GLIB_CHECK_VERSION(2, 30, 0)
/**
* g_utf8_substring:
return out;
}
#endif
+
+/* Attempts to read count bytes from a PRNG into memory area starting at buf.
+ * It is up to the caller to make sure there is at least count bytes
+ * available at buf. */
+gboolean
+get_random_bytes(void *buf, size_t count)
+{
+ /* Open our prng source. */
+#if defined G_OS_WIN32
+ HCRYPTPROV rnd;
+
+ if (!CryptAcquireContext(&rnd, NULL, NULL, PROV_RSA_FULL, 0) &&
+ !CryptAcquireContext(&rnd, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET)) {
+ debug_print("Could not acquire a CSP handle.\n");
+ return FALSE;
+ }
+#else
+ int rnd;
+ ssize_t ret;
+
+ rnd = open("/dev/urandom", O_RDONLY);
+ if (rnd == -1) {
+ perror("open on /dev/urandom");
+ debug_print("Could not open /dev/urandom.\n");
+ return FALSE;
+ }
+#endif
+
+ /* Read data from the source into buf. */
+#if defined G_OS_WIN32
+ if (!CryptGenRandom(rnd, count, buf)) {
+ debug_print("Could not read %d random bytes.\n", count);
+ CryptReleaseContext(rnd, 0);
+ return FALSE;
+ }
+#else
+ ret = read(rnd, buf, count);
+ if (ret != count) {
+ perror("read from /dev/urandom");
+ debug_print("Could not read enough data from /dev/urandom, read only %ld of %lu bytes.\n", ret, count);
+ close(rnd);
+ return FALSE;
+ }
+#endif
+
+ /* Close the prng source. */
+#if defined G_OS_WIN32
+ CryptReleaseContext(rnd, 0);
+#else
+ close(rnd);
+#endif
+
+ return TRUE;
+}