[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