/*
* Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 1999-2016 Hiroyuki Yamamoto & The Claws Mail Team
+ * Copyright (C) 1999-2020 The Claws Mail Team and Hiroyuki Yamamoto
*
* 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
#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)
return str;
}
+#ifndef HAVE_STRCASESTR
/* Similar to `strstr' but this function ignores the case of both strings. */
gchar *strcasestr(const gchar *haystack, const gchar *needle)
{
return strncasestr(haystack, haystack_len, needle);
}
+#endif /* HAVE_STRCASESTR */
gchar *strncasestr(const gchar *haystack, gint haystack_len, const gchar *needle)
{
len = g_unichar_to_utf8(c, NULL);
- if (!g_unichar_isdefined(c) || !g_unichar_isprint(c) ||
- g_unichar_isspace(c)) {
+ if ((!g_unichar_isdefined(c) || !g_unichar_isprint(c) ||
+ g_unichar_isspace(c)) && c != 173) {
/* replace anything bad or whitespacey with a single space */
*ch = ' ';
ch++;
"../",
NULL };
gint num_attach = 0;
- gchar **my_att = NULL;
+
+ cm_return_val_if_fail(mailto != NULL, -1);
Xstrdup_a(tmp_mailto, mailto, return -1);
if (to && !*to)
*to = decode_uri_gdup(tmp_mailto);
- my_att = g_malloc(sizeof(char *));
- my_att[0] = NULL;
-
while (p) {
gchar *field, *value;
} else {
gchar *tmp = decode_uri_gdup(value);
gchar *new_from = g_strdup_printf("%s, %s", *from, tmp);
+ g_free(tmp);
g_free(*from);
*from = new_from;
}
} else {
gchar *tmp = decode_uri_gdup(value);
gchar *new_cc = g_strdup_printf("%s, %s", *cc, tmp);
+ g_free(tmp);
g_free(*cc);
*cc = new_cc;
}
} else {
gchar *tmp = decode_uri_gdup(value);
gchar *new_bcc = g_strdup_printf("%s, %s", *bcc, tmp);
+ g_free(tmp);
g_free(*bcc);
*bcc = new_bcc;
}
} else if (body && !*body && !g_ascii_strcasecmp(field, "body")) {
*body = decode_uri_gdup(value);
} else if (body && !*body && !g_ascii_strcasecmp(field, "insert")) {
+ int i = 0;
gchar *tmp = decode_uri_gdup(value);
- if (!g_file_get_contents(tmp, body, NULL, NULL)) {
- g_warning("couldn't set insert file '%s' in body", value);
+
+ for (; forbidden_uris[i]; i++) {
+ if (strstr(tmp, forbidden_uris[i])) {
+ g_print("Refusing to insert '%s', potential private data leak\n",
+ tmp);
+ g_free(tmp);
+ tmp = NULL;
+ break;
+ }
+ }
+
+ if (tmp) {
+ if (!is_file_entry_regular(tmp)) {
+ g_warning("Refusing to insert '%s', not a regular file\n", tmp);
+ } else if (!g_file_get_contents(tmp, body, NULL, NULL)) {
+ g_warning("couldn't set insert file '%s' in body", value);
+ }
+
+ g_free(tmp);
}
- g_free(tmp);
} else if (attach && !g_ascii_strcasecmp(field, "attach")) {
int i = 0;
gchar *tmp = decode_uri_gdup(value);
+ gchar **my_att = g_malloc(sizeof(char *));
+
+ my_att[0] = NULL;
+
for (; forbidden_uris[i]; i++) {
if (strstr(tmp, forbidden_uris[i])) {
g_print("Refusing to attach '%s', potential private data leak\n",
tmp);
g_free(tmp);
+ g_free(my_att);
+ tmp = NULL;
break;
}
}
my_att = g_realloc(my_att, (sizeof(char *))*(num_attach+1));
my_att[num_attach-1] = tmp;
my_att[num_attach] = NULL;
+ *attach = my_att;
}
} else if (inreplyto && !*inreplyto &&
!g_ascii_strcasecmp(field, "in-reply-to")) {
}
}
- if (attach)
- *attach = my_att;
return 0;
}
#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
return g_file_test(file, G_FILE_TEST_EXISTS);
}
+gboolean is_file_entry_regular(const gchar *file)
+{
+ if (file == NULL)
+ return FALSE;
+
+ return g_file_test(file, G_FILE_TEST_IS_REGULAR);
+}
+
gboolean dirent_is_regular_file(struct dirent *d)
{
#if !defined(G_OS_WIN32) && defined(HAVE_DIRENT_D_TYPE)
static gboolean is_toplvl_domain(GHashTable *tab, const gchar *first, const gchar *last)
{
- const gint MAX_LVL_DOM_NAME_LEN = 6;
- gchar buf[MAX_LVL_DOM_NAME_LEN + 1];
- const gchar *m = buf + MAX_LVL_DOM_NAME_LEN + 1;
+ gchar buf[BUFFSIZE + 1];
+ const gchar *m = buf + BUFFSIZE + 1;
register gchar *p;
- if (last - first > MAX_LVL_DOM_NAME_LEN || first > last)
+ if (last - first > BUFFSIZE || first > last)
return FALSE;
for (p = buf; p < m && first < last; *p++ = *first++)
}
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;
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;
/* 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;
}
return TRUE;
}
+#ifdef G_OS_WIN32
+gchar *win32_debug_log_path(void)
+{
+ return g_strconcat(g_get_tmp_dir(), G_DIR_SEPARATOR_S,
+ "claws-win32.log", NULL);
+}
+#endif