dovecot/dovecot-a744ae38a9e1.patch
Tomas Janousek b1451a6432 - update to a744ae38a9e1 from hg
- update dovecot-sieve to 131e25f6862b from hg and enable it again
2007-07-25 11:02:09 +00:00

4504 lines
150 KiB
Diff

diff --git a/NEWS b/NEWS
index 2251856..954db2b 100644
--- a/NEWS
+++ b/NEWS
@@ -15,7 +15,7 @@ v1.1.UNSTABLE
It's similar to REFERENCES, but it doesn't do base subject merging
and it sorts the threads by their newest message.
+ When saving messages, update cache file immediately with the data
- that we expect client to fetch later. Maildir-only currently.
+ that we expect client to fetch later.
+ NFS attribute and data caches are are flushed whenever needed.
See mail_nfs_storage and mail_nfs_index settings.
+ Mailbox list indexes. Mailbox metadata is stored there, so STATUS
diff --git a/configure.in b/configure.in
index 156e9d7..3f93ca6 100644
--- a/configure.in
+++ b/configure.in
@@ -82,7 +82,7 @@ AC_ARG_WITH(passwd,
fi,
want_passwd=yes)
-AC_ARG_WITH(passwd,
+AC_ARG_WITH(nss,
[ --with-nss Build with NSS module support (default)],
if test x$withval = xno; then
want_nss=no
diff --git a/doc/dovecot-ldap-example.conf b/doc/dovecot-ldap-example.conf
index 334ae8f..62ec866 100644
--- a/doc/dovecot-ldap-example.conf
+++ b/doc/dovecot-ldap-example.conf
@@ -106,7 +106,8 @@ base = uid=someone, dc=foo, dc=bar, dc=org
# userdb prefetch instead of userdb ldap in dovecot.conf. In that case you'll
# also have to include user_attrs in pass_attrs field prefixed with "userdb_"
# string. For example:
-#pass_attrs = uid=user,userPassword=password,homeDirectory=userdb_home,uidNumber=userdb_uid,gidNumber=userdb_gid
+#pass_attrs = uid=user,userPassword=password,\
+# homeDirectory=userdb_home,uidNumber=userdb_uid,gidNumber=userdb_gid
# Filter for password lookups
#pass_filter = (&(objectClass=posixAccount)(uid=%u))
diff --git a/doc/dovecot-sql-example.conf b/doc/dovecot-sql-example.conf
index bfc4b82..55fc998 100644
--- a/doc/dovecot-sql-example.conf
+++ b/doc/dovecot-sql-example.conf
@@ -88,7 +88,9 @@
# password_query = SELECT concat(userid, '@', domain) AS user, password FROM users WHERE userid = '%n' AND domain = '%d'
# password_query = SELECT pw AS password FROM users WHERE userid = '%u' AND active = 'Y'
#
-#password_query = SELECT userid as user, password FROM users WHERE userid = '%u'
+#password_query = \
+# SELECT userid as user, password \
+# FROM users WHERE userid = '%u'
# Query to retrieve the user information.
#
@@ -114,4 +116,7 @@
# userdb prefetch instead of userdb sql in dovecot.conf. In that case you'll
# also have to return userdb fields in password_query prefixed with "userdb_"
# string. For example:
-#password_query = SELECT userid as user, password, home as userdb_home, uid as userdb_uid, gid as userdb_gid FROM users WHERE userid = '%u'
+#password_query = \
+# SELECT userid as user, password, \
+# home as userdb_home, uid as userdb_uid, gid as userdb_gid \
+# FROM users WHERE userid = '%u'
diff --git a/src/auth/auth-client-connection.c b/src/auth/auth-client-connection.c
index d596854..e913a2e 100644
--- a/src/auth/auth-client-connection.c
+++ b/src/auth/auth-client-connection.c
@@ -275,10 +275,9 @@ auth_client_connection_create(struct auth_master_listener *listener, int fd)
conn->fd = fd;
conn->input =
- i_stream_create_file(fd, default_pool,
- AUTH_CLIENT_MAX_LINE_LENGTH, FALSE);
+ i_stream_create_file(fd, AUTH_CLIENT_MAX_LINE_LENGTH, FALSE);
conn->output =
- o_stream_create_file(fd, default_pool, (size_t)-1, FALSE);
+ o_stream_create_file(fd, (size_t)-1, FALSE);
o_stream_set_flush_callback(conn->output, auth_client_output, conn);
conn->io = io_add(fd, IO_READ, auth_client_input, conn);
diff --git a/src/auth/auth-master-connection.c b/src/auth/auth-master-connection.c
index d18c70e..ddfe029 100644
--- a/src/auth/auth-master-connection.c
+++ b/src/auth/auth-master-connection.c
@@ -242,10 +242,8 @@ auth_master_connection_create(struct auth_master_listener *listener, int fd)
conn->listener = listener;
conn->refcount = 1;
conn->fd = fd;
- conn->input = i_stream_create_file(fd, default_pool,
- MAX_INBUF_SIZE, FALSE);
- conn->output = o_stream_create_file(fd, default_pool,
- (size_t)-1, FALSE);
+ conn->input = i_stream_create_file(fd, MAX_INBUF_SIZE, FALSE);
+ conn->output = o_stream_create_file(fd, (size_t)-1, FALSE);
o_stream_set_flush_callback(conn->output, master_output, conn);
conn->io = io_add(fd, IO_READ, master_input, conn);
diff --git a/src/auth/auth-worker-client.c b/src/auth/auth-worker-client.c
index 2fca127..58ba197 100644
--- a/src/auth/auth-worker-client.c
+++ b/src/auth/auth-worker-client.c
@@ -468,10 +468,9 @@ auth_worker_client_create(struct auth *auth, int fd)
client->auth = auth;
client->fd = fd;
client->input =
- i_stream_create_file(fd, default_pool,
- AUTH_WORKER_MAX_LINE_LENGTH, FALSE);
+ i_stream_create_file(fd, AUTH_WORKER_MAX_LINE_LENGTH, FALSE);
client->output =
- o_stream_create_file(fd, default_pool, (size_t)-1, FALSE);
+ o_stream_create_file(fd, (size_t)-1, FALSE);
o_stream_set_flush_callback(client->output, auth_worker_output, client);
client->io = io_add(fd, IO_READ, auth_worker_input, client);
diff --git a/src/auth/auth-worker-server.c b/src/auth/auth-worker-server.c
index 537650b..b36c61e 100644
--- a/src/auth/auth-worker-server.c
+++ b/src/auth/auth-worker-server.c
@@ -79,10 +79,9 @@ static struct auth_worker_connection *auth_worker_create(void)
conn = i_new(struct auth_worker_connection, 1);
conn->fd = fd;
- conn->input = i_stream_create_file(fd, default_pool,
- AUTH_WORKER_MAX_LINE_LENGTH, FALSE);
- conn->output =
- o_stream_create_file(fd, default_pool, (size_t)-1, FALSE);
+ conn->input = i_stream_create_file(fd, AUTH_WORKER_MAX_LINE_LENGTH,
+ FALSE);
+ conn->output = o_stream_create_file(fd, (size_t)-1, FALSE);
conn->io = io_add(fd, IO_READ, worker_input, conn);
conn->requests = buffer_create_dynamic(default_pool, 128);
diff --git a/src/auth/db-ldap.c b/src/auth/db-ldap.c
index 7b564d1..363461c 100644
--- a/src/auth/db-ldap.c
+++ b/src/auth/db-ldap.c
@@ -52,9 +52,11 @@ struct db_ldap_result_iterate_context {
char *attr, **vals;
const char *name, *value, *template, *val_1_arr[2];
+ const char *const *static_attrs;
BerElement *ber;
string_t *var, *debug;
+ unsigned int value_idx;
};
#define DEF_STR(name) DEF_STRUCT_STR(name, ldap_settings)
@@ -102,9 +104,9 @@ struct ldap_settings default_ldap_settings = {
MEMBER(scope) "subtree",
MEMBER(base) NULL,
MEMBER(ldap_version) 2,
- MEMBER(user_attrs) "uid,homeDirectory,,,uidNumber,gidNumber",
+ MEMBER(user_attrs) "homeDirectory=home,uidNumber=uid,gidNumber=gid",
MEMBER(user_filter) "(&(objectClass=posixAccount)(uid=%u))",
- MEMBER(pass_attrs) "uid,userPassword",
+ MEMBER(pass_attrs) "uid=user,userPassword=password",
MEMBER(pass_filter) "(&(objectClass=posixAccount)(uid=%u))",
MEMBER(default_pass_scheme) "crypt"
};
@@ -618,10 +620,10 @@ static void ldap_conn_close(struct ldap_connection *conn, bool flush_requests)
void db_ldap_set_attrs(struct ldap_connection *conn, const char *attrlist,
char ***attr_names_r, struct hash_table *attr_map,
- const char *const default_attr_map[],
const char *skip_attr)
{
const char *const *attr;
+ string_t *static_data;
char *name, *value, *p;
unsigned int i, j, size;
@@ -630,6 +632,7 @@ void db_ldap_set_attrs(struct ldap_connection *conn, const char *attrlist,
t_push();
attr = t_strsplit(attrlist, ",");
+ static_data = t_str_new(128);
/* @UNSAFE */
for (size = 0; attr[size] != NULL; size++) ;
@@ -637,13 +640,17 @@ void db_ldap_set_attrs(struct ldap_connection *conn, const char *attrlist,
for (i = j = 0; i < size; i++) {
p = strchr(attr[i], '=');
- if (p == NULL) {
- name = p_strdup(conn->pool, attr[i]);
- value = *default_attr_map == NULL ? name :
- p_strdup(conn->pool, *default_attr_map);
- } else {
+ if (p == NULL)
+ name = value = p_strdup(conn->pool, attr[i]);
+ else if (p != attr[i]) {
name = p_strdup_until(conn->pool, attr[i], p);
value = p_strdup(conn->pool, p + 1);
+ } else {
+ /* =<static key>=<static value> */
+ if (str_len(static_data) > 0)
+ str_append_c(static_data, ',');
+ str_append(static_data, p + 1);
+ continue;
}
if (*name != '\0' &&
@@ -651,9 +658,10 @@ void db_ldap_set_attrs(struct ldap_connection *conn, const char *attrlist,
hash_insert(attr_map, name, value);
(*attr_names_r)[j++] = name;
}
-
- if (*default_attr_map != NULL)
- default_attr_map++;
+ }
+ if (str_len(static_data) > 0) {
+ hash_insert(attr_map, "",
+ p_strdup(conn->pool, str_c(static_data)));
}
t_pop();
}
@@ -709,6 +717,7 @@ db_ldap_result_iterate_init(struct ldap_connection *conn, LDAPMessage *entry,
struct hash_table *attr_map)
{
struct db_ldap_result_iterate_context *ctx;
+ const char *static_data;
ctx = t_new(struct db_ldap_result_iterate_context, 1);
ctx->conn = conn;
@@ -716,6 +725,10 @@ db_ldap_result_iterate_init(struct ldap_connection *conn, LDAPMessage *entry,
ctx->auth_request = auth_request;
ctx->attr_map = attr_map;
+ static_data = hash_lookup(attr_map, "");
+ if (static_data != NULL)
+ ctx->static_attrs = t_strsplit(static_data, ",");
+
if (auth_request->auth->verbose_debug)
ctx->debug = t_str_new(256);
@@ -764,12 +777,13 @@ db_ldap_result_change_attr(struct db_ldap_result_iterate_context *ctx)
ctx->vals = ldap_get_values(ctx->conn->ld, ctx->entry,
ctx->attr);
ctx->value = ctx->vals[0];
+ ctx->value_idx = 0;
}
static void
db_ldap_result_return_value(struct db_ldap_result_iterate_context *ctx)
{
- bool first = ctx->value == ctx->vals[0];
+ bool first = ctx->value_idx == 0;
if (ctx->template != NULL) {
ctx->var_table[0].value = ctx->value;
@@ -791,6 +805,8 @@ db_ldap_result_return_value(struct db_ldap_result_iterate_context *ctx)
static bool db_ldap_result_int_next(struct db_ldap_result_iterate_context *ctx)
{
+ const char *p;
+
while (ctx->attr != NULL) {
if (ctx->vals == NULL) {
/* a new attribute */
@@ -798,7 +814,7 @@ static bool db_ldap_result_int_next(struct db_ldap_result_iterate_context *ctx)
} else {
/* continuing existing attribute */
if (ctx->value != NULL)
- ctx->value++;
+ ctx->value = ctx->vals[++ctx->value_idx];
}
if (ctx->value != NULL) {
@@ -812,6 +828,19 @@ static bool db_ldap_result_int_next(struct db_ldap_result_iterate_context *ctx)
ctx->ber);
}
+ if (ctx->static_attrs != NULL && *ctx->static_attrs != NULL) {
+ p = strchr(*ctx->static_attrs, '=');
+ if (p == NULL) {
+ ctx->name = *ctx->static_attrs;
+ ctx->value = "";
+ } else {
+ ctx->name = t_strdup_until(*ctx->static_attrs, p);
+ ctx->value = p + 1;
+ }
+ ctx->static_attrs++;
+ return TRUE;
+ }
+
db_ldap_result_iterate_finish(ctx);
return FALSE;
}
diff --git a/src/auth/db-ldap.h b/src/auth/db-ldap.h
index 621e8b9..36823c2 100644
--- a/src/auth/db-ldap.h
+++ b/src/auth/db-ldap.h
@@ -99,7 +99,6 @@ void db_ldap_search(struct ldap_connection *conn, struct ldap_request *request,
void db_ldap_set_attrs(struct ldap_connection *conn, const char *attrlist,
char ***attr_names_r, struct hash_table *attr_map,
- const char *const default_attr_map[],
const char *skip_attr);
struct ldap_connection *db_ldap_init(const char *config_path);
diff --git a/src/auth/db-passwd-file.c b/src/auth/db-passwd-file.c
index 74c1f3d..27ac55e 100644
--- a/src/auth/db-passwd-file.c
+++ b/src/auth/db-passwd-file.c
@@ -183,7 +183,7 @@ static bool passwd_file_open(struct passwd_file *pw)
pw->users = hash_create(default_pool, pw->pool, 100,
str_hash, (hash_cmp_callback_t *)strcmp);
- input = i_stream_create_file(pw->fd, default_pool, 4096, FALSE);
+ input = i_stream_create_file(pw->fd, 4096, FALSE);
while ((line = i_stream_read_next_line(input)) != NULL) {
if (*line == '\0' || *line == ':' || *line == '#')
continue; /* no username or comment */
diff --git a/src/auth/passdb-ldap.c b/src/auth/passdb-ldap.c
index 45db512..1d43851 100644
--- a/src/auth/passdb-ldap.c
+++ b/src/auth/passdb-ldap.c
@@ -15,10 +15,6 @@
#include <ldap.h>
#include <stdlib.h>
-static const char *default_attr_map[] = {
- "user", "password", NULL
-};
-
struct ldap_passdb_module {
struct passdb_module module;
@@ -434,7 +430,7 @@ passdb_ldap_preinit(struct auth_passdb *auth_passdb, const char *args)
if (conn->set.auth_bind_userdn != NULL)
conn->set.auth_bind = TRUE;
db_ldap_set_attrs(conn, conn->set.pass_attrs, &conn->pass_attr_names,
- conn->pass_attr_map, default_attr_map,
+ conn->pass_attr_map,
conn->set.auth_bind ? "password" : NULL);
module->module.cache_key =
auth_cache_parse_key(auth_passdb->auth->pool,
diff --git a/src/auth/userdb-ldap.c b/src/auth/userdb-ldap.c
index 3a8d2f5..170add0 100644
--- a/src/auth/userdb-ldap.c
+++ b/src/auth/userdb-ldap.c
@@ -26,10 +26,6 @@ struct userdb_ldap_request {
userdb_callback_t *userdb_callback;
};
-static const char *default_attr_map[] = {
- "", "home", "mail", "system_user", "uid", "gid", NULL
-};
-
static void
ldap_query_get_result(struct ldap_connection *conn, LDAPMessage *entry,
struct auth_request *auth_request)
@@ -37,6 +33,8 @@ ldap_query_get_result(struct ldap_connection *conn, LDAPMessage *entry,
struct db_ldap_result_iterate_context *ldap_iter;
const char *name, *const *values;
+ auth_request_init_userdb_reply(auth_request);
+
ldap_iter = db_ldap_result_iterate_init(conn, entry, auth_request,
conn->user_attr_map);
while (db_ldap_result_iterate_next_all(ldap_iter, &name, &values)) {
@@ -139,7 +137,7 @@ userdb_ldap_preinit(struct auth_userdb *auth_userdb, const char *args)
(hash_cmp_callback_t *)strcmp);
db_ldap_set_attrs(conn, conn->set.user_attrs, &conn->user_attr_names,
- conn->user_attr_map, default_attr_map, NULL);
+ conn->user_attr_map, NULL);
module->module.cache_key =
auth_cache_parse_key(auth_userdb->auth->pool,
conn->set.user_filter);
diff --git a/src/deliver/auth-client.c b/src/deliver/auth-client.c
index 083a70e..8a865bd 100644
--- a/src/deliver/auth-client.c
+++ b/src/deliver/auth-client.c
@@ -179,10 +179,8 @@ static struct auth_connection *auth_connection_new(const char *auth_socket)
conn = i_new(struct auth_connection, 1);
conn->fd = fd;
- conn->input =
- i_stream_create_file(fd, default_pool, MAX_INBUF_SIZE, FALSE);
- conn->output =
- o_stream_create_file(fd, default_pool, MAX_OUTBUF_SIZE, FALSE);
+ conn->input = i_stream_create_file(fd, MAX_INBUF_SIZE, FALSE);
+ conn->output = o_stream_create_file(fd, MAX_OUTBUF_SIZE, FALSE);
conn->io = io_add(fd, IO_READ, auth_input, conn);
return conn;
}
diff --git a/src/deliver/deliver.c b/src/deliver/deliver.c
index 42bb812..e38a621 100644
--- a/src/deliver/deliver.c
+++ b/src/deliver/deliver.c
@@ -229,7 +229,7 @@ static void config_file_init(const char *path)
i_fatal_status(EX_CONFIG, "open(%s) failed: %m", path);
t_push();
- input = i_stream_create_file(fd, default_pool, 1024, TRUE);
+ input = i_stream_create_file(fd, 1024, TRUE);
while ((line = i_stream_read_next_line(input)) != NULL) {
/* @UNSAFE: line is modified */
@@ -417,7 +417,7 @@ static struct istream *create_mbox_stream(int fd, const char *envelope_sender)
envelope_sender = address_sanitize(envelope_sender);
mbox_hdr = mbox_from_create(envelope_sender, ioloop_time);
- input = i_stream_create_file(fd, default_pool, 4096, FALSE);
+ input = i_stream_create_file(fd, 4096, FALSE);
input_filter =
i_stream_create_header_filter(input,
HEADER_FILTER_EXCLUDE |
@@ -428,14 +428,12 @@ static struct istream *create_mbox_stream(int fd, const char *envelope_sender)
NULL);
i_stream_unref(&input);
- input_list[0] = i_stream_create_from_data(default_pool, mbox_hdr,
- strlen(mbox_hdr));
+ input_list[0] = i_stream_create_from_data(mbox_hdr, strlen(mbox_hdr));
input_list[1] = input_filter;
- input_list[2] = i_stream_create_from_data(default_pool, "\n", 1);
+ input_list[2] = i_stream_create_from_data("\n", 1);
input_list[3] = NULL;
- input = i_stream_create_seekable(input_list, default_pool,
- MAIL_MAX_MEMORY_BUFFER,
+ input = i_stream_create_seekable(input_list, MAIL_MAX_MEMORY_BUFFER,
"/tmp/dovecot.deliver.");
i_stream_unref(&input_list[0]);
i_stream_unref(&input_list[1]);
@@ -754,28 +752,46 @@ int main(int argc, char *argv[])
if (mail_set_seq(mail, 1) < 0)
i_fatal("mail_set_seq() failed");
+ storage = NULL;
default_mailbox_name = mailbox;
- if (deliver_mail != NULL)
- (void)deliver_mail(ns, &storage, mail, destination, mailbox);
+ if (deliver_mail == NULL)
+ ret = -1;
+ else {
+ if (deliver_mail(ns, &storage, mail,
+ destination, mailbox) <= 0) {
+ /* if message was saved, don't bounce it even though
+ the script failed later. */
+ ret = saved_mail ? 0 : -1;
+ } else {
+ /* success. message may or may not have been saved. */
+ ret = 0;
+ }
+ }
- if (!saved_mail && !tried_default_save) {
+ if (ret < 0 && !tried_default_save) {
/* plugins didn't handle this. save into the default mailbox. */
i_stream_seek(input, 0);
- (void)deliver_save(ns, &storage, mailbox, mail, 0, NULL);
+ ret = deliver_save(ns, &storage, mailbox, mail, 0, NULL);
}
- if (!saved_mail && strcasecmp(mailbox, "INBOX") != 0) {
+ if (ret < 0 && strcasecmp(mailbox, "INBOX") != 0) {
/* still didn't work. try once more to save it
to INBOX. */
i_stream_seek(input, 0);
- (void)deliver_save(ns, &storage, "INBOX", mail, 0, NULL);
+ ret = deliver_save(ns, &storage, "INBOX", mail, 0, NULL);
}
- if (!saved_mail) {
+ if (ret < 0 ) {
const char *error_string, *msgid;
enum mail_error error;
int ret;
- error_string = mail_storage_get_last_error(ns->storage, &error);
+ if (storage == NULL) {
+ /* This shouldn't happen */
+ i_error("BUG: Saving failed for unknown storage");
+ return EX_TEMPFAIL;
+ }
+
+ error_string = mail_storage_get_last_error(storage, &error);
if (error != MAIL_ERROR_NOSPACE ||
getenv("QUOTA_FULL_TEMPFAIL") != NULL) {
/* Saving to INBOX should always work unless
diff --git a/src/deliver/duplicate.c b/src/deliver/duplicate.c
index bb6f5d5..a724cc9 100644
--- a/src/deliver/duplicate.c
+++ b/src/deliver/duplicate.c
@@ -94,7 +94,7 @@ static int duplicate_read(struct duplicate_file *file)
}
/* <timestamp> <id_size> <user_size> <id> <user> */
- input = i_stream_create_file(fd, default_pool, 4096, FALSE);
+ input = i_stream_create_file(fd, 4096, FALSE);
change_count = 0;
while (i_stream_read_data(input, &data, &size, sizeof(stamp) +
@@ -218,7 +218,7 @@ void duplicate_flush(void)
if (duplicate_file == NULL || !file->changed || file->new_fd == -1)
return;
- output = o_stream_create_file(file->new_fd, default_pool, 4096, FALSE);
+ output = o_stream_create_file(file->new_fd, 4096, FALSE);
iter = hash_iterate_init(file->hash);
while (hash_iterate(iter, &key, &value)) {
struct duplicate *d = value;
diff --git a/src/dict/dict-server.c b/src/dict/dict-server.c
index 1fa9609..6acf34b 100644
--- a/src/dict/dict-server.c
+++ b/src/dict/dict-server.c
@@ -446,9 +446,9 @@ dict_client_connection_init(struct dict_server *server, int fd)
conn = i_new(struct dict_client_connection, 1);
conn->server = server;
conn->fd = fd;
- conn->input = i_stream_create_file(fd, default_pool,
- DICT_CLIENT_MAX_LINE_LENGTH, FALSE);
- conn->output = o_stream_create_file(fd, default_pool, 128*1024, FALSE);
+ conn->input = i_stream_create_file(fd, DICT_CLIENT_MAX_LINE_LENGTH,
+ FALSE);
+ conn->output = o_stream_create_file(fd, 128*1024, FALSE);
conn->io = io_add(fd, IO_READ, dict_client_connection_input, conn);
return conn;
}
diff --git a/src/imap-login/client.c b/src/imap-login/client.c
index 6fa0e76..e984ce9 100644
--- a/src/imap-login/client.c
+++ b/src/imap-login/client.c
@@ -68,10 +68,8 @@ static void client_set_title(struct imap_client *client)
static void client_open_streams(struct imap_client *client, int fd)
{
- client->input = i_stream_create_file(fd, default_pool,
- MAX_INBUF_SIZE, FALSE);
- client->output = o_stream_create_file(fd, default_pool, MAX_OUTBUF_SIZE,
- FALSE);
+ client->input = i_stream_create_file(fd, MAX_INBUF_SIZE, FALSE);
+ client->output = o_stream_create_file(fd, MAX_OUTBUF_SIZE, FALSE);
client->parser = imap_parser_create(client->input, client->output,
MAX_IMAP_LINE);
}
diff --git a/src/imap/client.c b/src/imap/client.c
index 1036e9e..99df764 100644
--- a/src/imap/client.c
+++ b/src/imap/client.c
@@ -30,10 +30,9 @@ struct client *client_create(int fd_in, int fd_out,
client = i_new(struct client, 1);
client->fd_in = fd_in;
client->fd_out = fd_out;
- client->input = i_stream_create_file(fd_in, default_pool,
- imap_max_line_length, FALSE);
- client->output = o_stream_create_file(fd_out, default_pool,
- (size_t)-1, FALSE);
+ client->input =
+ i_stream_create_file(fd_in, imap_max_line_length, FALSE);
+ client->output = o_stream_create_file(fd_out, (size_t)-1, FALSE);
o_stream_set_flush_callback(client->output, _client_output, client);
diff --git a/src/imap/cmd-append.c b/src/imap/cmd-append.c
index ccbce56..2f1ec5f 100644
--- a/src/imap/cmd-append.c
+++ b/src/imap/cmd-append.c
@@ -186,7 +186,7 @@ static bool cmd_append_cancel(struct cmd_append_context *ctx, bool nonsync)
/* we have to read the nonsynced literal so we don't treat the message
data as commands. */
- ctx->input = i_stream_create_limit(default_pool, ctx->client->input,
+ ctx->input = i_stream_create_limit(ctx->client->input,
ctx->client->input->v_offset,
ctx->msg_size);
@@ -317,7 +317,7 @@ static bool cmd_append_continue_parsing(struct client_command_context *cmd)
}
/* save the mail */
- ctx->input = i_stream_create_limit(default_pool, client->input,
+ ctx->input = i_stream_create_limit(client->input,
client->input->v_offset,
ctx->msg_size);
ret = mailbox_save_init(ctx->t, flags, keywords,
diff --git a/src/imap/imap-fetch-body.c b/src/imap/imap-fetch-body.c
index 392b4a3..23712d0 100644
--- a/src/imap/imap-fetch-body.c
+++ b/src/imap/imap-fetch-body.c
@@ -280,7 +280,7 @@ static int fetch_stream(struct imap_fetch_context *ctx,
if (size->physical_size == size->virtual_size &&
ctx->cur_mail->has_no_nuls) {
/* no need to kludge with CRs, we can use sendfile() */
- input = i_stream_create_limit(default_pool, ctx->cur_input,
+ input = i_stream_create_limit(ctx->cur_input,
ctx->cur_input->v_offset,
ctx->cur_size);
i_stream_unref(&ctx->cur_input);
diff --git a/src/lib-auth/auth-server-connection.c b/src/lib-auth/auth-server-connection.c
index 3f5d5c0..3ba6111 100644
--- a/src/lib-auth/auth-server-connection.c
+++ b/src/lib-auth/auth-server-connection.c
@@ -226,10 +226,9 @@ auth_server_connection_new(struct auth_client *client, const char *path)
conn->path = p_strdup(pool, path);
conn->fd = fd;
conn->io = io_add(fd, IO_READ, auth_client_input, conn);
- conn->input = i_stream_create_file(fd, default_pool,
- AUTH_CLIENT_MAX_LINE_LENGTH, FALSE);
- conn->output = o_stream_create_file(fd, default_pool, (size_t)-1,
- FALSE);
+ conn->input = i_stream_create_file(fd, AUTH_CLIENT_MAX_LINE_LENGTH,
+ FALSE);
+ conn->output = o_stream_create_file(fd, (size_t)-1, FALSE);
conn->requests = hash_create(default_pool, pool, 100, NULL, NULL);
conn->auth_mechs_buf = buffer_create_dynamic(default_pool, 256);
diff --git a/src/lib-charset/charset-iconv.c b/src/lib-charset/charset-iconv.c
index 955cf5d..da6aa48 100644
--- a/src/lib-charset/charset-iconv.c
+++ b/src/lib-charset/charset-iconv.c
@@ -1,7 +1,8 @@
-/* Copyright (C) 2002 Timo Sirainen */
+/* Copyright (C) 2002-2007 Timo Sirainen */
#include "lib.h"
#include "buffer.h"
+#include "unichar.h"
#include "charset-utf8.h"
#ifdef HAVE_ICONV
@@ -11,31 +12,28 @@
struct charset_translation {
iconv_t cd;
+ enum charset_flags flags;
};
-struct charset_translation *charset_to_utf8_begin(const char *charset,
- bool *unknown_charset)
+int charset_to_utf8_begin(const char *charset, enum charset_flags flags,
+ struct charset_translation **t_r)
{
struct charset_translation *t;
iconv_t cd;
- if (unknown_charset != NULL)
- *unknown_charset = FALSE;
-
if (charset_is_utf8(charset))
cd = (iconv_t)-1;
else {
cd = iconv_open("UTF-8", charset);
- if (cd == (iconv_t)-1) {
- if (unknown_charset != NULL)
- *unknown_charset = TRUE;
- return NULL;
- }
+ if (cd == (iconv_t)-1)
+ return -1;
}
t = i_new(struct charset_translation, 1);
t->cd = cd;
- return t;
+ t->flags = flags;
+ *t_r = t;
+ return 0;
}
void charset_to_utf8_end(struct charset_translation **_t)
@@ -55,70 +53,90 @@ void charset_to_utf8_reset(struct charset_translation *t)
(void)iconv(t->cd, NULL, NULL, NULL, NULL);
}
-enum charset_result
-charset_to_ucase_utf8(struct charset_translation *t,
- const unsigned char *src, size_t *src_size,
- buffer_t *dest)
+static bool
+charset_to_utf8_try(struct charset_translation *t,
+ const unsigned char *src, size_t *src_size, buffer_t *dest,
+ enum charset_result *result)
{
ICONV_CONST char *ic_srcbuf;
- char *ic_destbuf;
- size_t srcleft, destpos, destleft, size;
- enum charset_result ret;
-
- destpos = buffer_get_used_size(dest);
- destleft = buffer_get_size(dest) - destpos;
+ char tmpbuf[8192], *ic_destbuf;
+ size_t srcleft, destleft;
+ bool dtcase = (t->flags & CHARSET_FLAG_DECOMP_TITLECASE) != 0;
+ bool ret = TRUE;
if (t->cd == (iconv_t)-1) {
/* no translation needed - just copy it to outbuf uppercased */
- if (*src_size > destleft)
- *src_size = destleft;
- _charset_utf8_ucase(src, *src_size, dest, destpos);
- return CHARSET_RET_OK;
+ *result = CHARSET_RET_OK;
+ if (!dtcase) {
+ buffer_append(dest, src, *src_size);
+ return TRUE;
+ }
+
+ if (uni_utf8_to_decomposed_titlecase(src, *src_size, dest) < 0)
+ *result = CHARSET_RET_INVALID_INPUT;
+ return TRUE;
+ }
+ if (!dtcase) {
+ destleft = buffer_get_size(dest) - dest->used;
+ if (destleft < *src_size) {
+ /* The buffer is most likely too small to hold the
+ output, so increase it at least to the input size. */
+ destleft = *src_size;
+ }
+ ic_destbuf = buffer_append_space_unsafe(dest, destleft);
+ } else {
+ destleft = sizeof(tmpbuf);
+ ic_destbuf = tmpbuf;
}
- size = destleft;
srcleft = *src_size;
ic_srcbuf = (ICONV_CONST char *) src;
- ic_destbuf = buffer_append_space_unsafe(dest, destleft);
if (iconv(t->cd, &ic_srcbuf, &srcleft,
&ic_destbuf, &destleft) != (size_t)-1)
- ret = CHARSET_RET_OK;
- else if (errno == E2BIG)
- ret = CHARSET_RET_OUTPUT_FULL;
- else if (errno == EINVAL)
- ret = CHARSET_RET_INCOMPLETE_INPUT;
+ *result = CHARSET_RET_OK;
+ else if (errno == E2BIG) {
+ /* set result just to avoid compiler warning */
+ *result = CHARSET_RET_INCOMPLETE_INPUT;
+ ret = FALSE;
+ } else if (errno == EINVAL)
+ *result = CHARSET_RET_INCOMPLETE_INPUT;
else {
/* should be EILSEQ */
- return CHARSET_RET_INVALID_INPUT;
+ *result = CHARSET_RET_INVALID_INPUT;
+ return TRUE;
}
- size -= destleft;
+ *src_size -= srcleft;
- /* give back the memory we didn't use */
- buffer_set_used_size(dest, buffer_get_used_size(dest) - destleft);
+ if (!dtcase) {
+ /* give back the memory we didn't use */
+ buffer_set_used_size(dest, dest->used - destleft);
+ } else {
+ size_t tmpsize = sizeof(tmpbuf) - destleft;
- *src_size -= srcleft;
- _charset_utf8_ucase((unsigned char *) ic_destbuf - size, size,
- dest, destpos);
+ /* we just converted data to UTF-8, it can't be invalid */
+ if (uni_utf8_to_decomposed_titlecase(tmpbuf, tmpsize, dest) < 0)
+ i_unreached();
+ }
return ret;
}
enum charset_result
-charset_to_ucase_utf8_full(struct charset_translation *t,
- const unsigned char *src, size_t *src_size,
- buffer_t *dest)
+charset_to_utf8(struct charset_translation *t,
+ const unsigned char *src, size_t *src_size, buffer_t *dest)
{
- enum charset_result ret;
+ enum charset_result result;
size_t pos, used, size;
+ bool ret;
for (pos = 0;;) {
size = *src_size - pos;
- ret = charset_to_ucase_utf8(t, src + pos, &size, dest);
+ ret = charset_to_utf8_try(t, src + pos, &size, dest, &result);
pos += size;
- if (ret != CHARSET_RET_OUTPUT_FULL) {
+ if (ret) {
*src_size = pos;
- return ret;
+ return result;
}
/* force buffer to grow */
@@ -129,89 +147,4 @@ charset_to_ucase_utf8_full(struct charset_translation *t,
}
}
-static const char *
-charset_to_utf8_string_int(const char *charset, bool *unknown_charset,
- const unsigned char *data, size_t size,
- size_t *utf8_size_r, bool ucase)
-{
- iconv_t cd;
- ICONV_CONST char *inbuf;
- char *outbuf, *outpos;
- size_t inleft, outleft, outsize, pos;
-
- if (charset == NULL || charset_is_utf8(charset)) {
- if (unknown_charset != NULL)
- *unknown_charset = FALSE;
-
- if (!ucase) {
- if (utf8_size_r != NULL)
- *utf8_size_r = size;
- return t_strndup(data, size);
- }
-
- return _charset_utf8_ucase_strdup(data, size, utf8_size_r);
- }
-
- cd = iconv_open("UTF-8", charset);
- if (cd == (iconv_t)-1) {
- if (unknown_charset != NULL)
- *unknown_charset = TRUE;
- return NULL;
- }
-
- if (unknown_charset != NULL)
- *unknown_charset = FALSE;
-
- inbuf = (ICONV_CONST char *) data;
- inleft = size;
-
- outsize = outleft = inleft * 2;
- outbuf = outpos = t_buffer_get(outsize + 1);
-
- while (iconv(cd, &inbuf, &inleft, &outpos, &outleft) == (size_t)-1) {
- if (errno != E2BIG) {
- /* invalid data */
- iconv_close(cd);
- return NULL;
- }
-
- /* output buffer too small, grow it */
- pos = outsize - outleft;
- outsize *= 2;
- outleft = outsize - pos;
-
- outbuf = t_buffer_reget(outbuf, outsize + 1);
- outpos = outbuf + pos;
- }
-
- if (utf8_size_r != NULL)
- *utf8_size_r = (size_t) (outpos - outbuf);
- *outpos++ = '\0';
- t_buffer_alloc((size_t) (outpos - outbuf));
-
- if (ucase)
- str_ucase(outbuf); /* FIXME: utf8 */
-
- iconv_close(cd);
- return outbuf;
-}
-
-const char *
-charset_to_utf8_string(const char *charset, bool *unknown_charset,
- const unsigned char *data, size_t size,
- size_t *utf8_size_r)
-{
- return charset_to_utf8_string_int(charset, unknown_charset,
- data, size, utf8_size_r, FALSE);
-}
-
-const char *
-charset_to_ucase_utf8_string(const char *charset, bool *unknown_charset,
- const unsigned char *data, size_t size,
- size_t *utf8_size_r)
-{
- return charset_to_utf8_string_int(charset, unknown_charset,
- data, size, utf8_size_r, TRUE);
-}
-
#endif
diff --git a/src/lib-charset/charset-utf8.c b/src/lib-charset/charset-utf8.c
index 3917ebb..71c6963 100644
--- a/src/lib-charset/charset-utf8.c
+++ b/src/lib-charset/charset-utf8.c
@@ -2,6 +2,7 @@
#include "lib.h"
#include "buffer.h"
+#include "unichar.h"
#include "charset-utf8.h"
#include <ctype.h>
@@ -14,59 +15,30 @@ bool charset_is_utf8(const char *charset)
strcasecmp(charset, "UTF8") == 0;
}
-void _charset_utf8_ucase(const unsigned char *src, size_t src_size,
- buffer_t *dest, size_t destpos)
-{
- char *destbuf;
- size_t i;
-
- destbuf = buffer_get_space_unsafe(dest, destpos, src_size);
- for (i = 0; i < src_size; i++)
- destbuf[i] = i_toupper(src[i]); /* FIXME: utf8 */
-}
-
-const char *_charset_utf8_ucase_strdup(const unsigned char *data, size_t size,
- size_t *utf8_size_r)
-{
- buffer_t *dest;
-
- dest = buffer_create_dynamic(pool_datastack_create(), size);
- _charset_utf8_ucase(data, size, dest, 0);
- if (utf8_size_r != NULL)
- *utf8_size_r = buffer_get_used_size(dest);
- buffer_append_c(dest, '\0');
- return buffer_free_without_data(dest);
-}
-
-
#ifndef HAVE_ICONV
-#include <ctype.h>
-
struct charset_translation {
- int dummy;
+ enum charset_flags flags;
};
-static struct charset_translation ascii_translation, utf8_translation;
+static struct charset_translation raw_translation = { 0 };
+static struct charset_translation tc_translation = {
+ CHARSET_FLAG_DECOMP_TITLECASE
+};
-struct charset_translation *charset_to_utf8_begin(const char *charset,
- bool *unknown_charset)
+int charset_to_utf8_begin(const char *charset, enum charset_flags flags,
+ struct charset_translation **t_r)
{
- if (unknown_charset != NULL)
- *unknown_charset = FALSE;
-
- if (strcasecmp(charset, "us-ascii") == 0 ||
- strcasecmp(charset, "ascii") == 0)
- return &ascii_translation;
-
- if (strcasecmp(charset, "UTF-8") == 0 ||
- strcasecmp(charset, "UTF8") == 0)
- return &utf8_translation;
+ if (charset_is_utf8(charset)) {
+ if ((flags & CHARSET_FLAG_DECOMP_TITLECASE) != 0)
+ *t_r = &tc_translation;
+ else
+ *t_r = &raw_translation;
+ return 0;
+ }
/* no support for charsets that need translation */
- if (unknown_charset != NULL)
- *unknown_charset = TRUE;
- return NULL;
+ return -1;
}
void charset_to_utf8_end(struct charset_translation **t __attr_unused__)
@@ -78,57 +50,16 @@ void charset_to_utf8_reset(struct charset_translation *t __attr_unused__)
}
enum charset_result
-charset_to_ucase_utf8(struct charset_translation *t __attr_unused__,
- const unsigned char *src, size_t *src_size,
- buffer_t *dest)
+charset_to_utf8(struct charset_translation *t,
+ const unsigned char *src, size_t *src_size, buffer_t *dest)
{
- size_t destpos, destleft;
-
- destpos = buffer_get_used_size(dest);
- destleft = buffer_get_size(dest) - destpos;
-
- /* no translation needed - just copy it to outbuf uppercased */
- if (*src_size > destleft)
- *src_size = destleft;
- _charset_utf8_ucase(src, *src_size, dest, destpos);
- return CHARSET_RET_OK;
-}
-
-const char *
-charset_to_utf8_string(const char *charset, bool *unknown_charset,
- const unsigned char *data, size_t size,
- size_t *utf8_size_r)
-{
- if (charset == NULL || strcasecmp(charset, "us-ascii") == 0 ||
- strcasecmp(charset, "ascii") == 0 ||
- strcasecmp(charset, "UTF-8") == 0 ||
- strcasecmp(charset, "UTF8") == 0) {
- if (unknown_charset != NULL)
- *unknown_charset = FALSE;
- if (utf8_size_r != NULL)
- *utf8_size_r = size;
- return t_strndup(data, size);
- } else {
- if (unknown_charset != NULL)
- *unknown_charset = TRUE;
- return NULL;
- }
-}
-
-const char *
-charset_to_ucase_utf8_string(const char *charset, bool *unknown_charset,
- const unsigned char *data, size_t size,
- size_t *utf8_size_r)
-{
- if (charset == NULL || charset_is_utf8(charset)) {
- if (unknown_charset != NULL)
- *unknown_charset = FALSE;
- return _charset_utf8_ucase_strdup(data, size, utf8_size_r);
- } else {
- if (unknown_charset != NULL)
- *unknown_charset = TRUE;
- return NULL;
+ if ((t->flags & CHARSET_FLAG_DECOMP_TITLECASE) == 0)
+ buffer_append(dest, src, *src_size);
+ else {
+ if (uni_utf8_to_decomposed_titlecase(src, *src_size, dest) < 0)
+ return CHARSET_RET_INVALID_INPUT;
}
+ return CHARSET_RET_OK;
}
#endif
diff --git a/src/lib-charset/charset-utf8.h b/src/lib-charset/charset-utf8.h
index 0476df9..c603edb 100644
--- a/src/lib-charset/charset-utf8.h
+++ b/src/lib-charset/charset-utf8.h
@@ -1,51 +1,32 @@
#ifndef __CHARSET_UTF8_H
#define __CHARSET_UTF8_H
+struct charset_translation;
+
+enum charset_flags {
+ /* Translate the output to decomposed titlecase */
+ CHARSET_FLAG_DECOMP_TITLECASE = 0x01
+};
+
enum charset_result {
CHARSET_RET_OK = 1,
- CHARSET_RET_OUTPUT_FULL = 0,
CHARSET_RET_INCOMPLETE_INPUT = -1,
CHARSET_RET_INVALID_INPUT = -2
};
-/* Begin translation to UTF-8. */
-struct charset_translation *charset_to_utf8_begin(const char *charset,
- bool *unknown_charset);
-
+/* Begin translation to UTF-8. Returns -1 if charset is unknown. */
+int charset_to_utf8_begin(const char *charset, enum charset_flags flags,
+ struct charset_translation **t_r);
void charset_to_utf8_end(struct charset_translation **t);
-
void charset_to_utf8_reset(struct charset_translation *t);
/* Returns TRUE if charset is UTF-8 or ASCII */
bool charset_is_utf8(const char *charset);
/* Translate src to UTF-8. src_size is updated to contain the number of
- characters actually translated from src. Note that dest buffer is used
- only up to its current size, for growing it automatically use
- charset_to_ucase_utf8_full(). */
-enum charset_result
-charset_to_ucase_utf8(struct charset_translation *t,
- const unsigned char *src, size_t *src_size,
- buffer_t *dest);
+ characters actually translated from src. */
enum charset_result
-charset_to_ucase_utf8_full(struct charset_translation *t,
- const unsigned char *src, size_t *src_size,
- buffer_t *dest);
-
-/* Simple wrappers for above functions. If utf8_size is non-NULL, it's set
- to same as strlen(returned data). */
-const char *
-charset_to_utf8_string(const char *charset, bool *unknown_charset,
- const unsigned char *data, size_t size,
- size_t *utf8_size_r);
-const char *
-charset_to_ucase_utf8_string(const char *charset, bool *unknown_charset,
- const unsigned char *data, size_t size,
- size_t *utf8_size_r);
-
-void _charset_utf8_ucase(const unsigned char *src, size_t src_size,
- buffer_t *dest, size_t destpos);
-const char *_charset_utf8_ucase_strdup(const unsigned char *data, size_t size,
- size_t *utf8_size_r);
+charset_to_utf8(struct charset_translation *t,
+ const unsigned char *src, size_t *src_size, buffer_t *dest);
#endif
diff --git a/src/lib-dict/dict-client.c b/src/lib-dict/dict-client.c
index 5064b6f..0fb8446 100644
--- a/src/lib-dict/dict-client.c
+++ b/src/lib-dict/dict-client.c
@@ -244,10 +244,8 @@ static int client_dict_connect(struct client_dict *dict)
/* Dictionary lookups are blocking */
net_set_nonblock(dict->fd, FALSE);
- dict->input = i_stream_create_file(dict->fd, default_pool,
- (size_t)-1, FALSE);
- dict->output = o_stream_create_file(dict->fd, default_pool,
- 4096, FALSE);
+ dict->input = i_stream_create_file(dict->fd, (size_t)-1, FALSE);
+ dict->output = o_stream_create_file(dict->fd, 4096, FALSE);
dict->transaction_id_counter = 0;
t_push();
diff --git a/src/lib-dict/dict-sql.c b/src/lib-dict/dict-sql.c
index 2386c13..c440026 100644
--- a/src/lib-dict/dict-sql.c
+++ b/src/lib-dict/dict-sql.c
@@ -48,7 +48,7 @@ static int sql_dict_read_config(struct sql_dict *dict, const char *path)
return -1;
}
- input = i_stream_create_file(fd, default_pool, (size_t)-1, FALSE);
+ input = i_stream_create_file(fd, (size_t)-1, FALSE);
while ((line = i_stream_read_next_line(input)) != NULL) {
while (*line == ' ') line++;
value = strchr(line, '=');
diff --git a/src/lib-imap/imap-base-subject.c b/src/lib-imap/imap-base-subject.c
index 1e41413..41806b2 100644
--- a/src/lib-imap/imap-base-subject.c
+++ b/src/lib-imap/imap-base-subject.c
@@ -9,39 +9,6 @@
#include "message-header-decode.h"
#include "imap-base-subject.h"
-static bool header_decode(const unsigned char *data, size_t size,
- const char *charset, void *context)
-{
- buffer_t *buf = context;
- struct charset_translation *t;
- unsigned char *buf_data;
- size_t pos, used_size;
-
- pos = buffer_get_used_size(buf);
- if (charset == NULL) {
- /* It's ASCII. */
- buffer_append(buf, data, size);
- } else {
- t = charset_to_utf8_begin(charset, NULL);
- if (t != NULL) {
- (void)charset_to_ucase_utf8(t, data, &size, buf);
- charset_to_utf8_end(&t);
- }
- }
-
- if (size > 0) {
- /* @UNSAFE: uppercase it. Current draft specifies that we
- should touch only ASCII. */
- buf_data = buffer_get_modifiable_data(buf, &used_size);
- for (; pos < used_size; pos++) {
- if (buf_data[pos] >= 'a' && buf_data[pos] <= 'z')
- buf_data[pos] = buf_data[pos] - 'a' + 'A';
- }
- }
-
- return TRUE;
-}
-
static void pack_whitespace(buffer_t *buf)
{
char *data, *dest;
@@ -246,8 +213,8 @@ const char *imap_get_base_subject_cased(pool_t pool, const char *subject,
/* (1) Convert any RFC 2047 encoded-words in the subject to
UTF-8. Convert all tabs and continuations to space.
Convert all multiple spaces to a single space. */
- message_header_decode((const unsigned char *)subject, subject_len,
- header_decode, buf);
+ message_header_decode_utf8((const unsigned char *)subject, subject_len,
+ buf, TRUE);
buffer_append_c(buf, '\0');
pack_whitespace(buf);
diff --git a/src/lib-imap/imap-bodystructure.c b/src/lib-imap/imap-bodystructure.c
index b346722..3eaed30 100644
--- a/src/lib-imap/imap-bodystructure.c
+++ b/src/lib-imap/imap-bodystructure.c
@@ -5,7 +5,6 @@
#include "istream.h"
#include "str.h"
#include "message-parser.h"
-#include "message-content-parser.h"
#include "rfc822-parser.h"
#include "imap-parser.h"
#include "imap-quote.h"
@@ -20,7 +19,6 @@
struct message_part_body_data {
pool_t pool;
- string_t *str; /* temporary */
const char *content_type, *content_subtype;
const char *content_type_params;
const char *content_transfer_encoding;
@@ -32,65 +30,111 @@ struct message_part_body_data {
const char *content_language;
struct message_part_envelope_data *envelope;
-
- unsigned int charset_found:1;
};
-static void parse_content_type(const unsigned char *value, size_t value_len,
- void *context)
+static void parse_content_type(struct message_part_body_data *data,
+ struct message_header_line *hdr)
{
- struct message_part_body_data *data = context;
- size_t i;
+ struct rfc822_parser_context parser;
+ const char *key, *value;
+ string_t *str;
+ unsigned int i;
+ bool charset_found = FALSE;
+
+ rfc822_parser_init(&parser, hdr->full_value, hdr->full_value_len, NULL);
+ (void)rfc822_skip_lwsp(&parser);
- for (i = 0; i < value_len; i++) {
- if (value[i] == '/')
+ str = t_str_new(256);
+ if (rfc822_parse_content_type(&parser, str) < 0)
+ return;
+
+ /* Save content type and subtype */
+ value = str_c(str);
+ for (i = 0; value[i] != '\0'; i++) {
+ if (value[i] == '/') {
+ data->content_subtype =
+ imap_quote(data->pool, str_data(str) + i + 1,
+ str_len(str) - (i + 1));
break;
+ }
}
+ data->content_type =
+ imap_quote(data->pool, str_data(str), i);
- if (i == value_len)
- data->content_type = imap_quote(data->pool, value, value_len);
- else {
- data->content_type = imap_quote(data->pool, value, i);
+ /* parse parameters and save them */
+ str_truncate(str, 0);
+ while (rfc822_parse_content_param(&parser, &key, &value) > 0) {
+ if (strcasecmp(key, "charset") == 0)
+ charset_found = TRUE;
- i++;
- data->content_subtype =
- imap_quote(data->pool, value+i, value_len-i);
+ str_append_c(str, ' ');
+ imap_quote_append_string(str, key, TRUE);
+ str_append_c(str, ' ');
+ imap_quote_append_string(str, value, TRUE);
+ }
+
+ if (!charset_found &&
+ strcasecmp(data->content_type, "\"text\"") == 0) {
+ /* set a default charset */
+ str_append_c(str, ' ');
+ str_append(str, DEFAULT_CHARSET);
+ }
+ if (str_len(str) > 0) {
+ data->content_type_params =
+ p_strdup(data->pool, str_c(str) + 1);
}
}
-static void parse_save_params_list(const unsigned char *name, size_t name_len,
- const unsigned char *value, size_t value_len,
- bool value_quoted __attr_unused__,
- void *context)
+static void parse_content_transfer_encoding(struct message_part_body_data *data,
+ struct message_header_line *hdr)
{
- struct message_part_body_data *data = context;
-
- if (str_len(data->str) != 0)
- str_append_c(data->str, ' ');
+ struct rfc822_parser_context parser;
+ string_t *str;
- if (name_len == 7 && memcasecmp(name, "charset", 7) == 0)
- data->charset_found = TRUE;
+ rfc822_parser_init(&parser, hdr->full_value, hdr->full_value_len, NULL);
+ (void)rfc822_skip_lwsp(&parser);
- imap_quote_append(data->str, name, name_len, TRUE);
- str_append_c(data->str, ' ');
- imap_quote_append(data->str, value, value_len, TRUE);
+ t_push();
+ str = t_str_new(256);
+ if (rfc822_parse_mime_token(&parser, str) >= 0) {
+ data->content_transfer_encoding =
+ imap_quote(data->pool, str_data(str), str_len(str));
+ }
+ t_pop();
}
-static void parse_content_transfer_encoding(const unsigned char *value,
- size_t value_len, void *context)
+static void parse_content_disposition(struct message_part_body_data *data,
+ struct message_header_line *hdr)
{
- struct message_part_body_data *data = context;
+ struct rfc822_parser_context parser;
+ const char *key, *value;
+ string_t *str;
- data->content_transfer_encoding =
- imap_quote(data->pool, value, value_len);
-}
+ rfc822_parser_init(&parser, hdr->full_value, hdr->full_value_len, NULL);
+ (void)rfc822_skip_lwsp(&parser);
-static void parse_content_disposition(const unsigned char *value,
- size_t value_len, void *context)
-{
- struct message_part_body_data *data = context;
+ t_push();
+ str = t_str_new(256);
+ if (rfc822_parse_mime_token(&parser, str) < 0) {
+ t_pop();
+ return;
+ }
+ data->content_disposition =
+ imap_quote(data->pool, str_data(str), str_len(str));
- data->content_disposition = imap_quote(data->pool, value, value_len);
+ /* parse parameters and save them */
+ str_truncate(str, 0);
+ while (rfc822_parse_content_param(&parser, &key, &value) > 0) {
+ str_append_c(str, ' ');
+ imap_quote_append_string(str, key, TRUE);
+ str_append_c(str, ' ');
+ imap_quote_append_string(str, value, TRUE);
+ }
+ if (str_len(str) > 0) {
+ data->content_disposition_params =
+ p_strdup(data->pool, str_c(str) + 1);
+ }
+ t_pop();
}
static void parse_content_language(const unsigned char *value, size_t value_len,
@@ -164,27 +208,13 @@ static void parse_content_header(struct message_part_body_data *d,
case 't':
case 'T':
if (strcasecmp(name, "Type") == 0 && d->content_type == NULL) {
- d->str = str_new(default_pool, 256);
- message_content_parse_header(value, value_len,
- parse_content_type,
- parse_save_params_list, d);
- if (!d->charset_found &&
- strncasecmp(d->content_type, "\"text\"", 6) == 0) {
- /* set a default charset */
- if (str_len(d->str) != 0)
- str_append_c(d->str, ' ');
- str_append(d->str, DEFAULT_CHARSET);
- }
- d->content_type_params =
- p_strdup_empty(pool, str_c(d->str));
- str_free(&d->str);
+ t_push();
+ parse_content_type(d, hdr);
+ t_pop();
}
if (strcasecmp(name, "Transfer-Encoding") == 0 &&
- d->content_transfer_encoding == NULL) {
- message_content_parse_header(value, value_len,
- parse_content_transfer_encoding,
- null_parse_content_param_callback, d);
- }
+ d->content_transfer_encoding == NULL)
+ parse_content_transfer_encoding(d, hdr);
break;
case 'l':
@@ -202,15 +232,8 @@ static void parse_content_header(struct message_part_body_data *d,
imap_quote(pool, value, value_len);
}
if (strcasecmp(name, "Disposition") == 0 &&
- d->content_disposition_params == NULL) {
- d->str = str_new(default_pool, 256);
- message_content_parse_header(value, value_len,
- parse_content_disposition,
- parse_save_params_list, d);
- d->content_disposition_params =
- p_strdup_empty(pool, str_c(d->str));
- str_free(&d->str);
- }
+ d->content_disposition_params == NULL)
+ parse_content_disposition(d, hdr);
break;
}
}
@@ -672,8 +695,7 @@ bool imap_body_parse_from_bodystructure(const char *bodystructure,
const struct imap_arg *args;
int ret;
- input = i_stream_create_from_data(pool_datastack_create(),
- bodystructure, strlen(bodystructure));
+ input = i_stream_create_from_data(bodystructure, strlen(bodystructure));
(void)i_stream_read(input);
parser = imap_parser_create(input, NULL, (size_t)-1);
diff --git a/src/lib-imap/imap-envelope.c b/src/lib-imap/imap-envelope.c
index f2c670b..892368d 100644
--- a/src/lib-imap/imap-envelope.c
+++ b/src/lib-imap/imap-envelope.c
@@ -380,8 +380,7 @@ bool imap_envelope_parse(const char *envelope, enum imap_envelope_field field,
i_assert(field < IMAP_ENVELOPE_FIELDS);
- input = i_stream_create_from_data(pool_datastack_create(), envelope,
- strlen(envelope));
+ input = i_stream_create_from_data(envelope, strlen(envelope));
parser = imap_parser_create(input, NULL, (size_t)-1);
(void)i_stream_read(input);
diff --git a/src/lib-index/mail-cache-compress.c b/src/lib-index/mail-cache-compress.c
index 7916142..fe15217 100644
--- a/src/lib-index/mail-cache-compress.c
+++ b/src/lib-index/mail-cache-compress.c
@@ -138,7 +138,7 @@ mail_cache_copy(struct mail_cache *cache, struct mail_index_transaction *trans,
}
cache_view = mail_cache_view_open(cache, view);
- output = o_stream_create_file(fd, default_pool, 0, FALSE);
+ output = o_stream_create_file(fd, 0, FALSE);
memset(&hdr, 0, sizeof(hdr));
hdr.version = MAIL_CACHE_VERSION;
diff --git a/src/lib-index/mailbox-list-index-sync.c b/src/lib-index/mailbox-list-index-sync.c
index e8a89f2..d586a42 100644
--- a/src/lib-index/mailbox-list-index-sync.c
+++ b/src/lib-index/mailbox-list-index-sync.c
@@ -850,8 +850,7 @@ mailbox_list_index_sync_write(struct mailbox_list_index_sync_ctx *ctx)
int ret = 0;
if (ctx->index->mmap_base == NULL) {
- ctx->output = o_stream_create_file(ctx->index->fd, default_pool,
- 0, FALSE);
+ ctx->output = o_stream_create_file(ctx->index->fd, 0, FALSE);
ctx->output_buf = buffer_create_dynamic(default_pool, 4096);
o_stream_seek(ctx->output, ctx->hdr.used_space);
}
diff --git a/src/lib-mail/Makefile.am b/src/lib-mail/Makefile.am
index 668dd5a..6cd4c87 100644
--- a/src/lib-mail/Makefile.am
+++ b/src/lib-mail/Makefile.am
@@ -7,7 +7,6 @@ AM_CPPFLAGS = \
libmail_a_SOURCES = \
istream-header-filter.c \
message-address.c \
- message-content-parser.c \
message-date.c \
message-decoder.c \
message-header-decode.c \
@@ -25,7 +24,6 @@ headers = \
istream-header-filter.h \
mail-types.h \
message-address.h \
- message-content-parser.h \
message-date.h \
message-decoder.h \
message-header-decode.h \
diff --git a/src/lib-mail/istream-header-filter.c b/src/lib-mail/istream-header-filter.c
index 402942b..9b14784 100644
--- a/src/lib-mail/istream-header-filter.c
+++ b/src/lib-mail/istream-header-filter.c
@@ -329,24 +329,22 @@ i_stream_create_header_filter(struct istream *input,
header_filter_callback *callback, void *context)
{
struct header_filter_istream *mstream;
- pool_t pool;
unsigned int i;
i_assert((flags & (HEADER_FILTER_INCLUDE|HEADER_FILTER_EXCLUDE)) != 0);
- pool = pool_alloconly_create("header filter stream", 4096);
- mstream = p_new(pool, struct header_filter_istream, 1);
- mstream->pool = pool;
+ mstream = i_new(struct header_filter_istream, 1);
+ mstream->pool = pool_alloconly_create("header filter stream", 4096);
mstream->input = input;
i_stream_ref(mstream->input);
mstream->headers = headers_count == 0 ? NULL :
- p_new(pool, const char *, headers_count);
+ p_new(mstream->pool, const char *, headers_count);
for (i = 0; i < headers_count; i++)
- mstream->headers[i] = p_strdup(pool, headers[i]);
+ mstream->headers[i] = p_strdup(mstream->pool, headers[i]);
mstream->headers_count = headers_count;
- mstream->hdr_buf = buffer_create_dynamic(pool, 1024);
+ mstream->hdr_buf = buffer_create_dynamic(mstream->pool, 1024);
mstream->callback = callback;
mstream->context = context;
@@ -366,5 +364,5 @@ i_stream_create_header_filter(struct istream *input,
mstream->istream.istream.blocking = input->blocking;
mstream->istream.istream.seekable = input->seekable;
- return _i_stream_create(&mstream->istream, pool, -1, 0);
+ return _i_stream_create(&mstream->istream, -1, 0);
}
diff --git a/src/lib-mail/message-content-parser.c b/src/lib-mail/message-content-parser.c
deleted file mode 100644
index 38cb876..0000000
--- a/src/lib-mail/message-content-parser.c
+++ /dev/null
@@ -1,78 +0,0 @@
-/* Copyright (C) 2002-2005 Timo Sirainen */
-
-#include "lib.h"
-#include "str.h"
-#include "rfc822-parser.h"
-#include "message-content-parser.h"
-
-parse_content_callback_t *null_parse_content_callback = NULL;
-parse_content_param_callback_t *null_parse_content_param_callback = NULL;
-
-void message_content_parse_header(const unsigned char *data, size_t size,
- parse_content_callback_t *callback,
- parse_content_param_callback_t *param_cb,
- void *context)
-{
- struct rfc822_parser_context parser;
- string_t *str;
- size_t key_len;
- bool quoted_string;
-
- rfc822_parser_init(&parser, data, size, NULL);
-
- t_push();
- str = t_str_new(256);
-
- /* get content type */
- (void)rfc822_skip_lwsp(&parser);
- if (rfc822_parse_mime_token(&parser, str) > 0) {
- if (*parser.data == '/') {
- parser.data++;
- str_append_c(str, '/');
- (void)rfc822_parse_mime_token(&parser, str);
- }
- }
-
- if (callback != NULL)
- callback(str_data(str), str_len(str), context);
-
- if (param_cb == NULL) {
- /* we don't care about parameters */
- t_pop();
- return;
- }
-
- while (parser.data != parser.end && *parser.data == ';') {
- parser.data++;
- (void)rfc822_skip_lwsp(&parser);
-
- str_truncate(str, 0);
- if (rfc822_parse_mime_token(&parser, str) <= 0)
- break;
-
- /* <token> "=" <token> | <quoted-string> */
- if (str_len(str) == 0 || *parser.data != '=')
- break;
- parser.data++;
- if (rfc822_skip_lwsp(&parser) <= 0)
- break;
-
- quoted_string = parser.data != parser.end &&
- *parser.data == '"';
- key_len = str_len(str);
- if (quoted_string) {
- if (rfc822_parse_quoted_string(&parser, str) < 0)
- break;
- } else {
- if (rfc822_parse_mime_token(&parser, str) < 0)
- break;
- }
-
- param_cb(str_data(str), key_len,
- str_data(str) + key_len, str_len(str) - key_len,
- quoted_string, context);
-
- str_truncate(str, 0);
- }
- t_pop();
-}
diff --git a/src/lib-mail/message-content-parser.h b/src/lib-mail/message-content-parser.h
deleted file mode 100644
index 018bf1e..0000000
--- a/src/lib-mail/message-content-parser.h
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef __MESSAGE_CONTENT_PARSER_H
-#define __MESSAGE_CONTENT_PARSER_H
-
-/* NOTE: name and value aren't \0-terminated. */
-typedef void parse_content_callback_t(const unsigned char *value,
- size_t value_len, void *context);
-typedef void parse_content_param_callback_t(const unsigned char *name,
- size_t name_len,
- const unsigned char *value,
- size_t value_len,
- bool value_quoted, void *context);
-
-extern parse_content_callback_t *null_parse_content_callback;
-extern parse_content_param_callback_t *null_parse_content_param_callback;
-
-void message_content_parse_header(const unsigned char *data, size_t size,
- parse_content_callback_t *callback,
- parse_content_param_callback_t *param_cb,
- void *context);
-
-#endif
diff --git a/src/lib-mail/message-decoder.c b/src/lib-mail/message-decoder.c
index dbfae9c..5b23bb5 100644
--- a/src/lib-mail/message-decoder.c
+++ b/src/lib-mail/message-decoder.c
@@ -2,12 +2,13 @@
#include "lib.h"
#include "buffer.h"
-#include "strescape.h"
#include "base64.h"
+#include "str.h"
+#include "unichar.h"
#include "charset-utf8.h"
#include "quoted-printable.h"
+#include "rfc822-parser.h"
#include "message-parser.h"
-#include "message-content-parser.h"
#include "message-header-decode.h"
#include "message-decoder.h"
@@ -41,14 +42,16 @@ struct message_decoder_context {
char *content_charset;
enum content_type content_type;
+ unsigned int dtcase:1;
unsigned int charset_utf8:1;
};
-struct message_decoder_context *message_decoder_init_ucase(void)
+struct message_decoder_context *message_decoder_init(bool dtcase)
{
struct message_decoder_context *ctx;
ctx = i_new(struct message_decoder_context, 1);
+ ctx->dtcase = dtcase;
ctx->buf = buffer_create_dynamic(default_pool, 8192);
ctx->buf2 = buffer_create_dynamic(default_pool, 8192);
return ctx;
@@ -69,72 +72,68 @@ void message_decoder_deinit(struct message_decoder_context **_ctx)
i_free(ctx);
}
-static bool
-message_decode_header_callback(const unsigned char *data, size_t size,
- const char *charset, void *context)
+static void
+parse_content_transfer_encoding(struct message_decoder_context *ctx,
+ struct message_header_line *hdr)
{
- struct message_decoder_context *ctx = context;
- struct charset_translation *t;
- bool unknown_charset;
-
- if (charset == NULL || charset_is_utf8(charset)) {
- /* ASCII / UTF-8 */
- _charset_utf8_ucase(data, size, ctx->buf, ctx->buf->used);
- return TRUE;
- }
-
- t = charset_to_utf8_begin(charset, &unknown_charset);
- if (unknown_charset) {
- /* let's just ignore this part */
- return TRUE;
- }
-
- /* ignore any errors */
- (void)charset_to_ucase_utf8_full(t, data, &size, ctx->buf);
- charset_to_utf8_end(&t);
- return TRUE;
-}
+ struct rfc822_parser_context parser;
+ string_t *value;
-static void parse_content_encoding(const unsigned char *value, size_t value_len,
- void *context)
-{
- struct message_decoder_context *ctx = context;
+ t_push();
+ value = t_str_new(64);
+ rfc822_parser_init(&parser, hdr->full_value, hdr->full_value_len, NULL);
- ctx->content_type = CONTENT_TYPE_UNKNOWN;
+ (void)rfc822_skip_lwsp(&parser);
+ (void)rfc822_parse_mime_token(&parser, value);
- switch (value_len) {
+ switch (str_len(value)) {
case 4:
- if (memcasecmp(value, "7bit", 4) == 0 ||
- memcasecmp(value, "8bit", 4) == 0)
+ if (memcasecmp(str_data(value), "7bit", 4) == 0 ||
+ memcasecmp(str_data(value), "8bit", 4) == 0)
ctx->content_type = CONTENT_TYPE_BINARY;
break;
case 6:
- if (memcasecmp(value, "base64", 6) == 0)
+ if (memcasecmp(str_data(value), "base64", 6) == 0)
ctx->content_type = CONTENT_TYPE_BASE64;
- else if (memcasecmp(value, "binary", 6) == 0)
+ else if (memcasecmp(str_data(value), "binary", 6) == 0)
ctx->content_type = CONTENT_TYPE_BINARY;
break;
case 16:
- if (memcasecmp(value, "quoted-printable", 16) == 0)
+ if (memcasecmp(str_data(value), "quoted-printable", 16) == 0)
ctx->content_type = CONTENT_TYPE_QP;
break;
}
+ t_pop();
}
static void
-parse_content_type_param(const unsigned char *name, size_t name_len,
- const unsigned char *value, size_t value_len,
- bool value_quoted, void *context)
+parse_content_type(struct message_decoder_context *ctx,
+ struct message_header_line *hdr)
{
- struct message_decoder_context *ctx = context;
-
- if (name_len == 7 && memcasecmp(name, "charset", 7) == 0 &&
- ctx->content_charset == NULL) {
- ctx->content_charset = i_strndup(value, value_len);
- if (value_quoted) str_unescape(ctx->content_charset);
+ struct rfc822_parser_context parser;
+ const char *key, *value;
+ string_t *str;
+
+ if (ctx->content_charset != NULL)
+ return;
+
+ rfc822_parser_init(&parser, hdr->full_value, hdr->full_value_len, NULL);
+ (void)rfc822_skip_lwsp(&parser);
+ t_push();
+ str = t_str_new(64);
+ if (rfc822_parse_content_type(&parser, str) <= 0) {
+ t_pop();
+ return;
+ }
- ctx->charset_utf8 = charset_is_utf8(ctx->content_charset);
+ while (rfc822_parse_content_param(&parser, &key, &value) > 0) {
+ if (strcasecmp(key, "charset") == 0) {
+ ctx->content_charset = i_strdup(value);
+ ctx->charset_utf8 = charset_is_utf8(value);
+ break;
+ }
}
+ t_pop();
}
static bool message_decode_header(struct message_decoder_context *ctx,
@@ -149,37 +148,32 @@ static bool message_decode_header(struct message_decoder_context *ctx,
}
if (hdr->name_len == 12 &&
- strcasecmp(hdr->name, "Content-Type") == 0) {
- message_content_parse_header(hdr->full_value,
- hdr->full_value_len,
- null_parse_content_callback,
- parse_content_type_param, ctx);
- }
+ strcasecmp(hdr->name, "Content-Type") == 0)
+ parse_content_type(ctx, hdr);
if (hdr->name_len == 25 &&
- strcasecmp(hdr->name, "Content-Transfer-Encoding") == 0) {
- message_content_parse_header(hdr->full_value,
- hdr->full_value_len,
- parse_content_encoding,
- null_parse_content_param_callback,
- ctx);
- }
+ strcasecmp(hdr->name, "Content-Transfer-Encoding") == 0)
+ parse_content_transfer_encoding(ctx, hdr);
buffer_set_used_size(ctx->buf, 0);
- message_header_decode(hdr->full_value, hdr->full_value_len,
- message_decode_header_callback, ctx);
+ message_header_decode_utf8(hdr->full_value, hdr->full_value_len,
+ ctx->buf, ctx->dtcase);
value_len = ctx->buf->used;
- _charset_utf8_ucase((const unsigned char *)hdr->name, hdr->name_len,
- ctx->buf, ctx->buf->used);
- buffer_append_c(ctx->buf, '\0');
+ if (ctx->dtcase) {
+ (void)uni_utf8_to_decomposed_titlecase(hdr->name, hdr->name_len,
+ ctx->buf);
+ buffer_append_c(ctx->buf, '\0');
+ }
ctx->hdr = *hdr;
ctx->hdr.full_value = ctx->buf->data;
ctx->hdr.full_value_len = value_len;
ctx->hdr.value_len = 0;
- ctx->hdr.name = CONST_PTR_OFFSET(ctx->buf->data,
- ctx->hdr.full_value_len);
- ctx->hdr.name_len = ctx->buf->used - 1 - value_len;
+ if (ctx->dtcase) {
+ ctx->hdr.name = CONST_PTR_OFFSET(ctx->buf->data,
+ ctx->hdr.full_value_len);
+ ctx->hdr.name_len = ctx->buf->used - 1 - value_len;
+ }
output->hdr = &ctx->hdr;
return TRUE;
@@ -199,8 +193,7 @@ static void translation_buf_decode(struct message_decoder_context *ctx,
memcpy(trans_buf + ctx->translation_size, data, skip);
pos = *size;
- (void)charset_to_ucase_utf8_full(ctx->charset_trans,
- *data, &pos, ctx->buf2);
+ (void)charset_to_utf8(ctx->charset_trans, *data, &pos, ctx->buf2);
i_assert(pos > ctx->translation_size);
skip = (ctx->translation_size + skip) - pos;
@@ -219,14 +212,13 @@ static bool message_decode_body(struct message_decoder_context *ctx,
unsigned char new_buf[MAX_ENCODING_BUF_SIZE+1];
const unsigned char *data = NULL;
size_t pos, size = 0, skip = 0;
- bool unknown_charset;
int ret;
if (ctx->charset_trans == NULL && !ctx->charset_utf8) {
- ctx->charset_trans =
- charset_to_utf8_begin(ctx->content_charset != NULL ?
- ctx->content_charset : "UTF-8",
- &unknown_charset);
+ if (charset_to_utf8_begin(ctx->content_charset != NULL ?
+ ctx->content_charset : "UTF-8",
+ ctx->dtcase, &ctx->charset_trans) < 0)
+ ctx->charset_trans = NULL;
}
if (ctx->encoding_size != 0) {
@@ -304,10 +296,16 @@ static bool message_decode_body(struct message_decoder_context *ctx,
}
if (ctx->charset_utf8) {
- buffer_set_used_size(ctx->buf2, 0);
- _charset_utf8_ucase(data, size, ctx->buf2, ctx->buf2->used);
- output->data = ctx->buf2->data;
- output->size = ctx->buf2->used;
+ if (ctx->dtcase) {
+ buffer_set_used_size(ctx->buf2, 0);
+ (void)uni_utf8_to_decomposed_titlecase(data, size,
+ ctx->buf);
+ output->data = ctx->buf2->data;
+ output->size = ctx->buf2->used;
+ } else {
+ output->data = data;
+ output->size = size;
+ }
} else if (ctx->charset_trans == NULL) {
output->data = data;
output->size = size;
@@ -317,8 +315,8 @@ static bool message_decode_body(struct message_decoder_context *ctx,
translation_buf_decode(ctx, &data, &size);
pos = size;
- (void)charset_to_ucase_utf8_full(ctx->charset_trans,
- data, &pos, ctx->buf2);
+ (void)charset_to_utf8(ctx->charset_trans,
+ data, &pos, ctx->buf2);
if (pos != size) {
ctx->translation_size = size - pos;
i_assert(ctx->translation_size <=
diff --git a/src/lib-mail/message-decoder.h b/src/lib-mail/message-decoder.h
index 7fb6371..043cf3e 100644
--- a/src/lib-mail/message-decoder.h
+++ b/src/lib-mail/message-decoder.h
@@ -5,8 +5,9 @@ struct message_block;
/* Decode message's contents as UTF-8, both the headers and the MIME bodies.
The bodies are decoded from quoted-printable and base64 formats if needed.
- The data is returned uppercased. */
-struct message_decoder_context *message_decoder_init_ucase(void);
+ If dtcase=TRUE, the data is returned through
+ uni_utf8_to_decomposed_titlecase(). */
+struct message_decoder_context *message_decoder_init(bool dtcase);
void message_decoder_deinit(struct message_decoder_context **ctx);
/* Decode input and return decoded output. Headers are returned only in their
diff --git a/src/lib-mail/message-header-decode.c b/src/lib-mail/message-header-decode.c
index 19f5e2e..b8fb50a 100644
--- a/src/lib-mail/message-header-decode.c
+++ b/src/lib-mail/message-header-decode.c
@@ -3,6 +3,8 @@
#include "lib.h"
#include "base64.h"
#include "buffer.h"
+#include "unichar.h"
+#include "charset-utf8.h"
#include "quoted-printable.h"
#include "message-header-decode.h"
@@ -113,3 +115,58 @@ void message_header_decode(const unsigned char *data, size_t size,
}
t_pop();
}
+
+struct decode_utf8_context {
+ buffer_t *dest;
+ unsigned int changed:1;
+ unsigned int called:1;
+ unsigned int dtcase:1;
+};
+
+static bool
+decode_utf8_callback(const unsigned char *data, size_t size,
+ const char *charset, void *context)
+{
+ struct decode_utf8_context *ctx = context;
+ struct charset_translation *t;
+
+ /* one call with charset=NULL means nothing changed */
+ if (!ctx->called && charset == NULL)
+ ctx->called = TRUE;
+ else
+ ctx->changed = TRUE;
+
+ if (charset == NULL || charset_is_utf8(charset)) {
+ /* ASCII / UTF-8 */
+ if (ctx->dtcase) {
+ (void)uni_utf8_to_decomposed_titlecase(data, size,
+ ctx->dest);
+ } else {
+ buffer_append(ctx->dest, data, size);
+ }
+ return TRUE;
+ }
+
+ if (charset_to_utf8_begin(charset, ctx->dtcase, &t) < 0) {
+ /* let's just ignore this part */
+ return TRUE;
+ }
+
+ /* ignore any errors */
+ (void)charset_to_utf8(t, data, &size, ctx->dest);
+ charset_to_utf8_end(&t);
+ return TRUE;
+}
+
+bool message_header_decode_utf8(const unsigned char *data, size_t size,
+ buffer_t *dest, bool dtcase)
+{
+ struct decode_utf8_context ctx;
+ size_t used = dest->used;
+
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.dest = dest;
+ ctx.dtcase = dtcase;
+ message_header_decode(data, size, decode_utf8_callback, &ctx);
+ return ctx.changed || (dest->used - used != size);
+}
diff --git a/src/lib-mail/message-header-decode.h b/src/lib-mail/message-header-decode.h
index 6a1e9f2..b765523 100644
--- a/src/lib-mail/message-header-decode.h
+++ b/src/lib-mail/message-header-decode.h
@@ -13,4 +13,10 @@ void message_header_decode(const unsigned char *data, size_t size,
message_header_decode_callback_t *callback,
void *context);
+/* Append decoded RFC2047 header as UTF-8 to given buffer. If dtcase=TRUE,
+ the header is appended through uni_utf8_to_decomposed_titlecase().
+ Returns TRUE if output changed in any way from input. */
+bool message_header_decode_utf8(const unsigned char *data, size_t size,
+ buffer_t *dest, bool dtcase);
+
#endif
diff --git a/src/lib-mail/message-parser.c b/src/lib-mail/message-parser.c
index 4443773..670be66 100644
--- a/src/lib-mail/message-parser.c
+++ b/src/lib-mail/message-parser.c
@@ -1,9 +1,9 @@
/* Copyright (C) 2002-2006 Timo Sirainen */
#include "lib.h"
+#include "str.h"
#include "istream.h"
-#include "strescape.h"
-#include "message-content-parser.h"
+#include "rfc822-parser.h"
#include "message-parser.h"
/* RFC-2046 requires boundaries are max. 70 chars + "--" prefix + "--" suffix.
@@ -388,49 +388,46 @@ static int parse_next_body_to_eof(struct message_parser_ctx *ctx,
return 1;
}
-static void
-parse_content_type(const unsigned char *value, size_t value_len, void *context)
+static void parse_content_type(struct message_parser_ctx *ctx,
+ struct message_header_line *hdr)
{
- struct message_parser_ctx *ctx = context;
- const char *str;
+ struct rfc822_parser_context parser;
+ const char *key, *value;
+ string_t *content_type;
- if (ctx->part_seen_content_type || value_len == 0)
+ if (ctx->part_seen_content_type)
return;
ctx->part_seen_content_type = TRUE;
- t_push();
- str = t_strndup(value, value_len);
- if (strcasecmp(str, "message/rfc822") == 0)
+ rfc822_parser_init(&parser, hdr->full_value, hdr->full_value_len, NULL);
+ (void)rfc822_skip_lwsp(&parser);
+
+ content_type = t_str_new(64);
+ if (rfc822_parse_content_type(&parser, content_type) < 0)
+ return;
+
+ if (strcasecmp(str_c(content_type), "message/rfc822") == 0)
ctx->part->flags |= MESSAGE_PART_FLAG_MESSAGE_RFC822;
- else if (strncasecmp(str, "text", 4) == 0 &&
- (str[4] == '/' || str[4] == '\0'))
+ else if (strncasecmp(str_c(content_type), "text", 4) == 0 &&
+ (str_len(content_type) == 4 ||
+ str_data(content_type)[4] == '/'))
ctx->part->flags |= MESSAGE_PART_FLAG_TEXT;
- else if (strncasecmp(str, "multipart/", 10) == 0) {
+ else if (strncasecmp(str_c(content_type), "multipart/", 10) == 0) {
ctx->part->flags |= MESSAGE_PART_FLAG_MULTIPART;
- if (strcasecmp(str+10, "digest") == 0)
+ if (strcasecmp(str_c(content_type)+10, "digest") == 0)
ctx->part->flags |= MESSAGE_PART_FLAG_MULTIPART_DIGEST;
}
- t_pop();
-}
-
-static void
-parse_content_type_param(const unsigned char *name, size_t name_len,
- const unsigned char *value, size_t value_len,
- bool value_quoted, void *context)
-{
- struct message_parser_ctx *ctx = context;
- char *boundary;
if ((ctx->part->flags & MESSAGE_PART_FLAG_MULTIPART) == 0 ||
- name_len != 8 || memcasecmp(name, "boundary", 8) != 0)
+ ctx->last_boundary != NULL)
return;
- if (ctx->last_boundary == NULL) {
- boundary = p_strndup(ctx->parser_pool, value, value_len);
- if (value_quoted)
- str_unescape(boundary);
- ctx->last_boundary = boundary;
+ while (rfc822_parse_content_param(&parser, &key, &value) > 0) {
+ if (strcasecmp(key, "boundary") == 0) {
+ ctx->last_boundary = p_strdup(ctx->parser_pool, value);
+ break;
+ }
}
}
@@ -463,10 +460,9 @@ static int parse_next_header(struct message_parser_ctx *ctx,
if (hdr->continues)
hdr->use_full_value = TRUE;
else {
- message_content_parse_header(hdr->full_value,
- hdr->full_value_len,
- parse_content_type,
- parse_content_type_param, ctx);
+ t_push();
+ parse_content_type(ctx, hdr);
+ t_pop();
}
}
diff --git a/src/lib-mail/message-search.c b/src/lib-mail/message-search.c
index db3b4da..c8be4f2 100644
--- a/src/lib-mail/message-search.c
+++ b/src/lib-mail/message-search.c
@@ -3,11 +3,12 @@
#include "lib.h"
#include "buffer.h"
#include "istream.h"
+#include "str.h"
#include "str-find.h"
#include "charset-utf8.h"
+#include "rfc822-parser.h"
#include "message-decoder.h"
#include "message-parser.h"
-#include "message-content-parser.h"
#include "message-search.h"
struct message_search_context {
@@ -25,45 +26,34 @@ struct message_search_context {
unsigned int content_type_text:1; /* text/any or message/any */
};
-static void parse_content_type(const unsigned char *value, size_t value_len,
- void *context)
-{
- struct message_search_context *ctx = context;
- const char *str;
-
- t_push();
- str = t_strndup(value, value_len);
- ctx->content_type_text =
- strncasecmp(str, "text/", 5) == 0 ||
- strncasecmp(str, "message/", 8) == 0;
- t_pop();
-}
-
int message_search_init(pool_t pool, const char *key, const char *charset,
enum message_search_flags flags,
struct message_search_context **ctx_r)
{
struct message_search_context *ctx;
- bool unknown_charset;
+ struct charset_translation *t;
+ string_t *key_utf8;
size_t key_len;
- /* get the key uppercased */
+ if (charset_to_utf8_begin(charset, TRUE, &t) < 0)
+ return 0;
+
t_push();
- key = charset_to_ucase_utf8_string(charset, &unknown_charset,
- (const unsigned char *)key,
- strlen(key), &key_len);
- if (key == NULL) {
+ key_utf8 = t_str_new(I_MAX(128, key_len*2));
+ key_len = strlen(key);
+ if (charset_to_utf8(t, (const unsigned char *)key, &key_len,
+ key_utf8) != CHARSET_RET_OK) {
t_pop();
- return unknown_charset ? 0 : -1;
+ return -1;
}
ctx = *ctx_r = p_new(pool, struct message_search_context, 1);
ctx->pool = pool;
- ctx->key = p_strdup(pool, key);
- ctx->key_len = key_len;
+ ctx->key = p_strdup(pool, str_c(key_utf8));
+ ctx->key_len = str_len(key_utf8);
ctx->key_charset = p_strdup(pool, charset);
ctx->flags = flags;
- ctx->decoder = message_decoder_init_ucase();
+ ctx->decoder = message_decoder_init(TRUE);
ctx->str_find_ctx = str_find_init(pool, ctx->key);
t_pop();
return 1;
@@ -81,6 +71,25 @@ void message_search_deinit(struct message_search_context **_ctx)
p_free(ctx->pool, ctx);
}
+static void parse_content_type(struct message_search_context *ctx,
+ struct message_header_line *hdr)
+{
+ struct rfc822_parser_context parser;
+ string_t *content_type;
+
+ t_push();
+ rfc822_parser_init(&parser, hdr->full_value, hdr->full_value_len, NULL);
+ (void)rfc822_skip_lwsp(&parser);
+
+ content_type = t_str_new(64);
+ if (rfc822_parse_content_type(&parser, content_type) >= 0) {
+ ctx->content_type_text =
+ strncasecmp(str_c(content_type), "text/", 5) == 0 ||
+ strncasecmp(str_c(content_type), "message/", 8) == 0;
+ }
+ t_pop();
+}
+
static void handle_header(struct message_search_context *ctx,
struct message_header_line *hdr)
{
@@ -90,9 +99,7 @@ static void handle_header(struct message_search_context *ctx,
hdr->use_full_value = TRUE;
return;
}
- message_content_parse_header(hdr->full_value,
- hdr->full_value_len,
- parse_content_type, NULL, ctx);
+ parse_content_type(ctx, hdr);
}
}
diff --git a/src/lib-mail/rfc822-parser.c b/src/lib-mail/rfc822-parser.c
index 2d2d4d6..94f075f 100644
--- a/src/lib-mail/rfc822-parser.c
+++ b/src/lib-mail/rfc822-parser.c
@@ -2,6 +2,7 @@
#include "lib.h"
#include "str.h"
+#include "strescape.h"
#include "rfc822-parser.h"
/*
@@ -308,7 +309,7 @@ rfc822_parse_domain_literal(struct rfc822_parser_context *ctx, string_t *str)
} else if (*ctx->data == ']') {
ctx->data++;
str_append_n(str, start, ctx->data - start);
- return ctx->data != ctx->end;
+ return rfc822_skip_lwsp(ctx);
}
}
@@ -329,13 +330,77 @@ int rfc822_parse_domain(struct rfc822_parser_context *ctx, string_t *str)
if (rfc822_skip_lwsp(ctx) <= 0)
return -1;
- if (*ctx->data == '[') {
- if (rfc822_parse_domain_literal(ctx, str) < 0)
- return -1;
+ if (*ctx->data == '[')
+ return rfc822_parse_domain_literal(ctx, str);
+ else
+ return rfc822_parse_dot_atom(ctx, str);
+}
+
+int rfc822_parse_content_type(struct rfc822_parser_context *ctx, string_t *str)
+{
+ if (rfc822_skip_lwsp(ctx) <= 0)
+ return -1;
+
+ /* get main type */
+ if (rfc822_parse_mime_token(ctx, str) <= 0)
+ return -1;
+
+ /* skip over "/" */
+ if (*ctx->data != '/')
+ return -1;
+ ctx->data++;
+ if (rfc822_skip_lwsp(ctx) <= 0)
+ return -1;
+ str_append_c(str, '/');
+
+ /* get subtype */
+ return rfc822_parse_mime_token(ctx, str);
+}
+
+int rfc822_parse_content_param(struct rfc822_parser_context *ctx,
+ const char **key_r, const char **value_r)
+{
+ string_t *tmp;
+ size_t value_pos;
+ int ret;
+
+ /* .. := *(";" parameter)
+ parameter := attribute "=" value
+ attribute := token
+ value := token / quoted-string
+ */
+ *key_r = NULL;
+ *value_r = NULL;
+
+ if (ctx->data == ctx->end)
+ return 0;
+ if (*ctx->data != ';')
+ return -1;
+ ctx->data++;
+
+ if (rfc822_skip_lwsp(ctx) <= 0)
+ return -1;
+
+ tmp = t_str_new(64);
+ if (rfc822_parse_mime_token(ctx, tmp) <= 0)
+ return -1;
+ str_append_c(tmp, '\0');
+ value_pos = str_len(tmp);
+
+ if (*ctx->data != '=')
+ return -1;
+ ctx->data++;
+
+ if ((ret = rfc822_skip_lwsp(ctx)) <= 0) {
+ /* broken / no value */
+ } else if (*ctx->data == '"') {
+ ret = rfc822_parse_quoted_string(ctx, tmp);
+ str_unescape(str_c_modifiable(tmp) + value_pos);
} else {
- if (rfc822_parse_dot_atom(ctx, str) < 0)
- return -1;
+ ret = rfc822_parse_mime_token(ctx, tmp);
}
- return ctx->data != ctx->end;
+ *key_r = str_c(tmp);
+ *value_r = *key_r + value_pos;
+ return ret < 0 ? -1 : 1;
}
diff --git a/src/lib-mail/rfc822-parser.h b/src/lib-mail/rfc822-parser.h
index ba5b148..0ec54f4 100644
--- a/src/lib-mail/rfc822-parser.h
+++ b/src/lib-mail/rfc822-parser.h
@@ -6,10 +6,17 @@ struct rfc822_parser_context {
string_t *last_comment;
};
+/* Parse given data using RFC 822 token parser. */
void rfc822_parser_init(struct rfc822_parser_context *ctx,
const unsigned char *data, size_t size,
string_t *last_comment);
+/* The functions below return 1 = more data available, 0 = no more data
+ available (but a value might have been returned now), -1 = invalid input.
+
+ LWSP is automatically skipped after value, but not before it. So typically
+ you begin with skipping LWSP and then start using the parse functions. */
+
/* Parse comment. Assumes parser's data points to '(' */
int rfc822_skip_comment(struct rfc822_parser_context *ctx);
/* Skip LWSP if there is any */
@@ -29,4 +36,12 @@ int rfc822_parse_phrase(struct rfc822_parser_context *ctx, string_t *str);
/* dot-atom / domain-literal */
int rfc822_parse_domain(struct rfc822_parser_context *ctx, string_t *str);
+/* Parse Content-Type header's type/subtype. */
+int rfc822_parse_content_type(struct rfc822_parser_context *ctx, string_t *str);
+/* For Content-Type style parameter parsing. Expect ";" key "=" value.
+ value is unescaped if needed. The returned strings are allocated from data
+ stack. Returns 1 = key/value set, 0 = no more data, -1 = invalid input. */
+int rfc822_parse_content_param(struct rfc822_parser_context *ctx,
+ const char **key_r, const char **value_r);
+
#endif
diff --git a/src/lib-settings/settings.c b/src/lib-settings/settings.c
index 9608c47..c9d45cb 100644
--- a/src/lib-settings/settings.c
+++ b/src/lib-settings/settings.c
@@ -1,6 +1,7 @@
-/* Copyright (C) 2002 Timo Sirainen */
+/* Copyright (C) 2002-2007 Timo Sirainen */
#include "lib.h"
+#include "str.h"
#include "istream.h"
#include "strescape.h"
#include "settings.h"
@@ -71,6 +72,7 @@ bool settings_read(const char *path, const char *section,
struct istream *input;
const char *errormsg, *next_section, *name;
char *line, *key, *p, quote;
+ string_t *full_line;
size_t len;
int fd, linenum, last_section_line = 0, skip, sections, root_section;
@@ -90,8 +92,9 @@ bool settings_read(const char *path, const char *section,
next_section = t_strcut(section, '/');
}
+ full_line = t_str_new(512);
linenum = 0; sections = 0; root_section = 0; errormsg = NULL;
- input = i_stream_create_file(fd, default_pool, 2048, TRUE);
+ input = i_stream_create_file(fd, 2048, TRUE);
for (;;) {
line = i_stream_read_next_line(input);
if (line == NULL) {
@@ -140,6 +143,17 @@ bool settings_read(const char *path, const char *section,
len--;
line[len] = '\0';
+ if (len > 0 && line[len-1] == '\\') {
+ /* continues in next line */
+ line[len-1] = '\0';
+ str_append(full_line, line);
+ continue;
+ }
+ if (str_len(full_line) > 0) {
+ str_append(full_line, line);
+ line = str_c_modifiable(full_line);
+ }
+
/* a) key = value
b) section_type [section_name] {
c) } */
@@ -246,6 +260,7 @@ bool settings_read(const char *path, const char *section,
path, linenum, errormsg);
break;
}
+ str_truncate(full_line, 0);
}
i_stream_destroy(&input);
diff --git a/src/lib-storage/index/cydir/cydir-mail.c b/src/lib-storage/index/cydir/cydir-mail.c
index db2eee7..d995615 100644
--- a/src/lib-storage/index/cydir/cydir-mail.c
+++ b/src/lib-storage/index/cydir/cydir-mail.c
@@ -84,7 +84,7 @@ static uoff_t cydir_mail_get_physical_size(struct mail *_mail)
return data->physical_size;
if (cydir_mail_stat(_mail, &st) < 0)
- return (time_t)-1;
+ return (uoff_t)-1;
data->physical_size = data->virtual_size = st.st_size;
index_mail_cache_add(mail, MAIL_CACHE_PHYSICAL_FULL_SIZE,
@@ -113,8 +113,7 @@ cydir_mail_get_stream(struct mail *_mail, struct message_size *hdr_size,
return NULL;
}
mail->data.stream =
- i_stream_create_file(fd, default_pool,
- MAIL_READ_BLOCK_SIZE, TRUE);
+ i_stream_create_file(fd, MAIL_READ_BLOCK_SIZE, TRUE);
}
return index_mail_init_stream(mail, hdr_size, body_size);
diff --git a/src/lib-storage/index/cydir/cydir-save.c b/src/lib-storage/index/cydir/cydir-save.c
index 53f9f7c..07b4321 100644
--- a/src/lib-storage/index/cydir/cydir-save.c
+++ b/src/lib-storage/index/cydir/cydir-save.c
@@ -85,8 +85,8 @@ int cydir_save_init(struct mailbox_transaction_context *_t,
path = cydir_get_save_path(ctx, ctx->mail_count);
ctx->fd = open(path, O_WRONLY | O_CREAT | O_EXCL, 0660);
if (ctx->fd != -1) {
- output = o_stream_create_file(ctx->fd, default_pool, 0, FALSE);
- ctx->output = o_stream_create_crlf(default_pool, output);
+ output = o_stream_create_file(ctx->fd, 0, FALSE);
+ ctx->output = o_stream_create_crlf(output);
o_stream_unref(&output);
if (received_date != (time_t)-1) {
diff --git a/src/lib-storage/index/cydir/cydir-storage.c b/src/lib-storage/index/cydir/cydir-storage.c
index 994dcc6..f5975b6 100644
--- a/src/lib-storage/index/cydir/cydir-storage.c
+++ b/src/lib-storage/index/cydir/cydir-storage.c
@@ -347,7 +347,8 @@ static void cydir_notify_changes(struct mailbox *box)
index_mailbox_check_add(&mbox->ibox, mbox->path);
}
-static int cydir_list_iter_is_mailbox(struct mailbox_list_iterate_context *ctx,
+static int cydir_list_iter_is_mailbox(struct mailbox_list_iterate_context *ctx
+ __attr_unused__,
const char *dir, const char *fname,
enum mailbox_list_file_type type,
enum mailbox_info_flags *flags)
@@ -359,9 +360,9 @@ static int cydir_list_iter_is_mailbox(struct mailbox_list_iterate_context *ctx,
/* try to avoid stat() with these checks */
if (type != MAILBOX_LIST_FILE_TYPE_DIR &&
type != MAILBOX_LIST_FILE_TYPE_SYMLINK &&
- type != MAILBOX_LIST_FILE_TYPE_UNKNOWN &&
- (ctx->flags & MAILBOX_LIST_ITER_RETURN_NO_FLAGS) != 0) {
+ type != MAILBOX_LIST_FILE_TYPE_UNKNOWN) {
/* it's a file */
+ *flags |= MAILBOX_NOSELECT | MAILBOX_NOINFERIORS;
return 0;
}
@@ -376,7 +377,8 @@ static int cydir_list_iter_is_mailbox(struct mailbox_list_iterate_context *ctx,
ret = 0;
}
} else {
- /* non-selectable, but may contain subdirs */
+ /* non-selectable. probably either access denied, or symlink
+ destination not found. don't bother logging errors. */
*flags |= MAILBOX_NOSELECT;
}
t_pop();
diff --git a/src/lib-storage/index/dbox/dbox-file.c b/src/lib-storage/index/dbox/dbox-file.c
index 7eba324..6d4ca35 100644
--- a/src/lib-storage/index/dbox/dbox-file.c
+++ b/src/lib-storage/index/dbox/dbox-file.c
@@ -132,8 +132,7 @@ int dbox_file_seek(struct dbox_mailbox *mbox, uint32_t file_seq, uoff_t offset,
}
mbox->file->input =
- i_stream_create_file(mbox->file->fd, default_pool,
- 65536, FALSE);
+ i_stream_create_file(mbox->file->fd, 65536, FALSE);
if (dbox_file_read_header(mbox, mbox->file) < 0)
return -1;
diff --git a/src/lib-storage/index/dbox/dbox-mail.c b/src/lib-storage/index/dbox/dbox-mail.c
index d59dd27..659b001 100644
--- a/src/lib-storage/index/dbox/dbox-mail.c
+++ b/src/lib-storage/index/dbox/dbox-mail.c
@@ -229,8 +229,7 @@ dbox_mail_get_stream(struct mail *_mail,
offset += mbox->file->mail_header_size;
mail->data.stream =
- i_stream_create_limit(default_pool, mbox->file->input,
- offset,
+ i_stream_create_limit(mbox->file->input, offset,
mbox->file->seeked_mail_size);
}
diff --git a/src/lib-storage/index/dbox/dbox-sync-expunge.c b/src/lib-storage/index/dbox/dbox-sync-expunge.c
index 2cf3ed5..b7eb66c 100644
--- a/src/lib-storage/index/dbox/dbox-sync-expunge.c
+++ b/src/lib-storage/index/dbox/dbox-sync-expunge.c
@@ -145,7 +145,7 @@ static int dbox_sync_expunge_copy(struct dbox_sync_context *ctx,
/* try again with another file name */
}
- output = o_stream_create_file(fd, default_pool, 0, FALSE);
+ output = o_stream_create_file(fd, 0, FALSE);
lock_path = file_dotlock_get_lock_path(dotlock);
memset(&dest_entry, 0, sizeof(dest_entry));
@@ -190,7 +190,7 @@ static int dbox_sync_expunge_copy(struct dbox_sync_context *ctx,
/* copy the mail */
full_size = mbox->file->mail_header_size +
mbox->file->seeked_mail_size;
- input = i_stream_create_limit(default_pool, mbox->file->input,
+ input = i_stream_create_limit(mbox->file->input,
mbox->file->seeked_offset,
full_size);
bytes = o_stream_send_istream(output, input);
diff --git a/src/lib-storage/index/dbox/dbox-uidlist.c b/src/lib-storage/index/dbox/dbox-uidlist.c
index 3d7e1ad..c9fd1d4 100644
--- a/src/lib-storage/index/dbox/dbox-uidlist.c
+++ b/src/lib-storage/index/dbox/dbox-uidlist.c
@@ -353,7 +353,7 @@ static int dbox_uidlist_read(struct dbox_uidlist *uidlist)
uidlist->ino = st.st_ino;
uidlist->mtime = st.st_mtime;
- input = i_stream_create_file(uidlist->fd, default_pool, 65536, FALSE);
+ input = i_stream_create_file(uidlist->fd, 65536, FALSE);
/* read header: <version> <uidvalidity> <next-uid>.
Note that <next-uid> may be updated by UID lines, so it can't be
@@ -559,7 +559,7 @@ static int dbox_uidlist_full_rewrite(struct dbox_uidlist *uidlist)
return 0;
}
- output = o_stream_create_file(uidlist->lock_fd, default_pool, 0, FALSE);
+ output = o_stream_create_file(uidlist->lock_fd, 0, FALSE);
t_push();
str = t_str_new(256);
@@ -739,7 +739,7 @@ static int dbox_uidlist_append_changes(struct dbox_uidlist_append_ctx *ctx)
"lseek(%s) failed: %m", ctx->uidlist->path);
return -1;
}
- output = o_stream_create_file(ctx->uidlist->fd, default_pool, 0, FALSE);
+ output = o_stream_create_file(ctx->uidlist->fd, 0, FALSE);
uid_start = ctx->uidlist->last_uid + 1;
@@ -967,9 +967,8 @@ dbox_file_append(struct dbox_uidlist_append_ctx *ctx,
file->path = i_strdup(path);
file->fd = fd;
- file->input = i_stream_create_file(file->fd, default_pool,
- 65536, FALSE);
- file->output = o_stream_create_file(file->fd, default_pool, 0, FALSE);
+ file->input = i_stream_create_file(file->fd, 65536, FALSE);
+ file->output = o_stream_create_file(file->fd, 0, FALSE);
if ((uoff_t)st->st_size < sizeof(struct dbox_file_header)) {
if (dbox_file_write_header(mbox, file) < 0) {
dbox_file_close(file);
@@ -1152,7 +1151,7 @@ int dbox_uidlist_append_locked(struct dbox_uidlist_append_ctx *ctx,
/* we'll always use CRLF linefeeds for mails (but not the header,
so don't do this before dbox_file_write_header()) */
- output = o_stream_create_crlf(default_pool, file->output);
+ output = o_stream_create_crlf(file->output);
o_stream_unref(&file->output);
file->output = output;
diff --git a/src/lib-storage/index/index-mail-headers.c b/src/lib-storage/index/index-mail-headers.c
index 81879c1..bcf69f1 100644
--- a/src/lib-storage/index/index-mail-headers.c
+++ b/src/lib-storage/index/index-mail-headers.c
@@ -7,6 +7,7 @@
#include "str.h"
#include "message-date.h"
#include "message-parser.h"
+#include "message-header-decode.h"
#include "istream-tee.h"
#include "istream-header-filter.h"
#include "imap-envelope.h"
@@ -349,9 +350,9 @@ struct istream *index_mail_cache_parse_init(struct mail *_mail,
i_assert(mail->data.parser_ctx == NULL);
- tee = tee_i_stream_create(input, default_pool);
- input = tee_i_stream_create_child(tee, default_pool);
- input2 = tee_i_stream_create_child(tee, default_pool);
+ tee = tee_i_stream_create(input);
+ input = tee_i_stream_create_child(tee);
+ input2 = tee_i_stream_create_child(tee);
index_mail_parse_header_init(mail, NULL);
mail->data.parser_ctx =
@@ -547,9 +548,9 @@ index_mail_get_parsed_header(struct index_mail *mail, unsigned int field_idx)
return array_idx(&header_values, 0);
}
-const char *const *index_mail_get_headers(struct mail *_mail, const char *field)
+static const char *const *
+index_mail_get_raw_headers(struct index_mail *mail, const char *field)
{
- struct index_mail *mail = (struct index_mail *)_mail;
const char *headers[2], *value;
struct mailbox_header_lookup_ctx *headers_ctx;
unsigned char *data;
@@ -620,11 +621,62 @@ const char *const *index_mail_get_headers(struct mail *_mail, const char *field)
return array_idx(&header_values, 0);
}
-const char *index_mail_get_first_header(struct mail *mail, const char *field)
+static const char *const *
+index_mail_headers_decode(struct index_mail *mail, const char *const *list,
+ unsigned int max_count)
+{
+ const char **decoded_list;
+ unsigned int i, count;
+ buffer_t *buf;
+
+ count = strarray_length(list);
+ if (count > max_count)
+ count = max_count;
+ decoded_list = p_new(mail->data_pool, const char *, count + 1);
+
+ t_push();
+ buf = buffer_create_dynamic(pool_datastack_create(), 512);
+
+ for (i = 0; i < count; i++) {
+ buffer_set_used_size(buf, 0);
+ if (!message_header_decode_utf8((const unsigned char *)list[i],
+ strlen(list[i]), buf, FALSE))
+ decoded_list[i] = list[i];
+ else {
+ decoded_list[i] = p_strndup(mail->data_pool,
+ buf->data, buf->used);
+ }
+ }
+ t_pop();
+ return decoded_list;
+}
+
+const char *const *index_mail_get_headers(struct mail *_mail, const char *field,
+ bool decode_to_utf8)
{
- const char *const *list = index_mail_get_headers(mail, field);
+ struct index_mail *mail = (struct index_mail *)_mail;
+ const char *const *list;
+
+ list = index_mail_get_raw_headers(mail, field);
+ if (!decode_to_utf8 || list == NULL || *list == NULL)
+ return list;
+
+ return index_mail_headers_decode(mail, list, (unsigned int)-1);
+}
+
+const char *index_mail_get_first_header(struct mail *_mail, const char *field,
+ bool decode_to_utf8)
+{
+ struct index_mail *mail = (struct index_mail *)_mail;
+ const char *const *list;
+
+ list = index_mail_get_raw_headers(mail, field);
+ if (list == NULL || *list == NULL)
+ return NULL;
- return list == NULL ? NULL : list[0];
+ if (decode_to_utf8)
+ list = index_mail_headers_decode(mail, list, 1);
+ return list[0];
}
static void header_cache_callback(struct message_header_line *hdr,
@@ -658,8 +710,7 @@ index_mail_get_header_stream(struct mail *_mail,
if (mail->data.filter_stream != NULL)
i_stream_destroy(&mail->data.filter_stream);
mail->data.filter_stream =
- i_stream_create_from_data(default_pool,
- str_data(dest),
+ i_stream_create_from_data(str_data(dest),
str_len(dest));
return mail->data.filter_stream;
}
diff --git a/src/lib-storage/index/index-mail.h b/src/lib-storage/index/index-mail.h
index acfdbfc..18eed3a 100644
--- a/src/lib-storage/index/index-mail.h
+++ b/src/lib-storage/index/index-mail.h
@@ -146,9 +146,11 @@ int index_mail_parse_headers(struct index_mail *mail,
struct mailbox_header_lookup_ctx *headers);
void index_mail_headers_get_envelope(struct index_mail *mail);
-const char *index_mail_get_first_header(struct mail *_mail, const char *field);
+const char *index_mail_get_first_header(struct mail *_mail, const char *field,
+ bool decode_to_utf8);
const char *const *
-index_mail_get_headers(struct mail *_mail, const char *field);
+index_mail_get_headers(struct mail *_mail, const char *field,
+ bool decode_to_utf8);
struct istream *
index_mail_get_header_stream(struct mail *_mail,
struct mailbox_header_lookup_ctx *headers);
diff --git a/src/lib-storage/index/index-sort.c b/src/lib-storage/index/index-sort.c
index 36eb2b3..19b286c 100644
--- a/src/lib-storage/index/index-sort.c
+++ b/src/lib-storage/index/index-sort.c
@@ -31,6 +31,7 @@
#include "array.h"
#include "bsearch-insert-pos.h"
#include "str.h"
+#include "unichar.h"
#include "message-address.h"
#include "imap-base-subject.h"
#include "index-storage.h"
@@ -157,7 +158,7 @@ static const char *get_first_mailbox(struct mail *mail, const char *header)
struct message_address *addr;
const char *str;
- str = mail_get_first_header(mail, header);
+ str = mail_get_first_header_utf8(mail, header);
if (str == NULL)
return "";
@@ -171,6 +172,7 @@ static const char *
sort_header_get(enum mail_sort_type sort_type, struct mail *mail, uint32_t seq)
{
const char *str;
+ string_t *buf;
mail_set_seq(mail, seq);
switch (sort_type & MAIL_SORT_MASK) {
@@ -180,14 +182,21 @@ sort_header_get(enum mail_sort_type sort_type, struct mail *mail, uint32_t seq)
imap_get_base_subject_cased(pool_datastack_create(),
str, NULL);
case MAIL_SORT_CC:
- return get_first_mailbox(mail, "Cc");
+ str = get_first_mailbox(mail, "Cc");
+ break;
case MAIL_SORT_FROM:
- return get_first_mailbox(mail, "From");
+ str = get_first_mailbox(mail, "From");
+ break;
case MAIL_SORT_TO:
- return get_first_mailbox(mail, "To");
+ str = get_first_mailbox(mail, "To");
+ break;
default:
i_unreached();
}
+
+ buf = t_str_new(128);
+ (void)uni_utf8_to_decomposed_titlecase(str, (size_t)-1, buf);
+ return str_c(buf);
}
static int sort_node_cmp_type(struct sort_cmp_context *ctx,
@@ -213,7 +222,7 @@ static int sort_node_cmp_type(struct sort_cmp_context *ctx,
sort_header_get(sort_type, ctx->mail, n1->seq);
str2 = sort_header_get(sort_type, ctx->mail, n2->seq);
- ret = strcasecmp(str1, str2);
+ ret = strcmp(str1, str2);
t_pop();
break;
case MAIL_SORT_ARRIVAL:
@@ -358,9 +367,9 @@ index_sort_add_ids_range(struct mail_search_sort_program *program,
str = sort_header_get(program->sort_program[0], mail,
nodes[i].seq);
- if (i == idx2 && strcasecmp(str, last_str) == 0)
+ if (i == idx2 && strcmp(str, last_str) == 0)
nodes[i].sort_id = last_id;
- else if (strcasecmp(str, str_c(prev_str)) == 0 && prev_id != 0)
+ else if (strcmp(str, str_c(prev_str)) == 0 && prev_id != 0)
nodes[i].sort_id = prev_id;
else {
/* divide the available space so that each message gets
diff --git a/src/lib-storage/index/maildir/maildir-keywords.c b/src/lib-storage/index/maildir/maildir-keywords.c
index 8349741..e7194e1 100644
--- a/src/lib-storage/index/maildir/maildir-keywords.c
+++ b/src/lib-storage/index/maildir/maildir-keywords.c
@@ -133,7 +133,7 @@ static int maildir_keywords_sync(struct maildir_keywords *mk)
}
maildir_keywords_clear(mk);
- input = i_stream_create_file(fd, default_pool, 1024, FALSE);
+ input = i_stream_create_file(fd, 1024, FALSE);
while ((line = i_stream_read_next_line(input)) != NULL) {
p = strchr(line, ' ');
if (p == NULL) {
diff --git a/src/lib-storage/index/maildir/maildir-mail.c b/src/lib-storage/index/maildir/maildir-mail.c
index fd89bbd..2e397cf 100644
--- a/src/lib-storage/index/maildir/maildir-mail.c
+++ b/src/lib-storage/index/maildir/maildir-mail.c
@@ -62,8 +62,7 @@ maildir_open_mail(struct maildir_mailbox *mbox, struct mail *mail,
return NULL;
}
- return i_stream_create_file(fd, default_pool,
- MAIL_READ_BLOCK_SIZE, TRUE);
+ return i_stream_create_file(fd, MAIL_READ_BLOCK_SIZE, TRUE);
}
static int maildir_mail_stat(struct mail *mail, struct stat *st)
diff --git a/src/lib-storage/index/maildir/maildir-save.c b/src/lib-storage/index/maildir/maildir-save.c
index 3a36f82..4d03143 100644
--- a/src/lib-storage/index/maildir/maildir-save.c
+++ b/src/lib-storage/index/maildir/maildir-save.c
@@ -377,11 +377,10 @@ int maildir_save_init(struct mailbox_transaction_context *_t,
ctx->received_date = received_date;
ctx->input = input;
- output = o_stream_create_file(ctx->fd, system_pool, 0, FALSE);
+ output = o_stream_create_file(ctx->fd, 0, FALSE);
ctx->output = (ctx->mbox->storage->storage.flags &
MAIL_STORAGE_FLAG_SAVE_CRLF) != 0 ?
- o_stream_create_crlf(default_pool, output) :
- o_stream_create_lf(default_pool, output);
+ o_stream_create_crlf(output) : o_stream_create_lf(output);
o_stream_unref(&output);
flags &= ~MAIL_RECENT;
diff --git a/src/lib-storage/index/maildir/maildir-uidlist.c b/src/lib-storage/index/maildir/maildir-uidlist.c
index db87689..9bd8bf5 100644
--- a/src/lib-storage/index/maildir/maildir-uidlist.c
+++ b/src/lib-storage/index/maildir/maildir-uidlist.c
@@ -523,7 +523,7 @@ maildir_uidlist_update_read(struct maildir_uidlist *uidlist,
st.st_size/8));
}
- input = i_stream_create_file(fd, default_pool, 4096, FALSE);
+ input = i_stream_create_file(fd, 4096, FALSE);
i_stream_seek(input, uidlist->last_read_offset);
orig_next_uid = uidlist->next_uid;
@@ -804,7 +804,7 @@ static int maildir_uidlist_write_fd(struct maildir_uidlist *uidlist, int fd,
i_assert(fd != -1);
- output = o_stream_create_file(fd, default_pool, 0, FALSE);
+ output = o_stream_create_file(fd, 0, FALSE);
str = t_str_new(512);
if (output->offset == 0) {
diff --git a/src/lib-storage/index/mbox/istream-raw-mbox.c b/src/lib-storage/index/mbox/istream-raw-mbox.c
index 6cd8afd..5b57839 100644
--- a/src/lib-storage/index/mbox/istream-raw-mbox.c
+++ b/src/lib-storage/index/mbox/istream-raw-mbox.c
@@ -343,14 +343,14 @@ static const struct stat *_stat(struct _istream *stream, bool exact)
return &stream->statbuf;
}
-struct istream *i_stream_create_raw_mbox(pool_t pool, struct istream *input,
+struct istream *i_stream_create_raw_mbox(struct istream *input,
bool kludge_one_mail_only)
{
struct raw_mbox_istream *rstream;
i_stream_ref(input);
- rstream = p_new(pool, struct raw_mbox_istream, 1);
+ rstream = i_new(struct raw_mbox_istream, 1);
rstream->one_mail_only = kludge_one_mail_only;
rstream->input = input;
@@ -370,7 +370,7 @@ struct istream *i_stream_create_raw_mbox(pool_t pool, struct istream *input,
rstream->istream.istream.blocking = input->blocking;
rstream->istream.istream.seekable = input->seekable;
- return _i_stream_create(&rstream->istream, pool, -1,
+ return _i_stream_create(&rstream->istream, -1,
input->real_stream->abs_start_offset);
}
diff --git a/src/lib-storage/index/mbox/istream-raw-mbox.h b/src/lib-storage/index/mbox/istream-raw-mbox.h
index b6a74fa..582f812 100644
--- a/src/lib-storage/index/mbox/istream-raw-mbox.h
+++ b/src/lib-storage/index/mbox/istream-raw-mbox.h
@@ -3,7 +3,7 @@
/* Create a mbox stream for parsing mbox. Reading stops before From-line,
you'll have to call istream_raw_mbox_next() to get to next message. */
-struct istream *i_stream_create_raw_mbox(pool_t pool, struct istream *input,
+struct istream *i_stream_create_raw_mbox(struct istream *input,
bool kludge_one_mail_only);
/* Return offset to beginning of the "\nFrom"-line. */
diff --git a/src/lib-storage/index/mbox/mbox-file.c b/src/lib-storage/index/mbox/mbox-file.c
index cfbe626..f7166a9 100644
--- a/src/lib-storage/index/mbox/mbox-file.c
+++ b/src/lib-storage/index/mbox/mbox-file.c
@@ -73,8 +73,7 @@ int mbox_file_open_stream(struct mbox_mailbox *mbox)
i_assert(mbox->mbox_fd == -1 && mbox->mbox_readonly);
mbox->mbox_stream =
- i_stream_create_raw_mbox(default_pool,
- mbox->mbox_file_stream,
+ i_stream_create_raw_mbox(mbox->mbox_file_stream,
one_mail_only);
return 0;
}
@@ -84,18 +83,16 @@ int mbox_file_open_stream(struct mbox_mailbox *mbox)
return -1;
}
- if (mbox->mbox_writeonly) {
+ if (mbox->mbox_writeonly)
+ mbox->mbox_file_stream = i_stream_create_from_data(NULL, 0);
+ else {
mbox->mbox_file_stream =
- i_stream_create_from_data(default_pool, NULL, 0);
- } else {
- mbox->mbox_file_stream =
- i_stream_create_file(mbox->mbox_fd, default_pool,
+ i_stream_create_file(mbox->mbox_fd,
MAIL_READ_BLOCK_SIZE, FALSE);
}
mbox->mbox_stream =
- i_stream_create_raw_mbox(default_pool, mbox->mbox_file_stream,
- one_mail_only);
+ i_stream_create_raw_mbox(mbox->mbox_file_stream, one_mail_only);
return 0;
}
diff --git a/src/lib-storage/index/mbox/mbox-mail.c b/src/lib-storage/index/mbox/mbox-mail.c
index 79190d9..5fef2e9 100644
--- a/src/lib-storage/index/mbox/mbox-mail.c
+++ b/src/lib-storage/index/mbox/mbox-mail.c
@@ -209,7 +209,7 @@ static struct istream *mbox_mail_get_stream(struct mail *_mail,
raw_stream = mbox->mbox_stream;
offset = istream_raw_mbox_get_header_offset(raw_stream);
- raw_stream = i_stream_create_limit(default_pool, raw_stream,
+ raw_stream = i_stream_create_limit(raw_stream,
offset, (uoff_t)-1);
data->stream =
i_stream_create_header_filter(raw_stream,
diff --git a/src/lib-storage/index/mbox/mbox-save.c b/src/lib-storage/index/mbox/mbox-save.c
index 2ffd3b0..fa69025 100644
--- a/src/lib-storage/index/mbox/mbox-save.c
+++ b/src/lib-storage/index/mbox/mbox-save.c
@@ -321,8 +321,7 @@ mbox_save_init_file(struct mbox_save_context *ctx,
if (mbox_seek_to_end(ctx, &ctx->append_offset) < 0)
return -1;
- ctx->output = o_stream_create_file(mbox->mbox_fd, default_pool,
- 0, FALSE);
+ ctx->output = o_stream_create_file(mbox->mbox_fd, 0, FALSE);
}
return 0;
}
@@ -477,8 +476,8 @@ int mbox_save_init(struct mailbox_transaction_context *_t,
ctx->body_output =
(mbox->storage->storage.flags &
MAIL_STORAGE_FLAG_SAVE_CRLF) != 0 ?
- o_stream_create_crlf(default_pool, ctx->output) :
- o_stream_create_lf(default_pool, ctx->output);
+ o_stream_create_crlf(ctx->output) :
+ o_stream_create_lf(ctx->output);
if (ctx->mail != NULL) {
input = index_mail_cache_parse_init(ctx->mail,
ctx->input);
diff --git a/src/lib-storage/index/mbox/mbox-sync-rewrite.c b/src/lib-storage/index/mbox/mbox-sync-rewrite.c
index fa62858..3338bb7 100644
--- a/src/lib-storage/index/mbox/mbox-sync-rewrite.c
+++ b/src/lib-storage/index/mbox/mbox-sync-rewrite.c
@@ -26,8 +26,7 @@ int mbox_move(struct mbox_sync_context *sync_ctx,
i_stream_sync(sync_ctx->input);
- output = o_stream_create_file(sync_ctx->write_fd, default_pool,
- 4096, FALSE);
+ output = o_stream_create_file(sync_ctx->write_fd, 4096, FALSE);
i_stream_seek(sync_ctx->file_input, source);
if (o_stream_seek(output, dest) < 0) {
mbox_set_syscall_error(sync_ctx->mbox,
@@ -36,8 +35,7 @@ int mbox_move(struct mbox_sync_context *sync_ctx,
return -1;
}
- input = i_stream_create_limit(default_pool, sync_ctx->file_input,
- source, size);
+ input = i_stream_create_limit(sync_ctx->file_input, source, size);
ret = o_stream_send_istream(output, input);
i_stream_unref(&input);
diff --git a/src/lib-storage/list/subscription-file.c b/src/lib-storage/list/subscription-file.c
index 5aa1ddf..cc24560 100644
--- a/src/lib-storage/list/subscription-file.c
+++ b/src/lib-storage/list/subscription-file.c
@@ -16,11 +16,9 @@
#define SUBSCRIPTION_FILE_CHANGE_TIMEOUT 30
struct subsfile_list_context {
- pool_t pool;
-
struct mailbox_list *list;
struct istream *input;
- const char *path;
+ char *path;
bool failed;
};
@@ -115,10 +113,10 @@ int subsfile_set_subscribed(struct mailbox_list *list, const char *path,
}
input = fd_in == -1 ? NULL :
- i_stream_create_file(fd_in, default_pool,
- list->mailbox_name_max_length+1, TRUE);
- output = o_stream_create_file(fd_out, default_pool,
- list->mailbox_name_max_length+1, FALSE);
+ i_stream_create_file(fd_in, list->mailbox_name_max_length+1,
+ TRUE);
+ output = o_stream_create_file(fd_out, list->mailbox_name_max_length+1,
+ FALSE);
found = FALSE;
while ((line = next_line(list, path, input,
&failed, FALSE)) != NULL) {
@@ -176,14 +174,9 @@ struct subsfile_list_context *
subsfile_list_init(struct mailbox_list *list, const char *path)
{
struct subsfile_list_context *ctx;
- pool_t pool;
int fd;
- pool = pool_alloconly_create("subsfile_list",
- list->mailbox_name_max_length + 1024);
-
- ctx = p_new(pool, struct subsfile_list_context, 1);
- ctx->pool = pool;
+ ctx = i_new(struct subsfile_list_context, 1);
ctx->list = list;
fd = nfs_safe_open(path, O_RDONLY);
@@ -193,12 +186,10 @@ subsfile_list_init(struct mailbox_list *list, const char *path)
ctx->failed = TRUE;
}
} else {
- ctx->input =
- i_stream_create_file(fd, pool,
- list->mailbox_name_max_length+1,
- TRUE);
+ ctx->input = i_stream_create_file(fd,
+ list->mailbox_name_max_length+1, TRUE);
}
- ctx->path = p_strdup(pool, path);
+ ctx->path = i_strdup(path);
return ctx;
}
@@ -208,7 +199,8 @@ int subsfile_list_deinit(struct subsfile_list_context *ctx)
if (ctx->input != NULL)
i_stream_destroy(&ctx->input);
- pool_unref(ctx->pool);
+ i_free(ctx->path);
+ i_free(ctx);
return ret;
}
@@ -247,7 +239,7 @@ const char *subsfile_list_next(struct subsfile_list_context *ctx)
return NULL;
}
- ctx->input = i_stream_create_file(fd, ctx->pool,
+ ctx->input = i_stream_create_file(fd,
ctx->list->mailbox_name_max_length+1,
TRUE);
}
diff --git a/src/lib-storage/mail-storage-private.h b/src/lib-storage/mail-storage-private.h
index 9e81307..ec8ae3e 100644
--- a/src/lib-storage/mail-storage-private.h
+++ b/src/lib-storage/mail-storage-private.h
@@ -208,8 +208,10 @@ struct mail_vfuncs {
uoff_t (*get_virtual_size)(struct mail *mail);
uoff_t (*get_physical_size)(struct mail *mail);
- const char *(*get_first_header)(struct mail *mail, const char *field);
- const char *const *(*get_headers)(struct mail *mail, const char *field);
+ const char *(*get_first_header)(struct mail *mail, const char *field,
+ bool decode_to_utf8);
+ const char *const *(*get_headers)(struct mail *mail, const char *field,
+ bool decode_to_utf8);
struct istream *
(*get_header_stream)(struct mail *mail,
struct mailbox_header_lookup_ctx *headers);
diff --git a/src/lib-storage/mail-storage.h b/src/lib-storage/mail-storage.h
index 27918ad..2192203 100644
--- a/src/lib-storage/mail-storage.h
+++ b/src/lib-storage/mail-storage.h
@@ -424,8 +424,12 @@ uoff_t mail_get_physical_size(struct mail *mail);
/* Get value for single header field */
const char *mail_get_first_header(struct mail *mail, const char *field);
+/* Like mail_get_first_header(), but decode MIME encoded words to UTF-8 */
+const char *mail_get_first_header_utf8(struct mail *mail, const char *field);
/* Return a NULL-terminated list of values for each found field. */
const char *const *mail_get_headers(struct mail *mail, const char *field);
+/* Like mail_get_headers(), but decode MIME encoded words to UTF-8 */
+const char *const *mail_get_headers_utf8(struct mail *mail, const char *field);
/* Returns stream containing specified headers. */
struct istream *
mail_get_header_stream(struct mail *mail,
diff --git a/src/lib-storage/mail.c b/src/lib-storage/mail.c
index 61846a0..37566d7 100644
--- a/src/lib-storage/mail.c
+++ b/src/lib-storage/mail.c
@@ -93,14 +93,28 @@ const char *mail_get_first_header(struct mail *mail, const char *field)
{
struct mail_private *p = (struct mail_private *)mail;
- return p->v.get_first_header(mail, field);
+ return p->v.get_first_header(mail, field, FALSE);
+}
+
+const char *mail_get_first_header_utf8(struct mail *mail, const char *field)
+{
+ struct mail_private *p = (struct mail_private *)mail;
+
+ return p->v.get_first_header(mail, field, TRUE);
}
const char *const *mail_get_headers(struct mail *mail, const char *field)
{
struct mail_private *p = (struct mail_private *)mail;
- return p->v.get_headers(mail, field);
+ return p->v.get_headers(mail, field, FALSE);
+}
+
+const char *const *mail_get_headers_utf8(struct mail *mail, const char *field)
+{
+ struct mail_private *p = (struct mail_private *)mail;
+
+ return p->v.get_headers(mail, field, TRUE);
}
struct istream *
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
index 059fa0a..385d065 100644
--- a/src/lib/Makefile.am
+++ b/src/lib/Makefile.am
@@ -1,5 +1,13 @@
noinst_LIBRARIES = liblib.a
+BUILT_SOURCES = unicodemap.c
+
+EXTRA_DIST = unicodemap.c unicodemap.pl
+
+unicodemap.c:
+ test -f UnicodeData.txt || wget http://www.unicode.org/Public/UNIDATA/UnicodeData.txt
+ perl unicodemap.pl < UnicodeData.txt > $@
+
liblib_a_SOURCES = \
backtrace-string.c \
base64.c \
diff --git a/src/lib/bsearch-insert-pos.h b/src/lib/bsearch-insert-pos.h
index 4558ba9..daaa101 100644
--- a/src/lib/bsearch-insert-pos.h
+++ b/src/lib/bsearch-insert-pos.h
@@ -1,6 +1,25 @@
#ifndef __BSEARCH_INSERT_POS
#define __BSEARCH_INSERT_POS
+/* Binary search template */
+#define BINARY_NUMBER_SEARCH(data, count, value, idx_r) \
+ unsigned int idx, left_idx, right_idx; \
+ \
+ idx = 0; left_idx = 0; right_idx = (count); \
+ while (left_idx < right_idx) { \
+ idx = (left_idx + right_idx) / 2; \
+ \
+ if ((data)[idx] < (value)) \
+ left_idx = idx+1; \
+ else if ((data)[idx] > (value)) \
+ right_idx = idx; \
+ else { \
+ *(idx_r) = idx; \
+ return TRUE; \
+ } \
+ } \
+ return FALSE
+
/* If key is found, returns TRUE and sets idx_r to the position where the key
was found. If key isn't found, returns FALSE and sets idx_r to the position
where the key should be inserted. */
diff --git a/src/lib/file-copy.c b/src/lib/file-copy.c
index 1c0ba00..b7b0256 100644
--- a/src/lib/file-copy.c
+++ b/src/lib/file-copy.c
@@ -68,8 +68,8 @@ static int file_copy_to_tmp(const char *srcpath, const char *tmppath,
/* try to change the group, don't really care if it fails */
(void)fchown(fd_out, (uid_t)-1, st.st_gid);
- input = i_stream_create_file(fd_in, default_pool, 0, FALSE);
- output = o_stream_create_file(fd_out, default_pool, 0, FALSE);
+ input = i_stream_create_file(fd_in, 0, FALSE);
+ output = o_stream_create_file(fd_out, 0, FALSE);
while ((ret = o_stream_send_istream(output, input)) > 0) ;
diff --git a/src/lib/iostream-internal.h b/src/lib/iostream-internal.h
index 16572f1..d8f7743 100644
--- a/src/lib/iostream-internal.h
+++ b/src/lib/iostream-internal.h
@@ -4,7 +4,6 @@
/* This file is private to input stream and output stream implementations */
struct _iostream {
- pool_t pool;
int refcount;
void (*close)(struct _iostream *stream);
@@ -12,7 +11,7 @@ struct _iostream {
void (*set_max_buffer_size)(struct _iostream *stream, size_t max_size);
};
-void _io_stream_init(pool_t pool, struct _iostream *stream);
+void _io_stream_init(struct _iostream *stream);
void _io_stream_ref(struct _iostream *stream);
void _io_stream_unref(struct _iostream *stream);
void _io_stream_close(struct _iostream *stream);
diff --git a/src/lib/iostream.c b/src/lib/iostream.c
index aafbed5..78aab85 100644
--- a/src/lib/iostream.c
+++ b/src/lib/iostream.c
@@ -3,10 +3,8 @@
#include "lib.h"
#include "iostream-internal.h"
-void _io_stream_init(pool_t pool, struct _iostream *stream)
+void _io_stream_init(struct _iostream *stream)
{
- pool_ref(pool);
- stream->pool = pool;
stream->refcount = 1;
}
@@ -17,8 +15,6 @@ void _io_stream_ref(struct _iostream *stream)
void _io_stream_unref(struct _iostream *stream)
{
- pool_t pool;
-
i_assert(stream->refcount > 0);
if (--stream->refcount != 0)
return;
@@ -26,9 +22,7 @@ void _io_stream_unref(struct _iostream *stream)
stream->close(stream);
stream->destroy(stream);
- pool = stream->pool;
- p_free(pool, stream);
- pool_unref(pool);
+ i_free(stream);
}
void _io_stream_close(struct _iostream *stream)
diff --git a/src/lib/istream-data.c b/src/lib/istream-data.c
index becbee3..7e98bb9 100644
--- a/src/lib/istream-data.c
+++ b/src/lib/istream-data.c
@@ -24,12 +24,11 @@ static void _seek(struct _istream *stream, uoff_t v_offset,
stream->istream.v_offset = v_offset;
}
-struct istream *i_stream_create_from_data(pool_t pool, const void *data,
- size_t size)
+struct istream *i_stream_create_from_data(const void *data, size_t size)
{
struct _istream *stream;
- stream = p_new(pool, struct _istream, 1);
+ stream = i_new(struct _istream, 1);
stream->buffer = data;
stream->pos = size;
@@ -41,7 +40,7 @@ struct istream *i_stream_create_from_data(pool_t pool, const void *data,
stream->istream.blocking = TRUE;
stream->istream.seekable = TRUE;
- (void)_i_stream_create(stream, pool, -1, 0);
+ (void)_i_stream_create(stream, -1, 0);
stream->statbuf.st_size = size;
return &stream->istream;
}
diff --git a/src/lib/istream-file.c b/src/lib/istream-file.c
index 49b5eaf..2d270d6 100644
--- a/src/lib/istream-file.c
+++ b/src/lib/istream-file.c
@@ -36,7 +36,7 @@ static void _destroy(struct _iostream *stream)
{
struct _istream *_stream = (struct _istream *) stream;
- p_free(_stream->iostream.pool, _stream->w_buffer);
+ i_free(_stream->w_buffer);
}
static ssize_t _read(struct _istream *stream)
@@ -159,13 +159,13 @@ _stat(struct _istream *stream, bool exact __attr_unused__)
return &stream->statbuf;
}
-struct istream *i_stream_create_file(int fd, pool_t pool,
- size_t max_buffer_size, bool autoclose_fd)
+struct istream *i_stream_create_file(int fd, size_t max_buffer_size,
+ bool autoclose_fd)
{
struct file_istream *fstream;
struct stat st;
- fstream = p_new(pool, struct file_istream, 1);
+ fstream = i_new(struct file_istream, 1);
fstream->autoclose_fd = autoclose_fd;
fstream->istream.iostream.close = _close;
@@ -184,5 +184,5 @@ struct istream *i_stream_create_file(int fd, pool_t pool,
fstream->istream.istream.seekable = TRUE;
}
- return _i_stream_create(&fstream->istream, pool, fd, 0);
+ return _i_stream_create(&fstream->istream, fd, 0);
}
diff --git a/src/lib/istream-internal.h b/src/lib/istream-internal.h
index 23ee63f..780cd5d 100644
--- a/src/lib/istream-internal.h
+++ b/src/lib/istream-internal.h
@@ -32,8 +32,8 @@ struct _istream {
string_t *line_str; /* for i_stream_next_line() if w_buffer == NULL */
};
-struct istream *_i_stream_create(struct _istream *_buf, pool_t pool, int fd,
- uoff_t abs_start_offset);
+struct istream *
+_i_stream_create(struct _istream *_buf, int fd, uoff_t abs_start_offset);
void _i_stream_compress(struct _istream *stream);
void _i_stream_grow_buffer(struct _istream *stream, size_t bytes);
diff --git a/src/lib/istream-limit.c b/src/lib/istream-limit.c
index 7e77751..e1fec24 100644
--- a/src/lib/istream-limit.c
+++ b/src/lib/istream-limit.c
@@ -108,14 +108,14 @@ static const struct stat *_stat(struct _istream *stream, bool exact)
return &stream->statbuf;
}
-struct istream *i_stream_create_limit(pool_t pool, struct istream *input,
+struct istream *i_stream_create_limit(struct istream *input,
uoff_t v_start_offset, uoff_t v_size)
{
struct limit_istream *lstream;
i_stream_ref(input);
- lstream = p_new(pool, struct limit_istream, 1);
+ lstream = i_new(struct limit_istream, 1);
lstream->input = input;
lstream->v_start_offset = v_start_offset;
lstream->v_size = v_size;
@@ -135,7 +135,7 @@ struct istream *i_stream_create_limit(pool_t pool, struct istream *input,
lstream->istream.istream.blocking = input->blocking;
lstream->istream.istream.seekable = input->seekable;
- return _i_stream_create(&lstream->istream, pool, i_stream_get_fd(input),
+ return _i_stream_create(&lstream->istream, i_stream_get_fd(input),
input->real_stream->abs_start_offset +
v_start_offset);
}
diff --git a/src/lib/istream-mmap.c b/src/lib/istream-mmap.c
index 53d47b4..55a378f 100644
--- a/src/lib/istream-mmap.c
+++ b/src/lib/istream-mmap.c
@@ -185,7 +185,7 @@ _stat(struct _istream *stream, bool exact __attr_unused__)
return &stream->statbuf;
}
-struct istream *i_stream_create_mmap(int fd, pool_t pool, size_t block_size,
+struct istream *i_stream_create_mmap(int fd, size_t block_size,
uoff_t start_offset, uoff_t v_size,
bool autoclose_fd)
{
@@ -207,7 +207,7 @@ struct istream *i_stream_create_mmap(int fd, pool_t pool, size_t block_size,
}
}
- mstream = p_new(pool, struct mmap_istream, 1);
+ mstream = i_new(struct mmap_istream, 1);
mstream->autoclose_fd = autoclose_fd;
mstream->v_size = v_size;
@@ -220,7 +220,7 @@ struct istream *i_stream_create_mmap(int fd, pool_t pool, size_t block_size,
mstream->istream.sync = _sync;
mstream->istream.stat = _stat;
- istream = _i_stream_create(&mstream->istream, pool, fd, start_offset);
+ istream = _i_stream_create(&mstream->istream, fd, start_offset);
istream->mmaped = TRUE;
istream->blocking = TRUE;
istream->seekable = TRUE;
diff --git a/src/lib/istream-seekable.c b/src/lib/istream-seekable.c
index b0a95a3..8c60bd1 100644
--- a/src/lib/istream-seekable.c
+++ b/src/lib/istream-seekable.c
@@ -17,7 +17,6 @@
struct seekable_istream {
struct _istream istream;
- pool_t pool;
size_t max_buffer_size;
char *temp_prefix;
@@ -54,8 +53,7 @@ static void _destroy(struct _iostream *stream)
for (i = 0; sstream->input[i] != NULL; i++)
i_stream_unref(&sstream->input[i]);
- p_free(sstream->pool, sstream->temp_prefix);
- pool_unref(sstream->pool);
+ i_free(sstream->temp_prefix);
}
static void _set_max_buffer_size(struct _iostream *stream, size_t max_size)
@@ -124,8 +122,7 @@ static int copy_to_temp_file(struct seekable_istream *sstream)
sstream->fd = fd;
sstream->fd_input =
- i_stream_create_file(fd, sstream->pool,
- sstream->max_buffer_size, TRUE);
+ i_stream_create_file(fd, sstream->max_buffer_size, TRUE);
return 0;
}
@@ -296,7 +293,7 @@ static const struct stat *_stat(struct _istream *stream, bool exact)
}
struct istream *
-i_stream_create_seekable(struct istream *input[], pool_t pool,
+i_stream_create_seekable(struct istream *input[],
size_t max_buffer_size, const char *temp_prefix)
{
struct seekable_istream *sstream;
@@ -308,14 +305,12 @@ i_stream_create_seekable(struct istream *input[], pool_t pool,
i_stream_ref(input[count]);
i_assert(count != 0);
- pool_ref(pool);
- sstream = p_new(pool, struct seekable_istream, 1);
- sstream->pool = pool;
- sstream->temp_prefix = p_strdup(pool, temp_prefix);
- sstream->buffer = buffer_create_dynamic(pool, BUF_INITIAL_SIZE);
+ sstream = i_new(struct seekable_istream, 1);
+ sstream->temp_prefix = i_strdup(temp_prefix);
+ sstream->buffer = buffer_create_dynamic(default_pool, BUF_INITIAL_SIZE);
sstream->max_buffer_size = max_buffer_size;
- sstream->input = p_new(pool, struct istream *, count + 1);
+ sstream->input = i_new(struct istream *, count + 1);
memcpy(sstream->input, input, sizeof(*input) * count);
sstream->cur_input = sstream->input[0];
@@ -332,5 +327,5 @@ i_stream_create_seekable(struct istream *input[], pool_t pool,
sstream->istream.seek = _seek;
sstream->istream.stat = _stat;
- return _i_stream_create(&sstream->istream, pool, -1, 0);
+ return _i_stream_create(&sstream->istream, -1, 0);
}
diff --git a/src/lib/istream-seekable.h b/src/lib/istream-seekable.h
index 2775a07..c9f2a52 100644
--- a/src/lib/istream-seekable.h
+++ b/src/lib/istream-seekable.h
@@ -7,7 +7,7 @@
temp_prefix is used as path and filename prefix for creating the file.
It will be appended by PID, timestamp and 128 bits of weak randomness. */
struct istream *
-i_stream_create_seekable(struct istream *input[], pool_t pool,
+i_stream_create_seekable(struct istream *input[],
size_t max_buffer_size, const char *temp_prefix);
#endif
diff --git a/src/lib/istream-tee.c b/src/lib/istream-tee.c
index 02cf133..af2f525 100644
--- a/src/lib/istream-tee.c
+++ b/src/lib/istream-tee.c
@@ -5,7 +5,6 @@
#include "istream-tee.h"
struct tee_istream {
- pool_t pool;
struct istream *input;
struct tee_child_istream *children;
@@ -88,7 +87,7 @@ static void _destroy(struct _iostream *stream)
tee->max_read_offset - tee->input->v_offset);
i_stream_unref(&tee->input);
- p_free(tee->pool, tee);
+ i_free(tee);
} else {
tee_streams_skip(tstream->tee);
}
@@ -170,24 +169,22 @@ static void _sync(struct _istream *stream)
return i_stream_sync(tstream->tee->input);
}
-struct tee_istream *tee_i_stream_create(struct istream *input, pool_t pool)
+struct tee_istream *tee_i_stream_create(struct istream *input)
{
struct tee_istream *tee;
- tee = p_new(pool, struct tee_istream, 1);
- tee->pool = pool;
+ tee = i_new(struct tee_istream, 1);
tee->input = input;
i_stream_ref(input);
return tee;
}
-struct istream *
-tee_i_stream_create_child(struct tee_istream *tee, pool_t pool)
+struct istream *tee_i_stream_create_child(struct tee_istream *tee)
{
struct tee_child_istream *tstream;
- tstream = p_new(pool, struct tee_child_istream, 1);
+ tstream = i_new(struct tee_child_istream, 1);
tstream->tee = tee;
tstream->istream.iostream.close = _close;
@@ -202,6 +199,6 @@ tee_i_stream_create_child(struct tee_istream *tee, pool_t pool)
tstream->next = tee->children;
tee->children = tstream;
- return _i_stream_create(&tstream->istream, pool,
+ return _i_stream_create(&tstream->istream,
i_stream_get_fd(tee->input), 0);
}
diff --git a/src/lib/istream-tee.h b/src/lib/istream-tee.h
index 0e814cf..0ceeb6c 100644
--- a/src/lib/istream-tee.h
+++ b/src/lib/istream-tee.h
@@ -7,9 +7,8 @@
If the stream's buffer gets full because some child isn't consuming the
data, other streams get returned 0 by i_stream_read(). */
-struct tee_istream *tee_i_stream_create(struct istream *input, pool_t pool);
+struct tee_istream *tee_i_stream_create(struct istream *input);
-struct istream *
-tee_i_stream_create_child(struct tee_istream *tee, pool_t pool);
+struct istream *tee_i_stream_create_child(struct tee_istream *tee);
#endif
diff --git a/src/lib/istream.c b/src/lib/istream.c
index 7b194c1..987a5fc 100644
--- a/src/lib/istream.c
+++ b/src/lib/istream.c
@@ -279,19 +279,15 @@ void _i_stream_grow_buffer(struct _istream *stream, size_t bytes)
stream->buffer_size = stream->pos + bytes;
if (stream->buffer_size <= I_STREAM_MIN_SIZE)
stream->buffer_size = I_STREAM_MIN_SIZE;
- else {
- stream->buffer_size =
- pool_get_exp_grown_size(stream->iostream.pool,
- old_size, stream->buffer_size);
- }
+ else
+ stream->buffer_size = nearest_power(stream->buffer_size);
if (stream->max_buffer_size > 0 &&
stream->buffer_size > stream->max_buffer_size)
stream->buffer_size = stream->max_buffer_size;
stream->buffer = stream->w_buffer =
- p_realloc(stream->iostream.pool, stream->w_buffer,
- old_size, stream->buffer_size);
+ i_realloc(stream->w_buffer, old_size, stream->buffer_size);
}
static void _set_max_buffer_size(struct _iostream *stream, size_t max_size)
@@ -307,8 +303,8 @@ _stat(struct _istream *stream, bool exact __attr_unused__)
return &stream->statbuf;
}
-struct istream *_i_stream_create(struct _istream *_stream, pool_t pool, int fd,
- uoff_t abs_start_offset)
+struct istream *
+_i_stream_create(struct _istream *_stream, int fd, uoff_t abs_start_offset)
{
_stream->fd = fd;
_stream->abs_start_offset = abs_start_offset;
@@ -325,7 +321,7 @@ struct istream *_i_stream_create(struct _istream *_stream, pool_t pool, int fd,
_stream->statbuf.st_mtime =
_stream->statbuf.st_ctime = ioloop_time;
- _io_stream_init(pool, &_stream->iostream);
+ _io_stream_init(&_stream->iostream);
return &_stream->istream;
}
@@ -371,7 +367,7 @@ int main(void)
write(fd1, buf, sizeof(buf));
/* test reading */
- input = i_stream_create_file(fd1, default_pool, 512, FALSE);
+ input = i_stream_create_file(fd1, 512, FALSE);
i_assert(i_stream_get_size(input) == sizeof(buf));
i_assert(i_stream_read_data(input, &data, &size, 0) > 0);
@@ -394,8 +390,8 @@ int main(void)
check_buffer(data, size, 900);
/* test moving data */
- output1 = o_stream_create_file(fd1, default_pool, 512, FALSE);
- output2 = o_stream_create_file(fd2, default_pool, 512, FALSE);
+ output1 = o_stream_create_file(fd1, 512, FALSE);
+ output2 = o_stream_create_file(fd2, 512, FALSE);
i_stream_seek(input, 1); size = sizeof(buf)-1;
i_assert(o_stream_send_istream(output2, input) == size);
@@ -410,8 +406,7 @@ int main(void)
i_assert(o_stream_send_istream(output1, input) == sizeof(buf));
/* test moving with limits */
- l_input = i_stream_create_limit(default_pool, input,
- sizeof(buf)/2, 512);
+ l_input = i_stream_create_limit(input, sizeof(buf)/2, 512);
i_stream_seek(l_input, 0);
o_stream_seek(output1, 10);
i_assert(o_stream_send_istream(output1, l_input) == 512);
diff --git a/src/lib/istream.h b/src/lib/istream.h
index a08af7d..bdc1d12 100644
--- a/src/lib/istream.h
+++ b/src/lib/istream.h
@@ -18,14 +18,13 @@ struct istream {
struct _istream *real_stream;
};
-struct istream *i_stream_create_file(int fd, pool_t pool,
- size_t max_buffer_size, bool autoclose_fd);
-struct istream *i_stream_create_mmap(int fd, pool_t pool, size_t block_size,
+struct istream *i_stream_create_file(int fd, size_t max_buffer_size,
+ bool autoclose_fd);
+struct istream *i_stream_create_mmap(int fd, size_t block_size,
uoff_t start_offset, uoff_t v_size,
bool autoclose_fd);
-struct istream *i_stream_create_from_data(pool_t pool, const void *data,
- size_t size);
-struct istream *i_stream_create_limit(pool_t pool, struct istream *input,
+struct istream *i_stream_create_from_data(const void *data, size_t size);
+struct istream *i_stream_create_limit(struct istream *input,
uoff_t v_start_offset, uoff_t v_size);
/* i_stream_close() + i_stream_unref() */
diff --git a/src/lib/macros.h b/src/lib/macros.h
index 1f0705a..42152ec 100644
--- a/src/lib/macros.h
+++ b/src/lib/macros.h
@@ -15,6 +15,9 @@
# define TRUE (!FALSE)
#endif
+#define N_ELEMENTS(arr) \
+ (sizeof(arr) / sizeof((arr)[0]))
+
#define BITS_IN_UINT (CHAR_BIT * sizeof(unsigned int))
#define BITS_IN_SIZE_T (CHAR_BIT * sizeof(size_t))
diff --git a/src/lib/ostream-crlf.c b/src/lib/ostream-crlf.c
index 9a11f94..1150a97 100644
--- a/src/lib/ostream-crlf.c
+++ b/src/lib/ostream-crlf.c
@@ -347,12 +347,11 @@ _send_istream(struct _ostream *outstream, struct istream *instream)
return sent == 0 && instream->stream_errno != 0 ? -1 : (ssize_t)sent;
}
-static struct crlf_ostream *
-o_stream_create_common(pool_t pool, struct ostream *output)
+static struct crlf_ostream *o_stream_create_common(struct ostream *output)
{
struct crlf_ostream *cstream;
- cstream = p_new(pool, struct crlf_ostream, 1);
+ cstream = i_new(struct crlf_ostream, 1);
cstream->output = output;
o_stream_ref(output);
@@ -369,20 +368,20 @@ o_stream_create_common(pool_t pool, struct ostream *output)
return cstream;
}
-struct ostream *o_stream_create_crlf(pool_t pool, struct ostream *output)
+struct ostream *o_stream_create_crlf(struct ostream *output)
{
struct crlf_ostream *cstream;
- cstream = o_stream_create_common(pool, output);
+ cstream = o_stream_create_common(output);
cstream->ostream.sendv = _sendv_crlf;
- return _o_stream_create(&cstream->ostream, pool);
+ return _o_stream_create(&cstream->ostream);
}
-struct ostream *o_stream_create_lf(pool_t pool, struct ostream *output)
+struct ostream *o_stream_create_lf(struct ostream *output)
{
struct crlf_ostream *cstream;
- cstream = o_stream_create_common(pool, output);
+ cstream = o_stream_create_common(output);
cstream->ostream.sendv = _sendv_lf;
- return _o_stream_create(&cstream->ostream, pool);
+ return _o_stream_create(&cstream->ostream);
}
diff --git a/src/lib/ostream-crlf.h b/src/lib/ostream-crlf.h
index b6171a1..7fa38d7 100644
--- a/src/lib/ostream-crlf.h
+++ b/src/lib/ostream-crlf.h
@@ -2,8 +2,8 @@
#define __OSTREAM_CRLF_H
/* Replace all plain LFs with CRLF. */
-struct ostream *o_stream_create_crlf(pool_t pool, struct ostream *output);
+struct ostream *o_stream_create_crlf(struct ostream *output);
/* Replace all CRLF pairs with plain LFs. */
-struct ostream *o_stream_create_lf(pool_t pool, struct ostream *output);
+struct ostream *o_stream_create_lf(struct ostream *output);
#endif
diff --git a/src/lib/ostream-file.c b/src/lib/ostream-file.c
index 47c8887..31a2c59 100644
--- a/src/lib/ostream-file.c
+++ b/src/lib/ostream-file.c
@@ -78,7 +78,7 @@ static void _destroy(struct _iostream *stream)
{
struct file_ostream *fstream = (struct file_ostream *)stream;
- p_free(fstream->ostream.iostream.pool, fstream->buffer);
+ i_free(fstream->buffer);
}
static void _set_max_buffer_size(struct _iostream *stream, size_t max_size)
@@ -322,9 +322,7 @@ static void o_stream_grow_buffer(struct file_ostream *fstream, size_t bytes)
{
size_t size, new_size, end_size;
- size = pool_get_exp_grown_size(fstream->ostream.iostream.pool,
- fstream->buffer_size,
- fstream->buffer_size + bytes);
+ size = nearest_power(fstream->buffer_size + bytes);
if (size > fstream->max_buffer_size) {
/* limit the size */
size = fstream->max_buffer_size;
@@ -339,8 +337,7 @@ static void o_stream_grow_buffer(struct file_ostream *fstream, size_t bytes)
if (size <= fstream->buffer_size)
return;
- fstream->buffer = p_realloc(fstream->ostream.iostream.pool,
- fstream->buffer,
+ fstream->buffer = i_realloc(fstream->buffer,
fstream->buffer_size, size);
if (fstream->tail <= fstream->head && !IS_STREAM_EMPTY(fstream)) {
@@ -737,15 +734,14 @@ static off_t _send_istream(struct _ostream *outstream, struct istream *instream)
}
struct ostream *
-o_stream_create_file(int fd, pool_t pool, size_t max_buffer_size,
- bool autoclose_fd)
+o_stream_create_file(int fd, size_t max_buffer_size, bool autoclose_fd)
{
struct file_ostream *fstream;
struct ostream *ostream;
struct stat st;
off_t offset;
- fstream = p_new(pool, struct file_ostream, 1);
+ fstream = i_new(struct file_ostream, 1);
fstream->fd = fd;
fstream->max_buffer_size = max_buffer_size;
fstream->autoclose_fd = autoclose_fd;
@@ -763,7 +759,7 @@ o_stream_create_file(int fd, pool_t pool, size_t max_buffer_size,
fstream->ostream.sendv = _sendv;
fstream->ostream.send_istream = _send_istream;
- ostream = _o_stream_create(&fstream->ostream, pool);
+ ostream = _o_stream_create(&fstream->ostream);
offset = lseek(fd, 0, SEEK_CUR);
if (offset >= 0) {
diff --git a/src/lib/ostream-internal.h b/src/lib/ostream-internal.h
index 30a6e8b..2c3ee09 100644
--- a/src/lib/ostream-internal.h
+++ b/src/lib/ostream-internal.h
@@ -26,6 +26,6 @@ struct _ostream {
void *context;
};
-struct ostream *_o_stream_create(struct _ostream *_stream, pool_t pool);
+struct ostream *_o_stream_create(struct _ostream *_stream);
#endif
diff --git a/src/lib/ostream.c b/src/lib/ostream.c
index c7a3750..8d686b4 100644
--- a/src/lib/ostream.c
+++ b/src/lib/ostream.c
@@ -157,10 +157,10 @@ off_t o_stream_send_istream(struct ostream *outstream,
return ret;
}
-struct ostream *_o_stream_create(struct _ostream *_stream, pool_t pool)
+struct ostream *_o_stream_create(struct _ostream *_stream)
{
_stream->ostream.real_stream = _stream;
- _io_stream_init(pool, &_stream->iostream);
+ _io_stream_init(&_stream->iostream);
return &_stream->ostream;
}
diff --git a/src/lib/ostream.h b/src/lib/ostream.h
index b81dca9..4917d90 100644
--- a/src/lib/ostream.h
+++ b/src/lib/ostream.h
@@ -24,8 +24,7 @@ typedef int stream_flush_callback_t(void *context);
/* Create new output stream from given file descriptor.
If max_buffer_size is 0, an "optimal" buffer size is used (max 128kB). */
struct ostream *
-o_stream_create_file(int fd, pool_t pool, size_t max_buffer_size,
- bool autoclose_fd);
+o_stream_create_file(int fd, size_t max_buffer_size, bool autoclose_fd);
/* o_stream_close() + o_stream_unref() */
void o_stream_destroy(struct ostream **stream);
diff --git a/src/lib/unichar.c b/src/lib/unichar.c
index fe54970..ea7ce80 100644
--- a/src/lib/unichar.c
+++ b/src/lib/unichar.c
@@ -2,8 +2,14 @@
#include "lib.h"
#include "buffer.h"
+#include "bsearch-insert-pos.h"
#include "unichar.h"
+#include "unicodemap.c"
+
+#define HANGUL_FIRST 0xac00
+#define HANGUL_LAST 0xd7a3
+
static const uint8_t utf8_non1_bytes[256 - 192 - 2] = {
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,6,6,1,1
@@ -164,3 +170,118 @@ unsigned int uni_utf8_strlen_n(const void *_input, size_t size)
}
return len;
}
+
+static bool uint16_find(const uint16_t *data, unsigned int count,
+ uint16_t value, unsigned int *idx_r)
+{
+ BINARY_NUMBER_SEARCH(data, count, value, idx_r);
+}
+
+static bool uint32_find(const uint32_t *data, unsigned int count,
+ uint32_t value, unsigned int *idx_r)
+{
+ BINARY_NUMBER_SEARCH(data, count, value, idx_r);
+}
+
+unichar_t uni_ucs4_to_titlecase(unichar_t chr)
+{
+ unsigned int idx;
+
+ if (chr <= 0xffff) {
+ if (!uint16_find(titlecase16_keys, N_ELEMENTS(titlecase16_keys),
+ chr, &idx))
+ return chr;
+ else
+ return titlecase16_values[idx];
+ } else {
+ if (!uint32_find(titlecase32_keys, N_ELEMENTS(titlecase32_keys),
+ chr, &idx))
+ return chr;
+ else
+ return titlecase32_values[idx];
+ }
+}
+
+static bool uni_ucs4_decompose_uni(unichar_t *chr)
+{
+ unsigned int idx;
+
+ if (*chr <= 0xffff) {
+ if (!uint16_find(uni16_decomp_keys,
+ N_ELEMENTS(uni16_decomp_keys),
+ *chr, &idx))
+ return FALSE;
+ *chr = uni16_decomp_values[idx];
+ } else {
+ if (!uint32_find(uni32_decomp_keys,
+ N_ELEMENTS(uni32_decomp_keys),
+ *chr, &idx))
+ return FALSE;
+ *chr = uni32_decomp_values[idx];
+ }
+ return TRUE;
+}
+
+static void uni_ucs4_decompose_hangul_utf8(unichar_t chr, buffer_t *output)
+{
+#define SBase HANGUL_FIRST
+#define LBase 0x1100
+#define VBase 0x1161
+#define TBase 0x11A7
+#define LCount 19
+#define VCount 21
+#define TCount 28
+#define NCount (VCount * TCount)
+ unsigned int SIndex = chr - SBase;
+ unichar_t L = LBase + SIndex / NCount;
+ unichar_t V = VBase + (SIndex % NCount) / TCount;
+ unichar_t T = TBase + SIndex % TCount;
+
+ uni_ucs4_to_utf8_c(L, output);
+ uni_ucs4_to_utf8_c(V, output);
+ if (T != TBase) uni_ucs4_to_utf8_c(T, output);
+}
+
+static bool uni_ucs4_decompose_multi_utf8(unichar_t chr, buffer_t *output)
+{
+ const uint16_t *value;
+ unsigned int idx;
+
+ if (chr > 0xffff)
+ return FALSE;
+
+ if (!uint16_find(multidecomp_keys, N_ELEMENTS(multidecomp_keys),
+ chr, &idx))
+ return FALSE;
+
+ value = &multidecomp_values[multidecomp_offsets[idx]];
+ for (; *value != 0; value++)
+ uni_ucs4_to_utf8_c(*value, output);
+ return TRUE;
+}
+
+int uni_utf8_to_decomposed_titlecase(const void *_input, size_t max_len,
+ buffer_t *output)
+{
+ const unsigned char *input = _input;
+ unsigned int bytes;
+ unichar_t chr;
+
+ while (max_len > 0 && *input != '\0') {
+ if (uni_utf8_get_char_n(input, max_len, &chr) <= 0) {
+ /* invalid input */
+ return -1;
+ }
+ bytes = uni_utf8_char_bytes(*input);
+ input += bytes;
+ max_len -= bytes;
+
+ chr = uni_ucs4_to_titlecase(chr);
+ if (chr >= HANGUL_FIRST && chr <= HANGUL_LAST)
+ uni_ucs4_decompose_hangul_utf8(chr, output);
+ else if (uni_ucs4_decompose_uni(&chr) ||
+ !uni_ucs4_decompose_multi_utf8(chr, output))
+ uni_ucs4_to_utf8_c(chr, output);
+ }
+ return 0;
+}
diff --git a/src/lib/unichar.h b/src/lib/unichar.h
index 78b8af5..412f061 100644
--- a/src/lib/unichar.h
+++ b/src/lib/unichar.h
@@ -31,4 +31,13 @@ static inline unsigned int uni_utf8_char_bytes(char chr)
return uni_utf8_non1_bytes[(uint8_t)chr - (192 + 2)];
}
+/* Return given character in titlecase. */
+unichar_t uni_ucs4_to_titlecase(unichar_t chr);
+
+/* Convert UTF-8 input to titlecase and decompose the titlecase characters to
+ output buffer. Returns 0 if ok, -1 if input was invalid. This generates
+ output that's compatible with i;unicode-casemap comparator. */
+int uni_utf8_to_decomposed_titlecase(const void *input, size_t max_len,
+ buffer_t *output);
+
#endif
diff --git a/src/lib/unicodemap.pl b/src/lib/unicodemap.pl
new file mode 100755
index 0000000..93bdfb3
--- /dev/null
+++ b/src/lib/unicodemap.pl
@@ -0,0 +1,134 @@
+#!/usr/bin/env perl
+use strict;
+
+my (@titlecase16_keys, @titlecase16_values);
+my (@titlecase32_keys, @titlecase32_values);
+my (@uni16_decomp_keys, @uni16_decomp_values);
+my (@uni32_decomp_keys, @uni32_decomp_values);
+my (@multidecomp_keys, @multidecomp_offsets, @multidecomp_values);
+while (<>) {
+ chomp $_;
+ my @arr = split(";");
+ my $code = eval("0x".$arr[0]);
+ my $decomp = $arr[5];
+ my $titlecode = $arr[14];
+
+ if ($titlecode ne "") {
+ # titlecase mapping
+ my $value = eval("0x$titlecode");
+ if ($value == $code) {
+ # the same character, ignore
+ } elsif ($code <= 0xffff && $value <= 0xffff) {
+ push @titlecase16_keys, $code;
+ push @titlecase16_values, $value;
+ } else {
+ push @titlecase32_keys, $code;
+ push @titlecase32_values, $value;
+ }
+ } elsif ($decomp =~ /\<[^>]*> (.+)/) {
+ # decompositions
+ my $decomp_codes = $1;
+ if ($decomp_codes =~ /^([0-9A-Z]*)$/i) {
+ # unicharacter decomposition. use separate lists for this
+ my $value = eval("0x$1");
+ if ($value > 0xffff) {
+ print STDERR "We've assumed decomposition codes are max. 16bit\n";
+ exit;
+ }
+ if ($code <= 0xffff) {
+ push @uni16_decomp_keys, $code;
+ push @uni16_decomp_values, $value;
+ } else {
+ push @uni32_decomp_keys, $code;
+ push @uni32_decomp_values, $value;
+ }
+ } else {
+ # multicharacter decomposition.
+ if ($code > 0xffff) {
+ print STDERR "We've assumed multi-decomposition key codes are max. 16bit\n";
+ exit;
+ }
+
+ push @multidecomp_keys, $code;
+ push @multidecomp_offsets, scalar(@multidecomp_values);
+
+ foreach my $dcode (split(" ", $decomp_codes)) {
+ my $value = eval("0x$dcode");
+ if ($value > 0xffff) {
+ print STDERR "We've assumed decomposition codes are max. 16bit\n";
+ exit;
+ }
+ push @multidecomp_values, $value;
+ }
+ push @multidecomp_values, 0;
+ }
+ }
+}
+
+sub print_list {
+ my @list = @{$_[0]};
+
+ my $last = $#list;
+ my $n = 0;
+ foreach my $key (@list) {
+ printf("0x%04x", $key);
+ last if ($n == $last);
+ print ",";
+
+ $n++;
+ if (($n % 8) == 0) {
+ print "\n\t";
+ } else {
+ print " ";
+ }
+ }
+}
+
+print "/* This file is automatically generated by unicodemap.pl from UnicodeData.txt
+
+ NOTE: decompositions for characters having titlecase characters
+ are not included, because we first translate everything to titlecase */\n";
+
+print "static uint16_t titlecase16_keys[] = {\n\t";
+print_list(\@titlecase16_keys);
+print "\n};\n";
+
+print "static uint16_t titlecase16_values[] = {\n\t";
+print_list(\@titlecase16_values);
+print "\n};\n";
+
+print "static uint32_t titlecase32_keys[] = {\n\t";
+print_list(\@titlecase32_keys);
+print "\n};\n";
+
+print "static uint32_t titlecase32_values[] = {\n\t";
+print_list(\@titlecase32_values);
+print "\n};\n";
+
+print "static uint16_t uni16_decomp_keys[] = {\n\t";
+print_list(\@uni16_decomp_keys);
+print "\n};\n";
+
+print "static uint16_t uni16_decomp_values[] = {\n\t";
+print_list(\@uni16_decomp_values);
+print "\n};\n";
+
+print "static uint32_t uni32_decomp_keys[] = {\n\t";
+print_list(\@uni32_decomp_keys);
+print "\n};\n";
+
+print "static uint16_t uni32_decomp_values[] = {\n\t";
+print_list(\@uni32_decomp_values);
+print "\n};\n";
+
+print "static uint16_t multidecomp_keys[] = {\n\t";
+print_list(\@multidecomp_keys);
+print "\n};\n";
+
+print "static uint16_t multidecomp_offsets[] = {\n\t";
+print_list(\@multidecomp_offsets);
+print "\n};\n";
+
+print "static uint16_t multidecomp_values[] = {\n\t";
+print_list(\@multidecomp_values);
+print "\n};\n";
diff --git a/src/login-common/login-proxy.c b/src/login-common/login-proxy.c
index b7e3420..22d3fdb 100644
--- a/src/login-common/login-proxy.c
+++ b/src/login-common/login-proxy.c
@@ -121,11 +121,10 @@ static void proxy_wait_connect(struct login_proxy *proxy)
/* connect successful */
proxy->server_input =
- i_stream_create_file(proxy->server_fd, default_pool,
- MAX_PROXY_INPUT_SIZE, FALSE);
+ i_stream_create_file(proxy->server_fd, MAX_PROXY_INPUT_SIZE,
+ FALSE);
proxy->server_output =
- o_stream_create_file(proxy->server_fd, default_pool,
- (size_t)-1, FALSE);
+ o_stream_create_file(proxy->server_fd, (size_t)-1, FALSE);
io_remove(&proxy->server_io);
proxy->server_io =
diff --git a/src/login-common/master.c b/src/login-common/master.c
index 9a0af95..f2ae8dd 100644
--- a/src/login-common/master.c
+++ b/src/login-common/master.c
@@ -165,7 +165,7 @@ static void master_read_env(int fd)
env_clean();
/* read environment variable lines until empty line comes */
- input = i_stream_create_file(fd, default_pool, 8192, FALSE);
+ input = i_stream_create_file(fd, 8192, FALSE);
do {
switch (i_stream_read(input)) {
case -1:
diff --git a/src/master/auth-process.c b/src/master/auth-process.c
index adeba9a..faa35b5 100644
--- a/src/master/auth-process.c
+++ b/src/master/auth-process.c
@@ -297,10 +297,8 @@ auth_process_new(pid_t pid, int fd, struct auth_process_group *group)
p->pid = pid;
p->fd = fd;
p->io = io_add(fd, IO_READ, auth_process_input, p);
- p->input = i_stream_create_file(fd, default_pool,
- MAX_INBUF_SIZE, FALSE);
- p->output = o_stream_create_file(fd, default_pool, MAX_OUTBUF_SIZE,
- FALSE);
+ p->input = i_stream_create_file(fd, MAX_INBUF_SIZE, FALSE);
+ p->output = o_stream_create_file(fd, MAX_OUTBUF_SIZE, FALSE);
p->requests = hash_create(default_pool, default_pool, 0, NULL, NULL);
group->process_count++;
diff --git a/src/master/log.c b/src/master/log.c
index a43b72c..9ecfb8f 100644
--- a/src/master/log.c
+++ b/src/master/log.c
@@ -179,7 +179,7 @@ int log_create_pipe(struct log_io **log_r, unsigned int max_lines_per_sec)
log_io = i_new(struct log_io, 1);
log_io->refcount = 1;
- log_io->stream = i_stream_create_file(fd[0], default_pool, 1024, TRUE);
+ log_io->stream = i_stream_create_file(fd[0], 1024, TRUE);
log_io->max_lines_per_sec =
max_lines_per_sec != 0 ? max_lines_per_sec : (unsigned int)-1;
diff --git a/src/master/login-process.c b/src/master/login-process.c
index 2b33625..46e0d5f 100644
--- a/src/master/login-process.c
+++ b/src/master/login-process.c
@@ -449,7 +449,7 @@ login_process_new(struct login_group *group, pid_t pid, int fd)
p->pid = pid;
p->fd = fd;
p->io = io_add(fd, IO_READ, login_process_input, p);
- p->output = o_stream_create_file(fd, default_pool,
+ p->output = o_stream_create_file(fd,
sizeof(struct master_login_reply)*10,
FALSE);
child_process_add(pid, &p->process);
diff --git a/src/master/mail-process.c b/src/master/mail-process.c
index e770314..3a695ce 100644
--- a/src/master/mail-process.c
+++ b/src/master/mail-process.c
@@ -124,6 +124,7 @@ static bool validate_uid_gid(struct settings *set, uid_t uid, gid_t gid,
i_error("Logins with login process UID %s (user %s) "
"not permitted (see login_user in config file).",
dec2str(uid), user);
+ return FALSE;
}
if (uid < (uid_t)set->first_valid_uid ||
diff --git a/src/plugins/acl/acl-backend-vfile-acllist.c b/src/plugins/acl/acl-backend-vfile-acllist.c
index 1b7f64b..41b0110 100644
--- a/src/plugins/acl/acl-backend-vfile-acllist.c
+++ b/src/plugins/acl/acl-backend-vfile-acllist.c
@@ -83,7 +83,7 @@ static int acl_backend_vfile_acllist_read(struct acl_backend_vfile *backend)
backend->acllist_mtime = st.st_mtime;
acllist_clear(backend, st.st_size);
- input = i_stream_create_file(fd, default_pool, (size_t)-1, FALSE);
+ input = i_stream_create_file(fd, (size_t)-1, FALSE);
while ((line = i_stream_read_next_line(input)) != NULL) {
acllist.mtime = 0;
for (p = line; *p >= '0' && *p <= '9'; p++)
@@ -208,7 +208,7 @@ int acl_backend_vfile_acllist_rebuild(struct acl_backend_vfile *backend)
fd = safe_mkstemp(path, mode, uid, gid);
if (fd == -1)
return -1;
- output = o_stream_create_file(fd, default_pool, 0, FALSE);
+ output = o_stream_create_file(fd, 0, FALSE);
ret = 0;
acllist_clear(backend, 0);
diff --git a/src/plugins/acl/acl-backend-vfile.c b/src/plugins/acl/acl-backend-vfile.c
index c1be2e3..2c784a7 100644
--- a/src/plugins/acl/acl-backend-vfile.c
+++ b/src/plugins/acl/acl-backend-vfile.c
@@ -345,7 +345,7 @@ acl_backend_vfile_read(struct acl_object_vfile *aclobj, const char *path,
if (aclobj->aclobj.backend->debug)
i_info("acl vfile: reading file %s", path);
- input = i_stream_create_file(fd, default_pool, 4096, FALSE);
+ input = i_stream_create_file(fd, 4096, FALSE);
if (!array_is_created(&aclobj->rights)) {
aclobj->rights_pool =
diff --git a/src/plugins/expire/auth-client.c b/src/plugins/expire/auth-client.c
index 9011564..9511888 100644
--- a/src/plugins/expire/auth-client.c
+++ b/src/plugins/expire/auth-client.c
@@ -46,10 +46,8 @@ static int auth_connection_connect(struct auth_connection *conn)
}
conn->fd = fd;
- conn->input =
- i_stream_create_file(fd, default_pool, MAX_INBUF_SIZE, FALSE);
- conn->output =
- o_stream_create_file(fd, default_pool, MAX_OUTBUF_SIZE, FALSE);
+ conn->input = i_stream_create_file(fd, MAX_INBUF_SIZE, FALSE);
+ conn->output = o_stream_create_file(fd, MAX_OUTBUF_SIZE, FALSE);
conn->io = io_add(fd, IO_READ, auth_input, conn);
o_stream_send_str(conn->output, "VERSION\t1\t0\n");
diff --git a/src/plugins/fts-squat/squat-test.c b/src/plugins/fts-squat/squat-test.c
index 61bed52..f520945 100644
--- a/src/plugins/fts-squat/squat-test.c
+++ b/src/plugins/fts-squat/squat-test.c
@@ -59,7 +59,7 @@ int main(int argc __attr_unused__, char *argv[])
return 1;
build_ctx = squat_trie_build_init(trie, &last_uid);
- input = i_stream_create_file(fd, default_pool, 0, FALSE);
+ input = i_stream_create_file(fd, 0, FALSE);
while ((line = i_stream_read_next_line(input)) != NULL) {
if (last != input->v_offset/(1024*100)) {
fprintf(stderr, "\r%ukB", (unsigned)(input->v_offset/1024));
diff --git a/src/plugins/fts-squat/squat-trie.c b/src/plugins/fts-squat/squat-trie.c
index 7c49497..0a4f466 100644
--- a/src/plugins/fts-squat/squat-trie.c
+++ b/src/plugins/fts-squat/squat-trie.c
@@ -1474,7 +1474,7 @@ trie_nodes_write(struct squat_trie_build_context *ctx, uint32_t *uidvalidity_r)
return -1;
}
- ctx->output = o_stream_create_file(trie->fd, default_pool, 0, FALSE);
+ ctx->output = o_stream_create_file(trie->fd, 0, FALSE);
o_stream_cork(ctx->output);
if (hdr.used_file_size == 0) {
o_stream_send(ctx->output, &hdr, sizeof(hdr));
@@ -1799,7 +1799,7 @@ static int squat_trie_compress_init(struct squat_trie_compress_context *ctx,
}
ctx->trie = trie;
- ctx->output = o_stream_create_file(ctx->fd, default_pool, 0, FALSE);
+ ctx->output = o_stream_create_file(ctx->fd, 0, FALSE);
ctx->node_count = trie->hdr->node_count;
/* write a dummy header first */
diff --git a/src/plugins/fts-squat/squat-uidlist.c b/src/plugins/fts-squat/squat-uidlist.c
index 6d4d56a..50e9fb1 100644
--- a/src/plugins/fts-squat/squat-uidlist.c
+++ b/src/plugins/fts-squat/squat-uidlist.c
@@ -580,8 +580,7 @@ static int squat_uidlist_write_init(struct squat_uidlist *uidlist)
return -1;
}
- uidlist->output = o_stream_create_file(uidlist->fd, default_pool,
- 0, FALSE);
+ uidlist->output = o_stream_create_file(uidlist->fd, 0, FALSE);
o_stream_cork(uidlist->output);
if (uidlist->hdr.used_file_size < sizeof(uidlist->hdr)) {
/* creating a new file, write a dummy header */
@@ -761,7 +760,7 @@ squat_uidlist_compress_begin(struct squat_uidlist *uidlist,
ctx->failed = TRUE;
i_error("open(%s) failed: %m", ctx->tmp_path);
} else {
- ctx->output = o_stream_create_file(fd, default_pool, 0, TRUE);
+ ctx->output = o_stream_create_file(fd, 0, TRUE);
o_stream_send(ctx->output, &ctx->hdr, sizeof(ctx->hdr));
}
diff --git a/src/plugins/fts/fts-storage.c b/src/plugins/fts/fts-storage.c
index 3cd1fab..a0f62e1 100644
--- a/src/plugins/fts/fts-storage.c
+++ b/src/plugins/fts/fts-storage.c
@@ -176,7 +176,7 @@ static int fts_build_mail(struct fts_storage_build_context *ctx)
parser = message_parser_init(pool_datastack_create(), input,
MESSAGE_HEADER_PARSER_FLAG_CLEAN_ONELINE,
0);
- decoder = message_decoder_init_ucase();
+ decoder = message_decoder_init(TRUE);
for (;;) {
ret = message_parser_parse_next_block(parser, &raw_block);
i_assert(ret != 0);
diff --git a/src/plugins/trash/trash-plugin.c b/src/plugins/trash/trash-plugin.c
index a5dcd02..e1c15ba 100644
--- a/src/plugins/trash/trash-plugin.c
+++ b/src/plugins/trash/trash-plugin.c
@@ -262,7 +262,7 @@ static int read_configuration(const char *path)
p_clear(config_pool);
p_array_init(&trash_boxes, config_pool, INIT_TRASH_MAILBOX_COUNT);
- input = i_stream_create_file(fd, default_pool, (size_t)-1, FALSE);
+ input = i_stream_create_file(fd, (size_t)-1, FALSE);
while ((line = i_stream_read_next_line(input)) != NULL) {
/* <priority> <mailbox name> */
name = strchr(line, ' ');
diff --git a/src/plugins/zlib/istream-zlib.c b/src/plugins/zlib/istream-zlib.c
index 06b7b75..c93bca7 100644
--- a/src/plugins/zlib/istream-zlib.c
+++ b/src/plugins/zlib/istream-zlib.c
@@ -35,7 +35,7 @@ static void _destroy(struct _iostream *stream __attr_unused__)
{
struct _istream *_stream = (struct _istream *) stream;
- p_free(_stream->iostream.pool, _stream->w_buffer);
+ i_free(_stream->w_buffer);
}
static ssize_t _read(struct _istream *stream)
@@ -193,12 +193,12 @@ static void _sync(struct _istream *stream)
zstream->cached_size = (uoff_t)-1;
}
-struct istream *i_stream_create_zlib(int fd, pool_t pool)
+struct istream *i_stream_create_zlib(int fd)
{
struct zlib_istream *zstream;
struct stat st;
- zstream = p_new(pool, struct zlib_istream, 1);
+ zstream = i_new(struct zlib_istream, 1);
zstream->fd = fd;
zstream->file = gzdopen(fd, "r");
zstream->cached_size = (uoff_t)-1;
@@ -218,5 +218,5 @@ struct istream *i_stream_create_zlib(int fd, pool_t pool)
zstream->istream.istream.seekable = TRUE;
}
- return _i_stream_create(&zstream->istream, pool, fd, 0);
+ return _i_stream_create(&zstream->istream, fd, 0);
}
diff --git a/src/plugins/zlib/istream-zlib.h b/src/plugins/zlib/istream-zlib.h
index 88b3735..697c2ce 100644
--- a/src/plugins/zlib/istream-zlib.h
+++ b/src/plugins/zlib/istream-zlib.h
@@ -1,6 +1,6 @@
#ifndef __ISTREAM_ZLIB_H
#define __ISTREAM_ZLIB_H
-struct istream *i_stream_create_zlib(int fd, pool_t pool);
+struct istream *i_stream_create_zlib(int fd);
#endif
diff --git a/src/plugins/zlib/zlib-plugin.c b/src/plugins/zlib/zlib-plugin.c
index 97cab54..549dfc4 100644
--- a/src/plugins/zlib/zlib-plugin.c
+++ b/src/plugins/zlib/zlib-plugin.c
@@ -41,10 +41,8 @@ zlib_mailbox_open(struct mail_storage *storage, const char *name,
int fd;
fd = open(path, O_RDONLY);
- if (fd != -1) {
- input = zlib_input =
- i_stream_create_zlib(fd, default_pool);
- }
+ if (fd != -1)
+ input = zlib_input = i_stream_create_zlib(fd);
}
}
diff --git a/src/pop3-login/client.c b/src/pop3-login/client.c
index 040b6b9..3f5dc1c 100644
--- a/src/pop3-login/client.c
+++ b/src/pop3-login/client.c
@@ -65,10 +65,8 @@ static void client_set_title(struct pop3_client *client)
static void client_open_streams(struct pop3_client *client, int fd)
{
- client->input = i_stream_create_file(fd, default_pool,
- MAX_INBUF_SIZE, FALSE);
- client->output = o_stream_create_file(fd, default_pool,
- MAX_OUTBUF_SIZE, FALSE);
+ client->input = i_stream_create_file(fd, MAX_INBUF_SIZE, FALSE);
+ client->output = o_stream_create_file(fd, MAX_OUTBUF_SIZE, FALSE);
}
static void client_start_tls(struct pop3_client *client)
diff --git a/src/pop3/client.c b/src/pop3/client.c
index 10e96cb..3efc9e9 100644
--- a/src/pop3/client.c
+++ b/src/pop3/client.c
@@ -140,10 +140,8 @@ struct client *client_create(int fd_in, int fd_out,
client = i_new(struct client, 1);
client->fd_in = fd_in;
client->fd_out = fd_out;
- client->input = i_stream_create_file(fd_in, default_pool,
- MAX_INBUF_SIZE, FALSE);
- client->output = o_stream_create_file(fd_out, default_pool,
- (size_t)-1, FALSE);
+ client->input = i_stream_create_file(fd_in, MAX_INBUF_SIZE, FALSE);
+ client->output = o_stream_create_file(fd_out, (size_t)-1, FALSE);
o_stream_set_flush_callback(client->output, client_output, client);
client->io = io_add(fd_in, IO_READ, client_input, client);
diff --git a/src/util/rawlog.c b/src/util/rawlog.c
index ae89533..097f3f4 100644
--- a/src/util/rawlog.c
+++ b/src/util/rawlog.c
@@ -240,19 +240,16 @@ rawlog_proxy_create(int client_in_fd, int client_out_fd, int server_fd,
proxy = i_new(struct rawlog_proxy, 1);
proxy->server_fd = server_fd;
proxy->server_input =
- i_stream_create_file(server_fd, default_pool,
- MAX_PROXY_INPUT_SIZE, FALSE);
+ i_stream_create_file(server_fd, MAX_PROXY_INPUT_SIZE, FALSE);
proxy->server_output =
- o_stream_create_file(server_fd, default_pool,
- (size_t)-1, FALSE);
+ o_stream_create_file(server_fd, (size_t)-1, FALSE);
proxy->server_io = io_add(server_fd, IO_READ, server_input, proxy);
o_stream_set_flush_callback(proxy->server_output, server_output, proxy);
proxy->client_in_fd = client_in_fd;
proxy->client_out_fd = client_out_fd;
proxy->client_output =
- o_stream_create_file(client_out_fd, default_pool,
- (size_t)-1, FALSE);
+ o_stream_create_file(client_out_fd, (size_t)-1, FALSE);
proxy->client_io = io_add(proxy->client_in_fd, IO_READ,
client_input, proxy);
o_stream_set_flush_callback(proxy->client_output, client_output, proxy);