This replaces the LITERAL+ capability when the imap_literal_minus setting is enabled.
dnl IDLE doesn't really belong to banner. It's there just to make Blackberries
dnl happy, because otherwise BIS server disables push email.
-capability_banner="IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE"
+capability_banner="IMAP4rev1 SASL-IR LOGIN-REFERRALS ID ENABLE IDLE"
capability="$capability_banner SORT SORT=DISPLAY THREAD=REFERENCES THREAD=REFS THREAD=ORDEREDSUBJECT MULTIAPPEND URL-PARTIAL CATENATE UNSELECT CHILDREN NAMESPACE UIDPLUS LIST-EXTENDED I18NLEVEL=1 CONDSTORE QRESYNC ESEARCH ESORT SEARCHRES WITHIN CONTEXT=SEARCH LIST-STATUS BINARY MOVE"
AC_DEFINE_UNQUOTED(CAPABILITY_STRING, "$capability", [IMAP capabilities])
AC_DEFINE_UNQUOTED(CAPABILITY_BANNER_STRING, "$capability_banner", [IMAP capabilities advertised in banner])
# Host allowed in URLAUTH URLs sent by client. "*" allows all.
#imap_urlauth_host =
+# Enable IMAP LITERAL- extension (replaces LITERAL+)
+#imap_literal_minus = no
+
protocol imap {
# Space separated list of plugins to load (default is global mail_plugins).
#mail_plugins = $mail_plugins
{
struct imap_client *imap_client = (struct imap_client *)client;
string_t *cap_str = t_str_new(256);
+ bool explicit_capability = FALSE;
if (*imap_client->set->imap_capability == '\0')
str_append(cap_str, CAPABILITY_BANNER_STRING);
- else if (*imap_client->set->imap_capability != '+')
+ else if (*imap_client->set->imap_capability != '+') {
+ explicit_capability = TRUE;
str_append(cap_str, imap_client->set->imap_capability);
- else {
+ } else {
str_append(cap_str, CAPABILITY_BANNER_STRING);
str_append_c(cap_str, ' ');
str_append(cap_str, imap_client->set->imap_capability + 1);
}
+ if (!explicit_capability) {
+ if (imap_client->set->imap_literal_minus)
+ str_append(cap_str, " LITERAL-");
+ else
+ str_append(cap_str, " LITERAL+");
+ }
+
if (client_is_tls_enabled(client) && !client->tls)
str_append(cap_str, " STARTTLS");
if (is_login_cmd_disabled(client))
id->parser = imap_parser_create(client->common.input,
client->common.output,
MAX_IMAP_LINE);
+ if (client->set->imap_literal_minus)
+ imap_parser_enable_literal_minus(id->parser);
parser_flags = IMAP_PARSE_FLAG_STOP_AT_LIST;
} else {
id = client->cmd_id;
imap_client->parser =
imap_parser_create(imap_client->common.input,
imap_client->common.output, MAX_IMAP_LINE);
+ if (imap_client->set->imap_literal_minus)
+ imap_parser_enable_literal_minus(imap_client->parser);
client->io = io_add(client->fd, IO_READ, client_input, client);
}
DEF(SET_STR, imap_capability),
DEF(SET_STR, imap_id_send),
DEF(SET_STR, imap_id_log),
+ DEF(SET_BOOL, imap_literal_minus),
SETTING_DEFINE_LIST_END
};
static const struct imap_login_settings imap_login_default_settings = {
.imap_capability = "",
.imap_id_send = "name *",
- .imap_id_log = ""
+ .imap_id_log = "",
+ .imap_literal_minus = FALSE
};
static const struct setting_parser_info *imap_login_setting_dependencies[] = {
const char *imap_capability;
const char *imap_id_send;
const char *imap_id_log;
+ bool imap_literal_minus;
};
extern const struct setting_parser_info *imap_login_setting_roots[];
case IMAP_PARSE_ERROR_NONE:
i_unreached();
case IMAP_PARSE_ERROR_LITERAL_TOO_BIG:
- client_disconnect_with_error(client, msg);
+ client_send_line(client, t_strconcat("* BYE ",
+ (client->set->imap_literal_minus ? "[TOOBIG] " : ""),
+ msg, NULL));
+ client_disconnect(client, msg);
break;
default:
if (!ctx->failed)
case IMAP_PARSE_ERROR_NONE:
i_unreached();
case IMAP_PARSE_ERROR_LITERAL_TOO_BIG:
- client_disconnect_with_error(client, msg);
+ client_send_line(client, t_strconcat("* BYE ",
+ (client->set->imap_literal_minus ? "[TOOBIG] " : ""),
+ msg, NULL));
+ client_disconnect(client, msg);
break;
default:
client_send_command_error(cmd, msg);
ctx->save_parser = imap_parser_create(client->input, client->output,
client->set->imap_max_line_length);
+ if (client->set->imap_literal_minus)
+ imap_parser_enable_literal_minus(ctx->save_parser);
cmd->func = cmd_append_parse_new_msg;
cmd->context = ctx;
client->input_lock = cmd;
ctx->parser = imap_parser_create(client->input, client->output,
client->set->imap_max_line_length);
+ if (client->set->imap_literal_minus)
+ imap_parser_enable_literal_minus(ctx->parser);
o_stream_unset_flush_callback(client->output);
cmd->func = cmd_setmetadata_continue;
str_append_c(client->capability_string, ' ');
str_append(client->capability_string, set->imap_capability + 1);
}
+ if (!explicit_capability) {
+ if (client->set->imap_literal_minus)
+ str_append(client->capability_string, " LITERAL-");
+ else
+ str_append(client->capability_string, " LITERAL+");
+ }
if (user->fuzzy_search && !explicit_capability) {
/* Enable FUZZY capability only when it actually has
a chance of working */
cmd->parser =
imap_parser_create(client->input, client->output,
client->set->imap_max_line_length);
+ if (client->set->imap_literal_minus)
+ imap_parser_enable_literal_minus(cmd->parser);
}
return cmd;
}
DEF(SET_STR, imap_id_send),
DEF(SET_STR, imap_id_log),
DEF(SET_BOOL, imap_metadata),
+ DEF(SET_BOOL, imap_literal_minus),
DEF(SET_TIME, imap_hibernate_timeout),
DEF(SET_STR, imap_urlauth_host),
.imap_id_send = "name *",
.imap_id_log = "",
.imap_metadata = FALSE,
+ .imap_literal_minus = FALSE,
.imap_hibernate_timeout = 0,
.imap_urlauth_host = "",
const char *imap_id_send;
const char *imap_id_log;
bool imap_metadata;
+ bool imap_literal_minus;
unsigned int imap_hibernate_timeout;
/* imap urlauth: */
enum imap_parser_error error;
const char *error_msg;
+ unsigned int literal_minus:1;
unsigned int literal_skip_crlf:1;
unsigned int literal_nonsync:1;
unsigned int literal8:1;
*parser = NULL;
}
+void imap_parser_enable_literal_minus(struct imap_parser *parser)
+{
+ parser->literal_minus = TRUE;
+}
+
void imap_parser_reset(struct imap_parser *parser)
{
p_clear(parser->pool);
static int imap_parser_literal_end(struct imap_parser *parser)
{
+ if (parser->literal_minus && parser->literal_nonsync &&
+ parser->literal_size > 4096) {
+ parser->error_msg = "Non-synchronizing literal size too large";
+ parser->error = IMAP_PARSE_ERROR_LITERAL_TOO_BIG;
+ return FALSE;
+ }
+
if ((parser->flags & IMAP_PARSE_FLAG_LITERAL_SIZE) == 0) {
if (parser->line_size >= parser->max_line_size ||
parser->literal_size >
void imap_parser_ref(struct imap_parser *parser);
void imap_parser_unref(struct imap_parser **parser);
+/* Enable LITERAL- parser semantics: non-synchronizing literals must not
+ exceed 4096 bytes */
+void imap_parser_enable_literal_minus(struct imap_parser *parser);
+
/* Reset the parser to initial state. */
void imap_parser_reset(struct imap_parser *parser);