From ec3eb53293a282b409fe128153038522c294dda3 Mon Sep 17 00:00:00 2001 From: Aki Tuomi Date: Mon, 20 Feb 2017 09:18:45 +0200 Subject: [PATCH] pop3c: Add no pipelining pop3c feature This should help with certain broken pop3c servers that advertise that they support pipelining but they really don't. --- src/lib-storage/index/pop3c/pop3c-client.c | 3 +- src/lib-storage/index/pop3c/pop3c-client.h | 2 + src/lib-storage/index/pop3c/pop3c-mail.c | 1 - src/lib-storage/index/pop3c/pop3c-settings.c | 57 +++++++++++++++++++- src/lib-storage/index/pop3c/pop3c-settings.h | 10 ++++ src/lib-storage/index/pop3c/pop3c-storage.c | 1 - 6 files changed, 70 insertions(+), 4 deletions(-) diff --git a/src/lib-storage/index/pop3c/pop3c-client.c b/src/lib-storage/index/pop3c/pop3c-client.c index 9cbee3325a..9651b2ffd2 100644 --- a/src/lib-storage/index/pop3c/pop3c-client.c +++ b/src/lib-storage/index/pop3c/pop3c-client.c @@ -490,7 +490,8 @@ pop3c_client_prelogin_input_line(struct pop3c_client *client, const char *line) pop3c_client_login_finished(client); break; } - if (strcasecmp(line, "PIPELINING") == 0) + if ((client->set.parsed_features & POP3C_FEATURE_NO_PIPELINING) == 0 && + strcasecmp(line, "PIPELINING") == 0) client->capabilities |= POP3C_CAPABILITY_PIPELINING; else if (strcasecmp(line, "TOP") == 0) client->capabilities |= POP3C_CAPABILITY_TOP; diff --git a/src/lib-storage/index/pop3c/pop3c-client.h b/src/lib-storage/index/pop3c/pop3c-client.h index 84365c2621..57a4cb0d4f 100644 --- a/src/lib-storage/index/pop3c/pop3c-client.h +++ b/src/lib-storage/index/pop3c/pop3c-client.h @@ -2,6 +2,7 @@ #define POP3C_CLIENT_H #include "net.h" +#include "pop3c-settings.h" enum pop3c_capability { POP3C_CAPABILITY_PIPELINING = 0x01, @@ -33,6 +34,7 @@ struct pop3c_client_settings { const char *temp_path_prefix; enum pop3c_client_ssl_mode ssl_mode; + enum pop3c_features parsed_features; const char *ssl_ca_dir, *ssl_ca_file; bool ssl_verify; diff --git a/src/lib-storage/index/pop3c/pop3c-mail.c b/src/lib-storage/index/pop3c/pop3c-mail.c index 9073d5f9be..e2b61860d5 100644 --- a/src/lib-storage/index/pop3c/pop3c-mail.c +++ b/src/lib-storage/index/pop3c/pop3c-mail.c @@ -4,7 +4,6 @@ #include "ioloop.h" #include "istream.h" #include "index-mail.h" -#include "pop3c-settings.h" #include "pop3c-client.h" #include "pop3c-sync.h" #include "pop3c-storage.h" diff --git a/src/lib-storage/index/pop3c/pop3c-settings.c b/src/lib-storage/index/pop3c/pop3c-settings.c index ddf7f09160..93cb43e14c 100644 --- a/src/lib-storage/index/pop3c/pop3c-settings.c +++ b/src/lib-storage/index/pop3c/pop3c-settings.c @@ -25,6 +25,8 @@ static const struct setting_define pop3c_setting_defines[] = { DEF(SET_STR, pop3c_rawlog_dir), DEF(SET_BOOL, pop3c_quick_received_date), + DEF(SET_STR, pop3c_features), + SETTING_DEFINE_LIST_END }; @@ -40,9 +42,60 @@ static const struct pop3c_settings pop3c_default_settings = { .pop3c_ssl_verify = TRUE, .pop3c_rawlog_dir = "", - .pop3c_quick_received_date = FALSE + .pop3c_quick_received_date = FALSE, + + .pop3c_features = "" +}; + +/* */ +struct pop3c_feature_list { + const char *name; + enum pop3c_features num; }; +static const struct pop3c_feature_list pop3c_feature_list[] = { + { "no-pipelining", POP3C_FEATURE_NO_PIPELINING }, + { NULL, 0 } +}; + +static int +pop3c_settings_parse_features(struct pop3c_settings *set, + const char **error_r) +{ + enum pop3c_features features = 0; + const struct pop3c_feature_list *list; + const char *const *str; + + str = t_strsplit_spaces(set->pop3c_features, " ,"); + for (; *str != NULL; str++) { + list = pop3c_feature_list; + for (; list->name != NULL; list++) { + if (strcasecmp(*str, list->name) == 0) { + features |= list->num; + break; + } + } + if (list->name == NULL) { + *error_r = t_strdup_printf("pop3c_features: " + "Unknown feature: %s", *str); + return -1; + } + } + set->parsed_features = features; + return 0; +} + +static bool pop3c_settings_check(void *_set, pool_t pool ATTR_UNUSED, + const char **error_r) +{ + struct pop3c_settings *set = _set; + + if (pop3c_settings_parse_features(set, error_r) < 0) + return FALSE; + return TRUE; +} +/* */ + static const struct setting_parser_info pop3c_setting_parser_info = { .module_name = "pop3c", .defines = pop3c_setting_defines, @@ -53,6 +106,8 @@ static const struct setting_parser_info pop3c_setting_parser_info = { .parent_offset = (size_t)-1, .parent = &mail_user_setting_parser_info, + + .check_func = pop3c_settings_check }; const struct setting_parser_info *pop3c_get_setting_parser_info(void) diff --git a/src/lib-storage/index/pop3c/pop3c-settings.h b/src/lib-storage/index/pop3c/pop3c-settings.h index 844026afe7..bf44e24477 100644 --- a/src/lib-storage/index/pop3c/pop3c-settings.h +++ b/src/lib-storage/index/pop3c/pop3c-settings.h @@ -3,6 +3,13 @@ #include "net.h" +/* */ +enum pop3c_features { + POP3C_FEATURE_NO_PIPELINING = 0x1, +}; +/* */ + + struct pop3c_settings { const char *pop3c_host; in_port_t pop3c_port; @@ -16,6 +23,9 @@ struct pop3c_settings { const char *pop3c_rawlog_dir; bool pop3c_quick_received_date; + + const char *pop3c_features; + enum pop3c_features parsed_features; }; const struct setting_parser_info *pop3c_get_setting_parser_info(void); diff --git a/src/lib-storage/index/pop3c/pop3c-storage.c b/src/lib-storage/index/pop3c/pop3c-storage.c index 5c2f57e847..87be081860 100644 --- a/src/lib-storage/index/pop3c/pop3c-storage.c +++ b/src/lib-storage/index/pop3c/pop3c-storage.c @@ -8,7 +8,6 @@ #include "mailbox-list-private.h" #include "index-mail.h" #include "pop3c-client.h" -#include "pop3c-settings.h" #include "pop3c-sync.h" #include "pop3c-storage.h"