[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