[Commits] [SCM] claws branch, master, updated. 3.14.1-139-g989b3a3
wwp at claws-mail.org
wwp at claws-mail.org
Mon Jan 16 16:44:02 CET 2017
The branch, master has been updated
via 989b3a3f51c691b0bb0fd48521063a8c76d269ce (commit)
from 18227b9fc9164e9dd730a94c70095f70855cf9e3 (commit)
Summary of changes:
src/account.c | 14 +--
src/common/utils.c | 2 -
src/compose.c | 189 +++++++++++++++++++--------------
src/filtering.c | 6 +-
src/matcher.c | 17 +--
src/messageview.c | 65 +++++++-----
src/plugins/perl/perl_plugin.c | 14 +--
src/plugins/python/messageinfotype.c | 8 +-
src/plugins/spam_report/spam_report.c | 6 +-
src/procheader.c | 176 +++++++++++++++++++++++-------
src/procheader.h | 12 +--
src/procmsg.c | 15 +--
12 files changed, 338 insertions(+), 186 deletions(-)
- Log -----------------------------------------------------------------
commit 989b3a3f51c691b0bb0fd48521063a8c76d269ce
Author: wwp <wwp at free.fr>
Date: Mon Jan 16 16:35:13 2017 +0100
Fix bug 3571, 'recipient list lost and truncated'
by replacing lots of fixed-size buffers with dynamically
allocated ones.
Also enforce checks by adding or fixing few sanity tests,
fix returned value of some functions in some tricky cases.
diff --git a/src/account.c b/src/account.c
index 9c34f97..9c44ef0 100644
--- a/src/account.c
+++ b/src/account.c
@@ -1402,13 +1402,14 @@ PrefsAccount *account_get_reply_account(MsgInfo *msginfo, gboolean reply_autosel
else if (folder_has_parent_of_type(msginfo->folder, F_QUEUE) ||
folder_has_parent_of_type(msginfo->folder, F_OUTBOX) ||
folder_has_parent_of_type(msginfo->folder, F_DRAFT)) {
- gchar from[BUFFSIZE];
+ gchar *from = NULL;
if (!procheader_get_header_from_msginfo
- (msginfo, from, sizeof from, "From:")) {
+ (msginfo, &from, "From:")) {
gchar *buf = from + strlen("From:");
extract_address(buf);
account = account_find_from_address(buf, FALSE);
- }
+ g_free(from);
+ }
}
/* select account by to: and cc: header if enabled */
if (reply_autosel) {
@@ -1438,13 +1439,14 @@ PrefsAccount *account_get_reply_account(MsgInfo *msginfo, gboolean reply_autosel
}
}
if (!account) {
- gchar deliveredto[BUFFSIZE];
+ gchar *deliveredto = NULL;
if (!procheader_get_header_from_msginfo
- (msginfo, deliveredto,sizeof deliveredto , "Delivered-To:")) {
+ (msginfo, &deliveredto, "Delivered-To:")) {
gchar *buf = deliveredto + strlen("Delivered-To:");
extract_address(buf);
account = account_find_from_address(buf, FALSE);
- }
+ g_free(deliveredto);
+ }
}
}
diff --git a/src/common/utils.c b/src/common/utils.c
index 10c3764..b13d09a 100644
--- a/src/common/utils.c
+++ b/src/common/utils.c
@@ -1604,7 +1604,6 @@ gint scan_mailto_url(const gchar *mailto, gchar **from, gchar **to, gchar **cc,
g_warning("couldn't set insert file '%s' in body", value);
}
g_free(tmp);
- tmp = NULL;
} else if (attach && !g_ascii_strcasecmp(field, "attach")) {
int i = 0;
gchar *tmp = decode_uri_gdup(value);
@@ -1613,7 +1612,6 @@ gint scan_mailto_url(const gchar *mailto, gchar **from, gchar **to, gchar **cc,
g_print("Refusing to attach '%s', potential private data leak\n",
tmp);
g_free(tmp);
- tmp = NULL;
break;
}
}
diff --git a/src/compose.c b/src/compose.c
index bdb14b4..3308f3c 100644
--- a/src/compose.c
+++ b/src/compose.c
@@ -2224,7 +2224,6 @@ Compose *compose_reedit(MsgInfo *msginfo, gboolean batch)
GtkTextMark *mark;
GtkTextIter iter;
FILE *fp;
- gchar buf[BUFFSIZE];
gboolean use_signing = FALSE;
gboolean use_encryption = FALSE;
gchar *privacy_system = NULL;
@@ -2244,124 +2243,141 @@ Compose *compose_reedit(MsgInfo *msginfo, gboolean batch)
if (folder_has_parent_of_type(msginfo->folder, F_QUEUE) ||
folder_has_parent_of_type(msginfo->folder, F_DRAFT) ||
folder_has_parent_of_type(msginfo->folder, F_OUTBOX)) {
- gchar queueheader_buf[BUFFSIZE];
+ gchar *queueheader_buf = NULL;
gint id, param;
/* Select Account from queue headers */
- if (!procheader_get_header_from_msginfo(msginfo, queueheader_buf,
- sizeof(queueheader_buf), "X-Claws-Account-Id:")) {
+ if (!procheader_get_header_from_msginfo(msginfo, &queueheader_buf,
+ "X-Claws-Account-Id:")) {
id = atoi(&queueheader_buf[strlen("X-Claws-Account-Id:")]);
account = account_find_from_id(id);
+ g_free(queueheader_buf);
}
- if (!procheader_get_header_from_msginfo(msginfo, queueheader_buf,
- sizeof(queueheader_buf), "X-Sylpheed-Account-Id:")) {
+ if (!procheader_get_header_from_msginfo(msginfo, &queueheader_buf,
+ "X-Sylpheed-Account-Id:")) {
id = atoi(&queueheader_buf[strlen("X-Sylpheed-Account-Id:")]);
account = account_find_from_id(id);
+ g_free(queueheader_buf);
}
- if (!account && !procheader_get_header_from_msginfo(msginfo, queueheader_buf,
- sizeof(queueheader_buf), "NAID:")) {
+ if (!account && !procheader_get_header_from_msginfo(msginfo, &queueheader_buf,
+ "NAID:")) {
id = atoi(&queueheader_buf[strlen("NAID:")]);
account = account_find_from_id(id);
+ g_free(queueheader_buf);
}
- if (!account && !procheader_get_header_from_msginfo(msginfo, queueheader_buf,
- sizeof(queueheader_buf), "MAID:")) {
+ if (!account && !procheader_get_header_from_msginfo(msginfo, &queueheader_buf,
+ "MAID:")) {
id = atoi(&queueheader_buf[strlen("MAID:")]);
account = account_find_from_id(id);
+ g_free(queueheader_buf);
}
- if (!account && !procheader_get_header_from_msginfo(msginfo, queueheader_buf,
- sizeof(queueheader_buf), "S:")) {
+ if (!account && !procheader_get_header_from_msginfo(msginfo, &queueheader_buf,
+ "S:")) {
account = account_find_from_address(queueheader_buf, FALSE);
+ g_free(queueheader_buf);
}
- if (!procheader_get_header_from_msginfo(msginfo, queueheader_buf,
- sizeof(queueheader_buf), "X-Claws-Sign:")) {
+ if (!procheader_get_header_from_msginfo(msginfo, &queueheader_buf,
+ "X-Claws-Sign:")) {
param = atoi(&queueheader_buf[strlen("X-Claws-Sign:")]);
use_signing = param;
-
+ g_free(queueheader_buf);
}
- if (!procheader_get_header_from_msginfo(msginfo, queueheader_buf,
- sizeof(queueheader_buf), "X-Sylpheed-Sign:")) {
+ if (!procheader_get_header_from_msginfo(msginfo, &queueheader_buf,
+ "X-Sylpheed-Sign:")) {
param = atoi(&queueheader_buf[strlen("X-Sylpheed-Sign:")]);
use_signing = param;
-
+ g_free(queueheader_buf);
}
- if (!procheader_get_header_from_msginfo(msginfo, queueheader_buf,
- sizeof(queueheader_buf), "X-Claws-Encrypt:")) {
+ if (!procheader_get_header_from_msginfo(msginfo, &queueheader_buf,
+ "X-Claws-Encrypt:")) {
param = atoi(&queueheader_buf[strlen("X-Claws-Encrypt:")]);
use_encryption = param;
+ g_free(queueheader_buf);
}
- if (!procheader_get_header_from_msginfo(msginfo, queueheader_buf,
- sizeof(queueheader_buf), "X-Sylpheed-Encrypt:")) {
+ if (!procheader_get_header_from_msginfo(msginfo, &queueheader_buf,
+ "X-Sylpheed-Encrypt:")) {
param = atoi(&queueheader_buf[strlen("X-Sylpheed-Encrypt:")]);
use_encryption = param;
+ g_free(queueheader_buf);
}
- if (!procheader_get_header_from_msginfo(msginfo, queueheader_buf,
- sizeof(queueheader_buf), "X-Claws-Auto-Wrapping:")) {
+ if (!procheader_get_header_from_msginfo(msginfo, &queueheader_buf,
+ "X-Claws-Auto-Wrapping:")) {
param = atoi(&queueheader_buf[strlen("X-Claws-Auto-Wrapping:")]);
autowrap = param;
+ g_free(queueheader_buf);
}
- if (!procheader_get_header_from_msginfo(msginfo, queueheader_buf,
- sizeof(queueheader_buf), "X-Claws-Auto-Indent:")) {
+ if (!procheader_get_header_from_msginfo(msginfo, &queueheader_buf,
+ "X-Claws-Auto-Indent:")) {
param = atoi(&queueheader_buf[strlen("X-Claws-Auto-Indent:")]);
autoindent = param;
+ g_free(queueheader_buf);
}
- if (!procheader_get_header_from_msginfo(msginfo, queueheader_buf,
- sizeof(queueheader_buf), "X-Claws-Privacy-System:")) {
- privacy_system = g_strdup(&queueheader_buf[strlen("X-Claws-Privacy-System:")]);
- }
- if (!procheader_get_header_from_msginfo(msginfo, queueheader_buf,
- sizeof(queueheader_buf), "X-Sylpheed-Privacy-System:")) {
- privacy_system = g_strdup(&queueheader_buf[strlen("X-Sylpheed-Privacy-System:")]);
- }
- if (!procheader_get_header_from_msginfo(msginfo, queueheader_buf,
- sizeof(queueheader_buf), "X-Priority: ")) {
+ if (!procheader_get_header_from_msginfo(msginfo, &queueheader_buf,
+ "X-Claws-Privacy-System:")) {
+ privacy_system = g_strdup(&queueheader_buf[strlen("X-Claws-Privacy-System:")]);
+ g_free(queueheader_buf);
+ }
+ if (!procheader_get_header_from_msginfo(msginfo, &queueheader_buf,
+ "X-Sylpheed-Privacy-System:")) {
+ privacy_system = g_strdup(&queueheader_buf[strlen("X-Sylpheed-Privacy-System:")]);
+ g_free(queueheader_buf);
+ }
+ if (!procheader_get_header_from_msginfo(msginfo, &queueheader_buf,
+ "X-Priority: ")) {
param = atoi(&queueheader_buf[strlen("X-Priority: ")]); /* mind the space */
priority = param;
+ g_free(queueheader_buf);
}
- if (!procheader_get_header_from_msginfo(msginfo, queueheader_buf,
- sizeof(queueheader_buf), "RMID:")) {
+ if (!procheader_get_header_from_msginfo(msginfo, &queueheader_buf,
+ "RMID:")) {
gchar **tokens = g_strsplit(&queueheader_buf[strlen("RMID:")], "\t", 0);
- if (tokens[0] && tokens[1] && tokens[2]) {
+ if (tokens && tokens[0] && tokens[1] && tokens[2]) {
FolderItem *orig_item = folder_find_item_from_identifier(tokens[0]);
if (orig_item != NULL) {
replyinfo = folder_item_get_msginfo_by_msgid(orig_item, tokens[2]);
}
+ g_strfreev(tokens);
}
- g_strfreev(tokens);
+ g_free(queueheader_buf);
}
- if (!procheader_get_header_from_msginfo(msginfo, queueheader_buf,
- sizeof(queueheader_buf), "FMID:")) {
+ if (!procheader_get_header_from_msginfo(msginfo, &queueheader_buf,
+ "FMID:")) {
gchar **tokens = g_strsplit(&queueheader_buf[strlen("FMID:")], "\t", 0);
- if (tokens[0] && tokens[1] && tokens[2]) {
+ if (tokens && tokens[0] && tokens[1] && tokens[2]) {
FolderItem *orig_item = folder_find_item_from_identifier(tokens[0]);
if (orig_item != NULL) {
fwdinfo = folder_item_get_msginfo_by_msgid(orig_item, tokens[2]);
}
+ g_strfreev(tokens);
}
- g_strfreev(tokens);
+ g_free(queueheader_buf);
}
/* Get manual headers */
- if (!procheader_get_header_from_msginfo(msginfo, queueheader_buf, sizeof(queueheader_buf), "X-Claws-Manual-Headers:")) {
+ if (!procheader_get_header_from_msginfo(msginfo, &queueheader_buf,
+ "X-Claws-Manual-Headers:")) {
gchar *listmh = g_strdup(&queueheader_buf[strlen("X-Claws-Manual-Headers:")]);
- if (*listmh != '\0') {
+ if (listmh && *listmh != '\0') {
debug_print("Got manual headers: %s\n", listmh);
manual_headers = procheader_entries_from_str(listmh);
+ g_free(listmh);
}
- g_free(listmh);
+ g_free(queueheader_buf);
}
} else {
account = msginfo->folder->folder->account;
}
if (!account && prefs_common.reedit_account_autosel) {
- gchar from[BUFFSIZE];
- if (!procheader_get_header_from_msginfo(msginfo, from, sizeof(from), "FROM:")) {
- extract_address(from);
- account = account_find_from_address(from, FALSE);
- }
- }
- if (!account) {
- account = cur_account;
- }
+ gchar *from = NULL;
+ if (!procheader_get_header_from_msginfo(msginfo, &from, "FROM:")) {
+ extract_address(from);
+ account = account_find_from_address(from, FALSE);
+ g_free(from);
+ }
+ }
+ if (!account) {
+ account = cur_account;
+ }
cm_return_val_if_fail(account != NULL, NULL);
compose = compose_create(account, msginfo->folder, COMPOSE_REEDIT, batch);
@@ -2388,21 +2404,23 @@ Compose *compose_reedit(MsgInfo *msginfo, gboolean batch)
compose_extract_original_charset(compose);
- if (folder_has_parent_of_type(msginfo->folder, F_QUEUE) ||
+ if (folder_has_parent_of_type(msginfo->folder, F_QUEUE) ||
folder_has_parent_of_type(msginfo->folder, F_DRAFT) ||
folder_has_parent_of_type(msginfo->folder, F_OUTBOX)) {
- gchar queueheader_buf[BUFFSIZE];
+ gchar *queueheader_buf = NULL;
/* Set message save folder */
- if (!procheader_get_header_from_msginfo(msginfo, queueheader_buf, sizeof(queueheader_buf), "SCF:")) {
+ if (!procheader_get_header_from_msginfo(msginfo, &queueheader_buf, "SCF:")) {
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(compose->savemsg_checkbtn), TRUE);
compose_set_save_to(compose, &queueheader_buf[4]);
+ g_free(queueheader_buf);
}
- if (!procheader_get_header_from_msginfo(msginfo, queueheader_buf, sizeof(queueheader_buf), "RRCPT:")) {
+ if (!procheader_get_header_from_msginfo(msginfo, &queueheader_buf, "RRCPT:")) {
gint active = atoi(&queueheader_buf[strlen("RRCPT:")]);
if (active) {
cm_toggle_menu_set_active_full(compose->ui_manager, "Menu/Options/RequestRetRcpt", TRUE);
}
+ g_free(queueheader_buf);
}
}
@@ -2437,6 +2455,7 @@ Compose *compose_reedit(MsgInfo *msginfo, gboolean batch)
}
if (fp != NULL) {
+ gchar buf[BUFFSIZE];
gboolean prev_autowrap;
GtkTextBuffer *buffer;
BLOCK_WRAP();
@@ -5488,7 +5507,8 @@ static gint compose_redirect_write_to_file(Compose *compose, FILE *fdest)
{
FILE *fp;
size_t len;
- gchar buf[BUFFSIZE];
+ gchar *buf = NULL;
+ gchar rewrite_buf[BUFFSIZE];
int i = 0;
gboolean skip = FALSE;
gboolean err = FALSE;
@@ -5509,24 +5529,34 @@ static gint compose_redirect_write_to_file(Compose *compose, FILE *fdest)
"X-Claws-Auto-Wrapping:", "X-Claws-Auto-Indent:",
NULL
};
+ gint ret = 0;
+
if ((fp = g_fopen(compose->redirect_filename, "rb")) == NULL) {
FILE_OP_ERROR(compose->redirect_filename, "fopen");
return -1;
}
- while (procheader_get_one_field_asis(buf, sizeof(buf), fp) != -1) {
+ while ((ret = procheader_get_one_field_asis(&buf, fp)) != -1) {
skip = FALSE;
for (i = 0; not_included[i] != NULL; i++) {
if (g_ascii_strncasecmp(buf, not_included[i],
strlen(not_included[i])) == 0) {
skip = TRUE;
+ g_free(buf);
+ buf = NULL;
break;
}
}
- if (skip)
+ if (skip) {
+ g_free(buf);
+ buf = NULL;
continue;
- if (fputs(buf, fdest) == -1)
+ }
+ if (fputs(buf, fdest) == -1) {
+ g_free(buf);
+ buf = NULL;
goto error;
+ }
if (!prefs_common.redirect_keep_from) {
if (g_ascii_strncasecmp(buf, "From:",
@@ -5549,24 +5579,27 @@ static gint compose_redirect_write_to_file(Compose *compose, FILE *fdest)
}
}
+ g_free(buf);
+ buf = NULL;
if (fputs("\n", fdest) == -1)
goto error;
}
- if (err)
+ if (err || ret == -1)
goto error;
if (compose_redirect_write_headers(compose, fdest))
goto error;
- while ((len = fread(buf, sizeof(gchar), sizeof(buf), fp)) > 0) {
- if (fwrite(buf, sizeof(gchar), len, fdest) != len)
+ while ((len = fread(rewrite_buf, sizeof(gchar), sizeof(rewrite_buf), fp)) > 0) {
+ if (fwrite(rewrite_buf, sizeof(gchar), len, fdest) != len)
goto error;
}
fclose(fp);
return 0;
+
error:
fclose(fp);
@@ -11813,23 +11846,25 @@ static PrefsAccount *compose_find_account(MsgInfo *msginfo)
}
if (!account && prefs_common.forward_account_autosel) {
- gchar cc[BUFFSIZE];
+ gchar *cc = NULL;
if (!procheader_get_header_from_msginfo
- (msginfo, cc,sizeof cc , "Cc:")) {
+ (msginfo, &cc, "Cc:")) {
gchar *buf = cc + strlen("Cc:");
- extract_address(buf);
- account = account_find_from_address(buf, FALSE);
- }
+ extract_address(buf);
+ account = account_find_from_address(buf, FALSE);
+ g_free(cc);
+ }
}
if (!account && prefs_common.forward_account_autosel) {
- gchar deliveredto[BUFFSIZE];
+ gchar *deliveredto = NULL;
if (!procheader_get_header_from_msginfo
- (msginfo, deliveredto,sizeof deliveredto , "Delivered-To:")) {
+ (msginfo, &deliveredto, "Delivered-To:")) {
gchar *buf = deliveredto + strlen("Delivered-To:");
- extract_address(buf);
- account = account_find_from_address(buf, FALSE);
- }
+ extract_address(buf);
+ account = account_find_from_address(buf, FALSE);
+ g_free(deliveredto);
+ }
}
if (!account)
diff --git a/src/filtering.c b/src/filtering.c
index 7b604a8..e4f3d01 100644
--- a/src/filtering.c
+++ b/src/filtering.c
@@ -473,7 +473,7 @@ static gboolean filteringaction_apply(FilteringAction * action, MsgInfo * info)
AddressBookFile *abf = NULL;
ItemFolder *folder = NULL;
#endif
- gchar buf[BUFFSIZE];
+ gchar *buf;
Header *header;
gint errors = 0;
@@ -490,11 +490,11 @@ static gboolean filteringaction_apply(FilteringAction * action, MsgInfo * info)
abf = book->rawDataSource;
#endif
/* get the header */
- if (procheader_get_header_from_msginfo(info, buf,
- sizeof(buf), action->header) < 0)
+ if (procheader_get_header_from_msginfo(info, &buf, action->header) < 0)
return FALSE;
header = procheader_parse_header(buf);
+ g_free(buf);
/* add all addresses that are not already in */
if (header && *header->body && (*header->body != '\0')) {
diff --git a/src/matcher.c b/src/matcher.c
index 64000e1..89b6232 100644
--- a/src/matcher.c
+++ b/src/matcher.c
@@ -1287,10 +1287,10 @@ void matcherlist_free(MatcherList *cond)
*/
static void matcherlist_skip_headers(FILE *fp)
{
- gchar buf[BUFFSIZE];
+ gchar *buf = NULL;
- while (procheader_get_one_field(buf, sizeof(buf), fp, NULL) != -1)
- ;
+ while (procheader_get_one_field(&buf, fp, NULL) != -1)
+ g_free(buf);
}
/*!
@@ -1470,9 +1470,10 @@ static gboolean matcherprop_criteria_message(MatcherProp *matcher)
static gboolean matcherlist_match_headers(MatcherList *matchers, FILE *fp)
{
GSList *l;
- gchar buf[BUFFSIZE];
+ gchar *buf = NULL;
+ gint ret;
- while (procheader_get_one_field(buf, sizeof(buf), fp, NULL) != -1) {
+ while ((ret = procheader_get_one_field(&buf, fp, NULL)) != -1) {
for (l = matchers->matchers ; l != NULL ; l = g_slist_next(l)) {
MatcherProp *matcher = (MatcherProp *) l->data;
gint match = MATCH_ANY;
@@ -1537,10 +1538,14 @@ static gboolean matcherlist_match_headers(MatcherList *matchers, FILE *fp)
/* if the rule matched and the matchers are OR, no need to
* check the others */
if (matcher->result && matcher->done) {
- if (!matchers->bool_and)
+ if (!matchers->bool_and) {
+ g_free(buf);
return TRUE;
+ }
}
}
+ g_free(buf);
+ buf = NULL;
}
return FALSE;
diff --git a/src/messageview.c b/src/messageview.c
index ac8ab4f..7052ff8 100644
--- a/src/messageview.c
+++ b/src/messageview.c
@@ -771,32 +771,38 @@ void messageview_init(MessageView *messageview)
noticeview_hide(messageview->noticeview);
}
-static void notification_convert_header(gchar *dest, gint len,
+static void notification_convert_header(gchar **dest,
const gchar *src_,
gint header_len)
{
char *src;
cm_return_if_fail(src_ != NULL);
- cm_return_if_fail(dest != NULL);
- if (len < 1) return;
+ if (header_len < 1) {
+ *dest = g_strdup("");
+ return;
+ }
- Xstrndup_a(src, src_, len, return);
+ Xstrndup_a(src, src_, strlen(src_), return);
remove_return(src);
if (is_ascii_str(src)) {
- strncpy2(dest, src, len);
- dest[len - 1] = '\0';
+ *dest = g_strdup(src);
return;
- } else
- conv_encode_header(dest, len, src, header_len, FALSE);
+ } else {
+ *dest = g_malloc(BUFFSIZE);
+ if (*dest)
+ conv_encode_header(*dest, sizeof(dest), src, header_len, FALSE);
+ else
+ debug_print("notification_convert_header: alloc");
+ }
}
static gint disposition_notification_send(MsgInfo *msginfo)
{
- gchar buf[BUFFSIZE];
+ gchar *buf = NULL;
gchar tmp[MAXPATHLEN + 1];
FILE *fp;
GList *ac_list;
@@ -811,6 +817,7 @@ static gint disposition_notification_send(MsgInfo *msginfo)
gchar *foo = NULL;
gboolean queued_removed = FALSE;
gchar *boundary = NULL;
+ gchar buf_date[BUFFSIZE];
gchar *date = NULL;
gchar *orig_to = NULL;
gchar *enc_sub = NULL;
@@ -827,8 +834,7 @@ static gint disposition_notification_send(MsgInfo *msginfo)
else
to = msginfo->extradata->returnreceiptto;
- ok = procheader_get_header_from_msginfo(msginfo, buf, sizeof(buf),
- "Return-Path:");
+ ok = procheader_get_header_from_msginfo(msginfo, &buf, "Return-Path:");
if (ok == 0) {
gchar *to_addr = g_strdup(to);
extract_address(to_addr);
@@ -836,8 +842,7 @@ static gint disposition_notification_send(MsgInfo *msginfo)
ok = strcasecmp(to_addr, buf);
g_free(to_addr);
} else {
- g_strlcpy(buf, _("<No Return-Path found>"),
- sizeof(buf));
+ buf = g_strdup(_("<No Return-Path found>"));
}
if (ok != 0) {
@@ -854,9 +859,13 @@ static gint disposition_notification_send(MsgInfo *msginfo)
_("_Don't Send"), _("_Send"), NULL, FALSE,
NULL, ALERT_WARNING, G_ALERTDEFAULT);
g_free(message);
- if (val != G_ALERTALTERNATE)
+ if (val != G_ALERTALTERNATE) {
+ g_free(buf);
return -1;
+ }
}
+ g_free(buf);
+ buf = NULL;
ac_list = account_find_all_from_address(NULL, msginfo->to);
ac_list = account_find_all_from_address(ac_list, msginfo->cc);
@@ -959,17 +968,21 @@ static gint disposition_notification_send(MsgInfo *msginfo)
goto FILE_ERROR;
/* Date */
- get_rfc822_date(buf, sizeof(buf));
+ get_rfc822_date(buf_date, sizeof(buf_date));
if (fprintf(fp, "Date: %s\n", buf) < 0)
goto FILE_ERROR;
/* From */
if (account->name && *account->name) {
- notification_convert_header
- (buf, sizeof(buf), account->name,
- strlen("From: "));
- if (fprintf(fp, "From: %s <%s>\n", buf, account->address) < 0)
+ notification_convert_header(&buf, account->name, strlen("From: "));
+ if (buf == NULL)
+ goto FILE_ERROR;
+ if (fprintf(fp, "From: %s <%s>\n", buf, account->address) < 0) {
+ g_free(buf);
goto FILE_ERROR;
+ }
+ g_free(buf);
+ buf = NULL;
} else
if (fprintf(fp, "From: %s\n", account->address) < 0)
goto FILE_ERROR;
@@ -978,10 +991,15 @@ static gint disposition_notification_send(MsgInfo *msginfo)
goto FILE_ERROR;
/* Subject */
- notification_convert_header(buf, sizeof(buf), msginfo->subject,
- strlen("Subject: "));
- if (fprintf(fp, "Subject: Disposition notification: %s\n", buf) < 0)
+ notification_convert_header(&buf, msginfo->subject, strlen("Subject: "));
+ if (buf == NULL)
+ goto FILE_ERROR;
+ if (fprintf(fp, "Subject: Disposition notification: %s\n", buf) < 0) {
+ g_free(buf);
goto FILE_ERROR;
+ }
+ g_free(buf);
+ buf = NULL;
/* Message ID */
if (account->gen_msgid) {
@@ -994,8 +1012,7 @@ static gint disposition_notification_send(MsgInfo *msginfo)
}
boundary = generate_mime_boundary("DN");
- get_rfc822_date(buf, sizeof(buf));
- date = g_strdup(buf);
+ date = g_strdup(buf_date);
if (msginfo->to) {
orig_to = g_strdup(msginfo->to);
extract_address(orig_to);
diff --git a/src/plugins/perl/perl_plugin.c b/src/plugins/perl/perl_plugin.c
index 6db4c41..fc26555 100644
--- a/src/plugins/perl/perl_plugin.c
+++ b/src/plugins/perl/perl_plugin.c
@@ -651,7 +651,6 @@ static XS(XS_ClawsMail_filter_init)
static XS(XS_ClawsMail_open_mail_file)
{
char *file;
- gchar buf[BUFFSIZE];
dXSARGS;
if(items != 0) {
@@ -661,13 +660,13 @@ static XS(XS_ClawsMail_open_mail_file)
file = procmsg_get_message_file_path(msginfo);
if(!file)
XSRETURN_UNDEF;
- strncpy2(buf,file,sizeof(buf));
- g_free(file);
- if((message_file = fopen(buf, "rb")) == NULL) {
- FILE_OP_ERROR(buf, "fopen");
+ if((message_file = fopen(file, "rb")) == NULL) {
+ FILE_OP_ERROR(file, "fopen");
g_warning("Perl Plugin: File open error in ClawsMail::C::open_mail_file");
+ g_free(file);
XSRETURN_UNDEF;
}
+ g_free(file);
}
/* ClawsMail::C::close_mail_file */
@@ -686,7 +685,7 @@ static XS(XS_ClawsMail_close_mail_file)
/* ClawsMail::C::get_next_header */
static XS(XS_ClawsMail_get_next_header)
{
- gchar buf[BUFFSIZE];
+ gchar *buf;
Header *header;
dXSARGS;
@@ -698,7 +697,7 @@ static XS(XS_ClawsMail_get_next_header)
g_warning("Perl Plugin: Message file not open. Use ClawsMail::C::open_message_file first.");
XSRETURN_EMPTY;
}
- if(procheader_get_one_field(buf, sizeof(buf), message_file, NULL) != -1) {
+ if(procheader_get_one_field(&buf, message_file, NULL) != -1) {
header = procheader_parse_header(buf);
EXTEND(SP, 2);
if(header) {
@@ -710,6 +709,7 @@ static XS(XS_ClawsMail_get_next_header)
XST_mPV(0,"");
XST_mPV(1,"");
}
+ g_free(buf);
XSRETURN(2);
}
else
diff --git a/src/plugins/python/messageinfotype.c b/src/plugins/python/messageinfotype.c
index ea98320..2d20a3e 100644
--- a/src/plugins/python/messageinfotype.c
+++ b/src/plugins/python/messageinfotype.c
@@ -35,8 +35,6 @@
#include <string.h>
-#define HEADER_CONTENT_SIZE BUFFSIZE
-
typedef struct {
PyObject_HEAD
MsgInfo *msginfo;
@@ -194,7 +192,7 @@ static PyObject* get_header(PyObject *self, PyObject *args)
char *header_str;
char *header_str_dup;
MsgInfo *msginfo;
- gchar header_content[HEADER_CONTENT_SIZE];
+ gchar *header_content = NULL;
retval = PyArg_ParseTuple(args, "s", &header_str);
if(!retval)
@@ -203,7 +201,7 @@ static PyObject* get_header(PyObject *self, PyObject *args)
msginfo = ((clawsmail_MessageInfoObject*)self)->msginfo;
header_str_dup = g_strdup(header_str);
- retval = procheader_get_header_from_msginfo(msginfo, header_content, HEADER_CONTENT_SIZE, header_str);
+ retval = procheader_get_header_from_msginfo(msginfo, &header_content, header_str);
g_free(header_str_dup);
if(retval == 0) {
PyObject *header_content_object;
@@ -219,9 +217,11 @@ static PyObject* get_header(PyObject *self, PyObject *args)
while(*content_start == ' ')
content_start++;
header_content_object = Py_BuildValue("s", content_start);
+ g_free(header_content);
return header_content_object;
}
else {
+ g_free(header_content);
Py_RETURN_NONE;
}
}
diff --git a/src/plugins/spam_report/spam_report.c b/src/plugins/spam_report/spam_report.c
index e1987c5..826281d 100644
--- a/src/plugins/spam_report/spam_report.c
+++ b/src/plugins/spam_report/spam_report.c
@@ -141,11 +141,13 @@ static gchar *spamreport_strreplace(gchar *source, gchar *pattern,
static gboolean check_debian_listid(MsgInfo *msginfo)
{
- gchar buf[1024];
- if (!procheader_get_header_from_msginfo(msginfo, buf, sizeof(buf), "List-Id:")) {
+ gchar *buf = NULL;
+ if (!procheader_get_header_from_msginfo(msginfo, &buf, "List-Id:") && buf != NULL) {
if (strstr(buf, "lists.debian.org")) {
+ g_free(buf);
return TRUE;
}
+ g_free(buf);
}
return FALSE;
}
diff --git a/src/procheader.c b/src/procheader.c
index a9bfa5d..2aa4e6f 100644
--- a/src/procheader.c
+++ b/src/procheader.c
@@ -49,15 +49,15 @@ static gchar monthstr[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
typedef char *(*getlinefunc) (char *, size_t, void *);
typedef int (*peekcharfunc) (void *);
typedef int (*getcharfunc) (void *);
-typedef gint (*get_one_field_func) (gchar *, size_t, void *, HeaderEntry[]);
+typedef gint (*get_one_field_func) (gchar **, void *, HeaderEntry[]);
-static gint string_get_one_field(gchar *buf, size_t len, char **str,
+static gint string_get_one_field(gchar **buf, char **str,
HeaderEntry hentry[]);
static char *string_getline(char *buf, size_t len, char **str);
static int string_peekchar(char **str);
static int file_peekchar(FILE *fp);
-static gint generic_get_one_field(gchar *buf, size_t len, void *data,
+static gint generic_get_one_field(gchar **bufptr, void *data,
HeaderEntry hentry[],
getlinefunc getline,
peekcharfunc peekchar,
@@ -66,18 +66,18 @@ static MsgInfo *parse_stream(void *data, gboolean isstring, MsgFlags flags,
gboolean full, gboolean decrypted);
-gint procheader_get_one_field(gchar *buf, size_t len, FILE *fp,
+gint procheader_get_one_field(gchar **buf, FILE *fp,
HeaderEntry hentry[])
{
- return generic_get_one_field(buf, len, fp, hentry,
+ return generic_get_one_field(buf, fp, hentry,
(getlinefunc)fgets_crlf, (peekcharfunc)file_peekchar,
TRUE);
}
-static gint string_get_one_field(gchar *buf, size_t len, char **str,
+static gint string_get_one_field(gchar **buf, char **str,
HeaderEntry hentry[])
{
- return generic_get_one_field(buf, len, str, hentry,
+ return generic_get_one_field(buf, str, hentry,
(getlinefunc)string_getline,
(peekcharfunc)string_peekchar,
TRUE);
@@ -119,23 +119,48 @@ static int file_peekchar(FILE *fp)
return ungetc(getc(fp), fp);
}
-static gint generic_get_one_field(gchar *buf, size_t len, void *data,
+static gint generic_get_one_field(gchar **bufptr, void *data,
HeaderEntry *hentry,
getlinefunc getline, peekcharfunc peekchar,
gboolean unfold)
{
+ /* returns -1 in case of failure of any kind, whatever it's a parsing error
+ or an allocation error. if returns -1, *bufptr is always NULL, and vice-versa,
+ and if returning 0 (OK), *bufptr is always non-NULL, so callers just have to
+ test the return value
+ */
gint nexthead;
gint hnum = 0;
HeaderEntry *hp = NULL;
+ size_t len;
+ gchar *buf;
+/* cm_return_val_if_fail(bufptr != NULL, -1); TODO */
+
+ len = BUFFSIZE;
+ buf = g_malloc(len);
+ if (buf == NULL) {
+ debug_print("generic_get_one_field: primary allocation error\n");
+ *bufptr = NULL;
+ return -1;
+ }
if (hentry != NULL) {
/* skip non-required headers */
+ /* and get hentry header line */
do {
do {
- if (getline(buf, len, data) == NULL)
+ if (getline(buf, len, data) == NULL) {
+ debug_print("generic_get_one_field: getline\n");
+ g_free(buf);
+ *bufptr = NULL;
return -1;
- if (buf[0] == '\r' || buf[0] == '\n')
+ }
+ if (buf[0] == '\r' || buf[0] == '\n') {
+ debug_print("generic_get_one_field: empty line\n");
+ g_free(buf);
+ *bufptr = NULL;
return -1;
+ }
} while (buf[0] == ' ' || buf[0] == '\t');
for (hp = hentry, hnum = 0; hp->name != NULL;
@@ -146,8 +171,27 @@ static gint generic_get_one_field(gchar *buf, size_t len, void *data,
}
} while (hp->name == NULL);
} else {
- if (getline(buf, len, data) == NULL) return -1;
- if (buf[0] == '\r' || buf[0] == '\n') return -1;
+ /* read first line */
+ if (getline(buf, len, data) == NULL) {
+ debug_print("generic_get_one_field: getline\n");
+ g_free(buf);
+ *bufptr = NULL;
+ return -1;
+ }
+ if (buf[0] == '\r' || buf[0] == '\n') {
+ debug_print("generic_get_one_field: empty line\n");
+ g_free(buf);
+ *bufptr = NULL;
+ return -1;
+ }
+ }
+ /* reduce initial buffer to its useful part */
+ len = strlen(buf)+1;
+ buf = g_realloc(buf, len);
+ if (buf == NULL) {
+ debug_print("generic_get_one_field: reallocation error\n");
+ *bufptr = NULL;
+ return -1;
}
/* unfold line */
@@ -156,6 +200,9 @@ static gint generic_get_one_field(gchar *buf, size_t len, void *data,
/* ([*WSP CRLF] 1*WSP) */
if (nexthead == ' ' || nexthead == '\t') {
size_t buflen;
+ gchar *tmpbuf;
+ size_t tmplen;
+
gboolean skiptab = (nexthead == '\t');
/* trim previous trailing \n if requesting one header or
* unfolding was requested */
@@ -164,15 +211,34 @@ static gint generic_get_one_field(gchar *buf, size_t len, void *data,
buflen = strlen(buf);
- /* concatenate next line */
- if ((len - buflen) > 2) {
- if (getline(buf + buflen, len - buflen, data) == NULL)
- break;
- if (skiptab) { /* replace tab with space */
- *(buf + buflen) = ' ';
- }
- } else
+ /* read next line */
+ tmpbuf = g_malloc(BUFFSIZE);
+ if (tmpbuf == NULL) {
+ debug_print("generic_get_one_field: secondary allocation error\n");
+ g_free(buf);
+ *bufptr = NULL;
+ return -1;
+ }
+ if (getline(tmpbuf, BUFFSIZE, data) == NULL) {
+ g_free(tmpbuf);
break;
+ }
+ tmplen = strlen(tmpbuf)+1;
+
+ /* extend initial buffer and concatenate next line */
+ len += tmplen;
+ buf = g_realloc(buf, len);
+ if (buf == NULL) {
+ debug_print("generic_get_one_field: reallocation error\n");
+ g_free(buf);
+ *bufptr = NULL;
+ return -1;
+ }
+ memcpy(buf+buflen, tmpbuf, tmplen);
+ g_free(tmpbuf);
+ if (skiptab) { /* replace tab with space */
+ *(buf + buflen) = ' ';
+ }
} else {
/* remove trailing new line */
strretchomp(buf);
@@ -180,12 +246,14 @@ static gint generic_get_one_field(gchar *buf, size_t len, void *data,
}
}
+ *bufptr = buf;
+
return hnum;
}
-gint procheader_get_one_field_asis(gchar *buf, size_t len, FILE *fp)
+gint procheader_get_one_field_asis(gchar **buf, FILE *fp)
{
- return generic_get_one_field(buf, len, fp, NULL,
+ return generic_get_one_field(buf, fp, NULL,
(getlinefunc)fgets_crlf,
(peekcharfunc)file_peekchar,
FALSE);
@@ -193,7 +261,7 @@ gint procheader_get_one_field_asis(gchar *buf, size_t len, FILE *fp)
GPtrArray *procheader_get_header_array_asis(FILE *fp)
{
- gchar buf[BUFFSIZE];
+ gchar *buf = NULL;
GPtrArray *headers;
Header *header;
@@ -201,9 +269,11 @@ GPtrArray *procheader_get_header_array_asis(FILE *fp)
headers = g_ptr_array_new();
- while (procheader_get_one_field_asis(buf, sizeof(buf), fp) != -1) {
+ while (procheader_get_one_field_asis(&buf, fp) != -1 && buf != NULL) {
if ((header = procheader_parse_header(buf)) != NULL)
g_ptr_array_add(headers, header);
+ g_free(buf);
+ buf = NULL;
}
return headers;
@@ -214,6 +284,8 @@ void procheader_header_array_destroy(GPtrArray *harray)
gint i;
Header *header;
+ cm_return_if_fail(harray != NULL);
+
for (i = 0; i < harray->len; i++) {
header = g_ptr_array_index(harray, i);
procheader_header_free(header);
@@ -290,6 +362,8 @@ Header * procheader_parse_header(gchar * buf)
Header * header;
gboolean addr_field = FALSE;
+ cm_return_val_if_fail(buf != NULL, NULL);
+
if ((*buf == ':') || (*buf == ' '))
return NULL;
@@ -309,15 +383,14 @@ Header * procheader_parse_header(gchar * buf)
void procheader_get_header_fields(FILE *fp, HeaderEntry hentry[])
{
- gchar buf[BUFFSIZE];
+ gchar *buf = NULL;
HeaderEntry *hp;
gint hnum;
gchar *p;
if (hentry == NULL) return;
- while ((hnum = procheader_get_one_field(buf, sizeof(buf), fp, hentry))
- != -1) {
+ while ((hnum = procheader_get_one_field(&buf, fp, hentry)) != -1 && buf != NULL) {
hp = hentry + hnum;
p = buf + strlen(hp->name);
@@ -331,6 +404,8 @@ void procheader_get_header_fields(FILE *fp, HeaderEntry hentry[])
hp->body = g_strconcat(tp, ", ", p, NULL);
g_free(tp);
}
+ g_free(buf);
+ buf = NULL;
}
}
@@ -490,7 +565,7 @@ static MsgInfo *parse_stream(void *data, gboolean isstring, MsgFlags flags,
gboolean full, gboolean decrypted)
{
MsgInfo *msginfo;
- gchar buf[BUFFSIZE];
+ gchar *buf = NULL;
gchar *p, *tmp;
gchar *hp;
HeaderEntry *hentry;
@@ -504,7 +579,7 @@ static MsgInfo *parse_stream(void *data, gboolean isstring, MsgFlags flags,
hentry = procheader_get_headernames(full);
if (MSG_IS_QUEUED(flags) || MSG_IS_DRAFT(flags)) {
- while (get_one_field(buf, sizeof(buf), data, NULL) != -1) {
+ while (get_one_field(&buf, data, NULL) != -1 && buf != NULL) {
if ((!strncmp(buf, "X-Claws-End-Special-Headers: 1",
strlen("X-Claws-End-Special-Headers:"))) ||
(!strncmp(buf, "X-Sylpheed-End-Special-Headers: 1",
@@ -519,8 +594,12 @@ static MsgInfo *parse_stream(void *data, gboolean isstring, MsgFlags flags,
data = orig_data;
else
rewind((FILE *)data);
+ g_free(buf);
+ buf = NULL;
break;
}
+ g_free(buf);
+ buf = NULL;
}
}
@@ -540,8 +619,7 @@ static MsgInfo *parse_stream(void *data, gboolean isstring, MsgFlags flags,
avatar_hook_id = 0;
}
- while ((hnum = get_one_field(buf, sizeof(buf), data, hentry))
- != -1) {
+ while ((hnum = get_one_field(&buf, data, hentry)) != -1 && buf != NULL) {
hp = buf + strlen(hentry[hnum].name);
while (*hp == ' ' || *hp == '\t') hp++;
@@ -743,6 +821,8 @@ static MsgInfo *parse_stream(void *data, gboolean isstring, MsgFlags flags,
hooks_invoke(AVATAR_HEADER_UPDATE_HOOKLIST, (gpointer)acd);
g_free(acd);
}
+ g_free(buf);
+ buf = NULL;
}
if (!msginfo->inreplyto && msginfo->references)
@@ -1052,34 +1132,50 @@ void procheader_date_get_localtime(gchar *dest, gint len, const time_t timer)
/* Added by Mel Hadasht on 27 Aug 2001 */
/* Get a header from msginfo */
-gint procheader_get_header_from_msginfo(MsgInfo *msginfo, gchar *buf, gint len, gchar *header)
+gint procheader_get_header_from_msginfo(MsgInfo *msginfo, gchar **buf, gchar *header)
{
gchar *file;
FILE *fp;
HeaderEntry hentry[]={ { NULL, NULL, TRUE },
- { NULL, NULL, FALSE } };
+ { NULL, NULL, FALSE } };
gint val;
- hentry[0].name = header;
-
cm_return_val_if_fail(msginfo != NULL, -1);
+ cm_return_val_if_fail(buf != NULL, -1);
+ cm_return_val_if_fail(header != NULL, -1);
+
+ hentry[0].name = header;
+
file = procmsg_get_message_file_path(msginfo);
if ((fp = g_fopen(file, "rb")) == NULL) {
- FILE_OP_ERROR(file, "fopen");
- g_free(file);
- return -1;
+ FILE_OP_ERROR(file, "fopen");
+ g_free(file);
+ g_free(*buf);
+ *buf = NULL;
+ return -1;
+ }
+ val = procheader_get_one_field(buf, fp, hentry);
+ if (buf == NULL) {
+ claws_unlink(file);
+ g_free(file);
+ g_free(*buf);
+ *buf = NULL;
+ return -1;
}
- val = procheader_get_one_field(buf,len, fp, hentry);
if (fclose(fp) == EOF) {
FILE_OP_ERROR(file, "fclose");
claws_unlink(file);
g_free(file);
+ g_free(*buf);
+ *buf = NULL;
return -1;
}
g_free(file);
- if (val == -1)
+ if (val == -1) {
+ /* *buf is already NULL in that case, see procheader_get_one_field() */
return -1;
+ }
return 0;
}
diff --git a/src/procheader.h b/src/procheader.h
index e4cb92d..0588f30 100644
--- a/src/procheader.h
+++ b/src/procheader.h
@@ -41,15 +41,10 @@ struct _Header
gchar *body;
};
-gint procheader_get_one_field (gchar *buf,
- size_t len,
+gint procheader_get_one_field (gchar **buf,
FILE *fp,
HeaderEntry hentry[]);
-gint procheader_get_one_field_asis (gchar *buf,
- size_t len,
- FILE *fp);
-gchar *procheader_get_unfolded_line (gchar *buf,
- size_t len,
+gint procheader_get_one_field_asis (gchar **buf,
FILE *fp);
GPtrArray *procheader_get_header_array_asis (FILE *fp);
@@ -89,8 +84,7 @@ gboolean procheader_headername_equal (char * hdr1, char * hdr2);
void procheader_header_free (Header * header);
gint procheader_get_header_from_msginfo (MsgInfo *msginfo,
- gchar *buf,
- gint len,
+ gchar **buf,
gchar *header);
HeaderEntry *procheader_entries_from_str(const gchar *str);
diff --git a/src/procmsg.c b/src/procmsg.c
index aa3c9a8..c9b077e 100644
--- a/src/procmsg.c
+++ b/src/procmsg.c
@@ -724,7 +724,7 @@ static PrefsAccount *procmsg_get_account_from_file(const gchar *file)
PrefsAccount *mailac = NULL;
FILE *fp;
int hnum;
- gchar buf[BUFFSIZE];
+ gchar *buf = NULL;
static HeaderEntry qentry[] = {{"S:", NULL, FALSE},
{"SSV:", NULL, FALSE},
{"R:", NULL, FALSE},
@@ -750,14 +750,15 @@ static PrefsAccount *procmsg_get_account_from_file(const gchar *file)
return NULL;
}
- while ((hnum = procheader_get_one_field(buf, sizeof(buf), fp, qentry))
- != -1) {
+ while ((hnum = procheader_get_one_field(&buf, fp, qentry)) != -1 && buf != NULL) {
gchar *p = buf + strlen(qentry[hnum].name);
if (hnum == Q_MAIL_ACCOUNT_ID) {
mailac = account_find_from_id(atoi(p));
break;
}
+ g_free(buf);
+ buf = NULL;
}
fclose(fp);
return mailac;
@@ -1542,7 +1543,7 @@ static gint procmsg_send_message_queue_full(const gchar *file, gboolean keep_ses
gchar *savecopyfolder = NULL;
gchar *replymessageid = NULL;
gchar *fwdmessageid = NULL;
- gchar buf[BUFFSIZE];
+ gchar *buf;
gint hnum;
PrefsAccount *mailac = NULL, *newsac = NULL;
gboolean encrypt = FALSE;
@@ -1559,8 +1560,7 @@ static gint procmsg_send_message_queue_full(const gchar *file, gboolean keep_ses
return -1;
}
- while ((hnum = procheader_get_one_field(buf, sizeof(buf), fp, qentry))
- != -1) {
+ while ((hnum = procheader_get_one_field(&buf, fp, qentry)) != -1 && buf != NULL) {
gchar *p = buf + strlen(qentry[hnum].name);
switch (hnum) {
@@ -1607,6 +1607,8 @@ static gint procmsg_send_message_queue_full(const gchar *file, gboolean keep_ses
goto send_mail; /* can't "break;break;" */
}
}
+ g_free(buf);
+
send_mail:
filepos = ftell(fp);
if (filepos < 0) {
@@ -1679,6 +1681,7 @@ send_mail:
if (newsgroup_list && newsac && (mailval == 0)) {
Folder *folder;
gchar *tmp = NULL;
+ gchar buf[BUFFSIZE];
FILE *tmpfp;
/* write to temporary file */
-----------------------------------------------------------------------
hooks/post-receive
--
Claws Mail
More information about the Commits
mailing list