[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[mpop-users] [PATCH 2/9] Use a single function to perform all replacements.



This results in more consistent behavior.
It also adds "%%" to write a literal "%"
---
 src/conf.c     |   2 +-
 src/delivery.c |  34 +++++------------
 src/delivery.h |  11 ++----
 src/mpop.c     |   9 ++---
 src/pop3.c     |   5 ++-
 src/pop3.h     |   5 ++-
 src/tools.c    | 114 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/tools.h    |  20 ++++++++++
 8 files changed, 159 insertions(+), 41 deletions(-)

diff --git a/src/conf.c b/src/conf.c
index 55a9c9d..607dceb 100644
--- a/src/conf.c
+++ b/src/conf.c
@@ -37,11 +37,11 @@
 #include "gettext.h"
 #define _(string) gettext(string)
 
+#include "conf.h"
 #include "delivery.h"
 #include "list.h"
 #include "tools.h"
 #include "xalloc.h"
-#include "conf.h"
 
 /* buffer size for configuration file lines */
 #define LINEBUFSIZE 501
diff --git a/src/delivery.c b/src/delivery.c
index b3cc0b2..adbe8a8 100644
--- a/src/delivery.c
+++ b/src/delivery.c
@@ -152,23 +152,13 @@ static void mda_sigpipe_handler(int signum)
 #endif
 
 int delivery_method_mda_open(delivery_method_t *dm, const char *from,
-        long long size, char **errstr)
+        pop3_session_t *session, long recv_index, char **errstr)
 {
     int e;
     char *cmd;
-    char *sizestr;
 
-    cmd = xstrdup((char *)(dm->data));
-    if (dm->want_from_addr)
-    {
-        cmd = string_replace(cmd, "%F", from);
-    }
-    if (dm->want_size)
-    {
-        sizestr = xasprintf(PRINTFLLD, size);
-        cmd = string_replace(cmd, "%S", sizestr);
-        free(sizestr);
-    }
+    cmd = expand_session_variables(dm->data, session, recv_index, from);
+
     if (fflush(stdout) != 0 || fflush(stderr) != 0
             || !(dm->pipe = popen(cmd, "w")))
     {
@@ -236,7 +226,6 @@ int delivery_method_mda_init(delivery_method_t *dm, void *data,
     dm->need_from_quoting = 0;
     dm->need_crlf = 0;
     dm->want_from_addr = (strstr((char *)data, "%F") != NULL);
-    dm->want_size = 0;
     dm->open = delivery_method_mda_open;
     dm->close = delivery_method_mda_close;
     mda_caused_sigpipe = 0;
@@ -319,7 +308,6 @@ int delivery_method_filter_init(delivery_method_t *dm, void *data,
     {
         return e;
     }
-    dm->want_size = (strstr((char *)data, "%S") != NULL);
     dm->close = delivery_method_filter_close;
     return DELIVERY_EOK;
 }
@@ -350,7 +338,7 @@ typedef struct
 } maildir_data_t;
 
 int delivery_method_maildir_open(delivery_method_t *dm, const char *from,
-        long long size, char **errstr)
+        pop3_session_t *session, long recv_index, char **errstr)
 {
     maildir_data_t *maildir_data;
     char *filename;
@@ -358,7 +346,7 @@ int delivery_method_maildir_open(delivery_method_t *dm, const char *from,
     int fd;
 
     (void)from;
-    (void)size;
+    (void)session;
 
     maildir_data = dm->data;
     if (gettimeofday(&tv, NULL) < 0)
@@ -462,7 +450,6 @@ int delivery_method_maildir_init(delivery_method_t *dm, void *data,
     dm->need_from_quoting = 0;
     dm->need_crlf = 0;
     dm->want_from_addr = 0;
-    dm->want_size = 0;
     dm->open = delivery_method_maildir_open;
     dm->close = delivery_method_maildir_close;
     if (chdir(maildir_data->maildir) != 0)
@@ -509,7 +496,8 @@ typedef struct
 } exchange_data_t;
 
 int delivery_method_exchange_open(delivery_method_t *dm,
-        const char *from, long long size, char **errstr)
+        const char *from, pop3_session_t *session, long recv_index, 
+        char **errstr)
 {
     exchange_data_t *exchange_data;
     char *filename;
@@ -517,7 +505,7 @@ int delivery_method_exchange_open(delivery_method_t *dm,
     int fd;
 
     (void)from;
-    (void)size;
+    (void)session;
 
     exchange_data = dm->data;
     if (gettimeofday(&tv, NULL) < 0)
@@ -626,7 +614,6 @@ int delivery_method_exchange_init(delivery_method_t *dm, void *data,
     dm->need_from_quoting = 0;
     dm->need_crlf = 1;
     dm->want_from_addr = 0;
-    dm->want_size = 0;
     dm->open = delivery_method_exchange_open;
     dm->close = delivery_method_exchange_close;
     if (chdir(exchange_data->pickupdir) != 0)
@@ -660,11 +647,11 @@ int delivery_method_exchange_deinit(delivery_method_t *dm, char **errstr)
  ******************************************************************************/
 
 int delivery_method_mbox_open(delivery_method_t *dm, const char *from,
-        long long size, char **errstr)
+        pop3_session_t *session, long recv_index, char **errstr)
 {
     time_t t;
 
-    (void)size;
+    (void)session;
 
     if ((t = time(NULL)) < 0)
     {
@@ -717,7 +704,6 @@ int delivery_method_mbox_init(delivery_method_t *dm, void *data, char **errstr)
     dm->need_from_quoting = 1;
     dm->need_crlf = 0;
     dm->want_from_addr = 1;
-    dm->want_size = 0;
     dm->open = delivery_method_mbox_open;
     dm->close = delivery_method_mbox_close;
     (void)umask(S_IRWXG | S_IRWXO);
diff --git a/src/delivery.h b/src/delivery.h
index 2023e50..1c10bd6 100644
--- a/src/delivery.h
+++ b/src/delivery.h
@@ -25,6 +25,7 @@
 
 #include <stdio.h>
 
+#include "pop3.h"
 
 /*
  * Explanation of the available delivery methods:
@@ -100,8 +101,6 @@ typedef struct _delivery_method
     FILE *pipe;
     /* Whether this method wants the mail's envelope from address: */
     int want_from_addr;
-    /* Whether this method wants the mail's size: */
-    int want_size;
     /* Whether this method needs From quoting: */
     int need_from_quoting;
     /* Whether this method needs CRLF line endings: */
@@ -110,11 +109,9 @@ typedef struct _delivery_method
      * point to a valid mail address. It is important that this address only
      * contains characters that are valid in a mail address, since it might be
      * passed to a shell. If 'want_from_addr' is not set, then 'from' must be
-     * NULL. If 'want_size' is set, then 'size' should contain the size of the
-     * mail as reported by the POP3 server. If 'want_size' is not set, 'size' is
-     * ignored. */
-    int (*open)(struct _delivery_method *dm, const char *from, long long size,
-            char **errstr);
+     * NULL. */
+    int (*open)(struct _delivery_method *dm, const char *from, pop3_session_t *session, 
+            long recv_index, char **errstr);
     /* Close 'pipe' after a mail was written to 'pipe': */
     int (*close)(struct _delivery_method *dm, char **errstr);
 } delivery_method_t;
diff --git a/src/mpop.c b/src/mpop.c
index 743cefa..6ab59be 100644
--- a/src/mpop.c
+++ b/src/mpop.c
@@ -494,7 +494,7 @@ int mpop_serverinfo(account_t *acc, int debug, char **errmsg, char **errstr)
 
     /* Create a new pop3_server_t. We won't actually retrieve any mail, so the
      * FQDN and the local user are meaningless. */
-    session = pop3_session_new(acc->pipelining, "", "", debug ? stdout : NULL);
+    session = pop3_session_new(acc->pipelining, acc, "", "", debug ? stdout : NULL);
 
     /* connect */
     if ((e = pop3_connect(session, acc->host, acc->port, acc->timeout,
@@ -974,7 +974,7 @@ int mpop_retrmail(const char *canonical_hostname, const char *local_user,
 
 
     /* create a new pop3_server_t */
-    session = pop3_session_new(acc->pipelining, canonical_hostname, local_user,
+    session = pop3_session_new(acc->pipelining, acc, canonical_hostname, local_user,
             debug ? stdout : NULL);
 
     /* connect */
@@ -2539,10 +2539,7 @@ int main(int argc, char *argv[])
             goto exit;
         }
         /* construct the complete, absolute UIDLS file name */
-        account->uidls_file = string_replace(account->uidls_file, "%U",
-                account->username ? account->username : "");
-        account->uidls_file = string_replace(account->uidls_file, "%H",
-                account->host);
+        account->uidls_file = replace_account_variables(account->uidls_file, account);
         /* create directories needed for uidls_file */
         if (retrmail && !pretend && make_needed_dirs(account->uidls_file) != 0)
         {
diff --git a/src/pop3.c b/src/pop3.c
index e29dbbb..515956c 100644
--- a/src/pop3.c
+++ b/src/pop3.c
@@ -112,7 +112,7 @@
  * see pop3.h
  */
 
-pop3_session_t *pop3_session_new(int pipelining,
+pop3_session_t *pop3_session_new(int pipelining, const account_t *account,
         const char *local_hostname, const char *local_user,
         FILE *debug)
 {
@@ -120,6 +120,7 @@ pop3_session_t *pop3_session_new(int pipelining,
     char *p;
 
     session = xmalloc(sizeof(pop3_session_t));
+    session->account = account;
     session->local_hostname = xstrdup(local_hostname);
     session->local_user = xstrdup(local_user);
     /* sanitize the user name because it will appear in Received headers */
@@ -1877,7 +1878,7 @@ int pop3_delivery(pop3_session_t *session, volatile sig_atomic_t *abort,
             }
             /* open pipe */
             if (delivery->open(delivery, from_addr,
-                        session->msg_size[recv_index], errstr) != DELIVERY_EOK)
+                        session, recv_index, errstr) != DELIVERY_EOK)
             {
                 e = POP3_EDELIVERY;
                 goto error_exit;
diff --git a/src/pop3.h b/src/pop3.h
index 1d507dd..9deefba 100644
--- a/src/pop3.h
+++ b/src/pop3.h
@@ -32,6 +32,7 @@
 # include "tls.h"
 #endif /* HAVE_TLS */
 
+#include "conf.h"
 
 /* POP3 errors */
 
@@ -163,6 +164,8 @@ typedef struct
     char *local_hostname;       /* A canonical name of this host */
     char *local_user;           /* The (login) name of the user for which mails
                                    are retrieved in this session */
+    const account_t *account;   /* The account which spawned this session */
+    
     /* The POP3 server */
     char *server_hostname;      /* the hostname of the POP3 server as given by
                                    the user */
@@ -212,7 +215,7 @@ typedef struct
  * be logged to the referenced file.
  * Beware: this log may contain user passwords.
  */
-pop3_session_t *pop3_session_new(int pipelining,
+pop3_session_t *pop3_session_new(int pipelining, const account_t *account,
         const char *canonical_hostname, const char *local_user,
         FILE *debug);
 
diff --git a/src/tools.c b/src/tools.c
index b980f8d..df08ef6 100644
--- a/src/tools.c
+++ b/src/tools.c
@@ -42,13 +42,19 @@
 # include <lmcons.h>
 # include <sys/locking.h>
 # include <limits.h>
+# define PRINTFLLD "%I64d"
 #else
 # include <pwd.h>
+# define PRINTFLLD "%lld"
 #endif
 
+#include "gettext.h"
+#define _(string) gettext(string)
+
 #include "xalloc.h"
 #include "tools.h"
 
+extern const char *prgname;
 
 /*
  * link()
@@ -772,3 +778,111 @@ char *string_replace(char *str, const char *s, const char *r)
     }
     return str;
 }
+
+
+/*
+ * expand_session_variables()
+ *
+ * see tools.h
+ */
+
+char *expand_session_variables(const char *string, pop3_session_t *session, 
+        long recv_index, const char *from)
+{
+    size_t step, i, len=0;
+    char *newstr;
+    char *sizestr = NULL;
+    
+    for (step = 0; step < 2; step++)
+    {
+        for (i=0; string[i]; i++)
+        {
+            if (string[i] != '%')
+            {
+                if (step)
+                    newstr[len] = string[i];
+                len++;
+            } else {
+                switch (string[++i])
+                {
+                    case 'F': /* Envelope */
+                        if (step)
+                            strcpy(newstr + len, from);
+                        
+                        len += strlen(from);
+                        break;
+                    case 'H': /* Hostname */
+                        if (step)
+                            strcpy(newstr + len, session->account->host);
+                        
+                        len += strlen(session->account->host);
+                        break;
+                        
+                    case 'S': /* Email size */
+                        if (!sizestr)
+                        {
+                            long long size;
+                            size = session->msg_size ? session->msg_size[recv_index] : 0;
+                            sizestr = xasprintf(PRINTFLLD, size);
+                        }
+                        
+                        if (step)
+                            strcpy(newstr + len, sizestr);
+                        
+                        len += strlen(sizestr);
+                        break;
+
+                    case 'U': /* Username */
+                        if (step)
+                            strcpy(newstr + len, session->account->username);
+                        
+                        len += strlen(session->account->username);
+
+                        break;
+                    
+                    case '\0':
+                        if (step)
+                            fprintf(stderr, _("%s: Trailing %% character at end of string.\n"), prgname);
+                        i--;
+                        break;
+                        
+                    default:
+                        if (step)
+                            fprintf(stderr, _("%s: There is no expansion for %%%c\n"), prgname, string[i]);
+                        break;
+                }
+            }
+        }
+
+        if (!step)
+        {
+            newstr = xmalloc(len + 1);
+            len = 0;
+        }
+    }
+    newstr[len] = '\0';
+    
+    if (sizestr)
+        free(sizestr);
+        
+    return newstr;
+}
+
+
+/*
+ * replace_account_variables()
+ *
+ * see tools.h
+ */
+
+char *replace_account_variables(char *string, const account_t *account)
+{
+    char *newstr;
+    pop3_session_t *session;
+    
+    session = pop3_session_new(0, account, "", "", NULL);
+    newstr = expand_session_variables(string, session, 0, "");
+    pop3_session_free(session);
+    free(string);
+    return newstr;
+}
diff --git a/src/tools.h b/src/tools.h
index a541a13..c4ad3c1 100644
--- a/src/tools.h
+++ b/src/tools.h
@@ -23,6 +23,8 @@
 #ifndef TOOLS_H
 #define TOOLS_H
 
+#include <stdbool.h>
+
 #ifdef HAVE_SYSEXITS_H
 # include <sysexits.h>
 #else
@@ -62,6 +64,8 @@
 # define PATH_SEP '/'
 #endif
 
+#include "conf.h"
+#include "pop3.h"
 
 /*
  * link() - only for systems that lack it
@@ -193,4 +197,20 @@ int lock_file(FILE *f, int lock_type, int timeout);
  */
 char *string_replace(char *str, const char *s, const char *r);
 
+/*
+ * expand_session_variable()
+ *
+ * Return a new allocated string with the variables marked by a % 
+ * character expanded.
+ */
+char *expand_session_variables(const char *string, pop3_session_t *session, 
+        long recv_index, const char *from);
+
+/*
+ * replace_account_variables()
+ *
+ * Return a new allocated string with the variables marked by a % 
+ * character expanded, and freeing the input string.
+ */
+char *replace_account_variables(char *string, const account_t *account);
 #endif
-- 
2.1.1