[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[mpop-users] [PATCH 5/9] New add_header option
Allows addition of custom headers directly by mpop, without requiring a mda.
---
src/conf.c | 37 +++++++++++++++++++++++++++++++++++++
src/conf.h | 2 ++
src/list.c | 22 ++++++++++++++++++++++
src/list.h | 11 +++++++++++
src/pop3.c | 37 +++++++++++++++++++++++++++++++++++++
5 files changed, 109 insertions(+)
diff --git a/src/conf.c b/src/conf.c
index 607dceb..1a2d705 100644
--- a/src/conf.c
+++ b/src/conf.c
@@ -73,6 +73,7 @@ account_t *account_new(const char *conffile, const char *id)
a->killsize = -1;
a->skipsize = -1;
a->filter = NULL;
+ a->added_headers = list_new();
a->auth_mech = xstrdup("");
a->username = NULL;
a->password = NULL;
@@ -103,6 +104,7 @@ account_t *account_new(const char *conffile, const char *id)
account_t *account_copy(account_t *acc)
{
account_t *a = NULL;
+ void *ptrstrdup = xstrdup;
if (acc)
{
@@ -124,6 +126,7 @@ account_t *account_copy(account_t *acc)
a->killsize = acc->killsize;
a->skipsize = acc->skipsize;
a->filter = acc->filter ? xstrdup(acc->filter) : NULL;
+ a->added_headers = list_xcopy(acc->added_headers, ptrstrdup);
a->auth_mech = acc->auth_mech ? xstrdup(acc->auth_mech) : NULL;
a->username = acc->username ? xstrdup(acc->username) : NULL;
a->password = acc->password ? xstrdup(acc->password) : NULL;
@@ -183,6 +186,7 @@ void account_free(void *a)
free(p->delivery_args);
free(p->uidls_file);
free(p->filter);
+ list_xfree(p->added_headers, free);
free(p->auth_mech);
free(p->username);
free(p->password);
@@ -400,6 +404,8 @@ int check_auth_arg(char *arg)
void override_account(account_t *acc1, account_t *acc2)
{
+ void *ptrstrdup = xstrdup;
+
if (acc2->mask & ACC_HOST)
{
free(acc1->host);
@@ -453,6 +459,23 @@ void override_account(account_t *acc1, account_t *acc2)
{
acc1->filter = acc2->filter ? xstrdup(acc2->filter) : NULL;
}
+ if (acc2->mask & ACC_ADD_HEADER)
+ {
+ /* Completely replace with the new account headers */
+ list_xfree(acc1->added_headers, free);
+ acc1->added_headers = list_xcopy(acc2->added_headers, ptrstrdup);
+ }
+ else
+ {
+ /* Add the new headers to the previous list */
+ list_t *p, *last = list_last(acc1->added_headers);
+ p = acc2->added_headers;
+ while (!list_is_empty(p))
+ {
+ p = p->next;
+ list_insert(last, strdup(p->data));
+ }
+ }
if (acc2->mask & ACC_AUTH_MECH)
{
free(acc1->auth_mech);
@@ -1497,6 +1520,20 @@ int read_conffile(const char *conffile, FILE *f, list_t **acc_list,
acc->filter = xstrdup(arg);
}
}
+ else if (strcmp(cmd, "add_header") == 0)
+ {
+ free(acc->filter);
+ if (*arg == '\0')
+ {
+ acc->mask |= ACC_ADD_HEADER;
+ list_xfree(acc->added_headers, free);
+ acc->added_headers = list_new();
+ }
+ else
+ {
+ list_insert(list_last(acc->added_headers), strdup(arg));
+ }
+ }
else
{
*errstr = xasprintf(_("line %d: unknown command %s"), line, cmd);
diff --git a/src/conf.h b/src/conf.h
index 4dc6a34..0fc9382 100644
--- a/src/conf.h
+++ b/src/conf.h
@@ -69,6 +69,7 @@
#define ACC_TLS_FORCE_SSLV3 (1 << 25)
#define ACC_TLS_MIN_DH_PRIME_BITS (1 << 26)
#define ACC_TLS_PRIORITIES (1 << 27)
+#define ACC_ADD_HEADER (1 << 28)
typedef struct
{
@@ -94,6 +95,7 @@ typedef struct
long long skipsize; /* skipsize, -1 when disabled */
char *filter; /* a program to filter the mail headers
through */
+ list_t *added_headers; /* headers added to the mails on download */
/* Authentication */
char *auth_mech; /* authentication mechanism */
char *username; /* username for authentication */
diff --git a/src/list.c b/src/list.c
index a8155f6..f5ec185 100644
--- a/src/list.c
+++ b/src/list.c
@@ -128,6 +128,28 @@ void list_xremove(list_t *l, void (*destruct)(void *))
free(p);
}
+list_t *list_xcopy(list_t *l, void* (*copy)(void *))
+{
+ list_t *new_list, *p;
+
+ new_list = list_new();
+ p = new_list;
+ l = l->next;
+ while (l->next != l)
+ {
+ list_insert(p, copy ? copy(l->data) : l->data);
+ l = l->next;
+ p = p->next;
+ }
+
+ return new_list;
+}
+
+list_t *list_copy(list_t *l)
+{
+ return list_xcopy(l, NULL);
+}
+
/*
* list_is_empty()
diff --git a/src/list.h b/src/list.h
index be3b6cc..6715f43 100644
--- a/src/list.h
+++ b/src/list.h
@@ -77,6 +77,17 @@ void list_remove(list_t *e);
void list_xremove(list_t *e, void (*destruct)(void *));
/*
+ * Produces a new list with the same contents as e. See also list_xcopy().
+ */
+list_t *list_copy(list_t *l);
+
+/*
+ * Produces a new list with the same contents as e. Calls copy()
+ * to duplicate each element of the list.
+ */
+list_t *list_xcopy(list_t *l, void* (*copy)(void *));
+
+/*
* Returns 1 if the list is empty, 0 otherwise. Needs a pointer to the head
* element of the list.
*/
diff --git a/src/pop3.c b/src/pop3.c
index 515956c..90fe653 100644
--- a/src/pop3.c
+++ b/src/pop3.c
@@ -1640,6 +1640,37 @@ int pop3_retr_get_from_addr(pop3_session_t *session, FILE *f, char **from_addr,
return POP3_EOK;
}
+/*
+ * pop3_write_added_headers()
+ *
+ * Write the user-added headers to the given stream.
+ */
+
+int pop3_write_added_headers(pop3_session_t *session, FILE *f, int crlf,
+ int recv_index, const char* from_addr, char **errstr)
+{
+ int e;
+ list_t *h;
+ char *header;
+
+ h = session->account->added_headers;
+ while (!list_is_empty(h))
+ {
+ h = h->next;
+
+ header = expand_session_variables(h->data, session, recv_index, from_addr);
+ e = (fprintf(f, "%s%s", header, crlf ? "\r\n" : "\n") < 0);
+ if (e)
+ {
+ *errstr = xasprintf(_("cannot add user header: %s"),
+ header, strerror(errno));
+ free(header);
+ return POP3_EIO;
+ }
+ free(header);
+ }
+ return POP3_EOK;
+}
/*
* pop3_write_received_header()
@@ -1883,6 +1914,12 @@ int pop3_delivery(pop3_session_t *session, volatile sig_atomic_t *abort,
e = POP3_EDELIVERY;
goto error_exit;
}
+ if ((e = pop3_write_added_headers(session, delivery->pipe,
+ delivery->need_crlf, recv_index, from_addr,
+ errstr)) != POP3_EOK)
+ {
+ goto error_exit;
+ }
if (from_addr)
{
free(from_addr);
--
2.1.1