[Dovecot] Implementation of editheaders in dovecot
Hello.
I wrote the hook function for deliver. I want to add support of
editheaders in the plug-in for dovecot. For this purpose I wrote the
function rarules_get_stream. Remover of headrs works properly, but
adding does not work. I took Timo Sirainen's advice from http://markmail.org/message/skb6arnll5gaopdr
. Do I use a correct way of creation of a message?
I give backtrace and a part of my code.
Thanks, Konstantin
uname -a:
FreeBSD bsdman.virtualworld.com 6.4-RELEASE FreeBSD 6.4-RELEASE #0:
Wed Nov 26 11:43:51 UTC 2008 root@dessler.cse.buffalo.edu:/usr/obj/
usr/src/sys/GENERIC i386
dovecot --version: 1.1.11
build: $ ./configure --localstatedir=/var --with-statedir=/var/db/dovecot -- without-shadow --enable-debug --with-ioloop=kqueue --disable-ipv6 -- with-gssapi --without-vpopmail --without-ldap --without-pgsql --with- mysql --without-sqlite --prefix=/usr/local --mandir=/usr/local/man -- infodir=/usr/local/info/ --build=i386-portbld-freebsd6.4
patches: in freebsd ports
(gdb) bt
#0 0x282f3a01 in memcpy () from /lib/libc.so.6
#1 0x080df555 in i_stream_concat_read_next (cstream=0x814aa00) at
istream-concat.c:79
#2 0x080df784 in i_stream_concat_read (stream=0x814aa00) at istream-
concat.c:136
#3 0x080de659 in i_stream_read (stream=0x814aa28) at istream.c:78
#4 0x080cd99a in i_stream_header_filter_read (stream=0x814e400) at
istream-header-filter.c:322
#5 0x080de659 in i_stream_read (stream=0x814e428) at istream.c:78
#6 0x080dff26 in i_stream_crlf_read_common (cstream=0x814ad00) at
istream-crlf.c:41
#7 0x080e01b3 in i_stream_crlf_read_lf (stream=0x814ad00) at istream-
crlf.c:103
#8 0x080de659 in i_stream_read (stream=0x814ad28) at istream.c:78
#9 0x080e2611 in i_stream_tee_read (stream=0x814ae00) at istream-
tee.c:122
#10 0x080de659 in i_stream_read (stream=0x814ae28) at istream.c:78
#11 0x080deea3 in i_stream_read_data (stream=0x814ae28,
data_r=0xbfbfea88, size_r=0xbfbfea8c, threshold=1) at istream.c:322
#12 0x080d1744 in message_parser_read_more (ctx=0x8156468,
block_r=0xbfbfea80, full_r=0xbfbfea27) at message-parser.c:117
#13 0x080d20ac in parse_next_body_to_eof (ctx=0x8156468,
block_r=0xbfbfea80) at message-parser.c:411
#14 0x080d2ccf in message_parser_parse_next_block (ctx=0x8156468,
block_r=0xbfbfea80) at message-parser.c:765
#15 0x080931d9 in index_mail_cache_parse_continue (_mail=0x8150060) at
index-mail.c:1316
#16 0x0807838d in mbox_save_continue (_ctx=0x811bb00) at mbox-save.c:582
#17 0x080a05a8 in mailbox_save_continue (ctx=0x811bb00) at mail-
storage.c:740
#18 0x0809d9df in mail_storage_copy (t=0x811b980, mail=0x8141860,
flags=0, keywords=0x0, dest_mail=0x0) at mail-copy.c:33
#19 0x080a0632 in mailbox_copy (t=0x811b980, mail=0x8141860, flags=0,
keywords=0x0, dest_mail=0x0) at mail-storage.c:763
#20 0x0805960d in deliver_save (namespaces=0x8121c68,
storage_r=0xbfbfee14, mailbox=0x811a370 "Draft", mail=0x8141860,
flags=0, keywords=0x0) at deliver.c:234
#21 0x2831fe8f in store_in (arg=0x811a370 "Draft", md=0xbfbfed00) at /
home/pitman/work/rarules/src/actions.c:220
#22 0x2831f759 in rarules_execute_action
(type=RARULES_ACTION_STORE_IN, arg=0x811a370 "Draft", md=0xbfbfed00)
at /home/pitman/work/rarules/src/actions.c:57
#23 0x2831e70d in execute_actions (action=0x811a360, md=0xbfbfed00)
at /home/pitman/work/rarules/src/rarules.c:98
#24 0x2831e692 in apply_rules (rule=0x811a320, md=0xbfbfed00) at /home/
pitman/work/rarules/src/rarules.c:80
#25 0x2831e56a in rarules_main (namespaces=0x8121c68,
storage_r=0xbfbfee14, mail=0x8141860, db=0x8121000,
destaddr=0xbfbfef62 "pitman@virtualworld.com", username=0x8113525
"pitman@virtualworld.com", mailbox=0x80f2a19 "INBOX")
at /home/pitman/work/rarules/src/rarules.c:52
#26 0x2831da37 in rarules_deliver_mail (namespaces=0x8121c68,
storage_r=0xbfbfee14, mail=0x8141860,
destaddr=0xbfbfef62 "pitman@virtualworld.com", mailbox=0x80f2a19
"INBOX")
at /home/pitman/work/rarules/src/rarules_plugin.c:126
#27 0x0805b69a in main (argc=3, argv=0xbfbfeeac) at deliver.c:1084
(gdb) f 1
#1 0x080df555 in i_stream_concat_read_next (cstream=0x814aa00) at
istream-concat.c:79
79 memcpy(cstream->istream.w_buffer, data, data_size);
(gdb) p data $4 = (const unsigned char *) 0x15 <Address 0x15 out of bounds> (gdb) p data_size $5 = 1
/////////////////////////////////////////My
code/////////////////////////////////////////////////////////
static int rarules_get_stream(struct mail * mail, struct message_size
hdr_size, struct message_size * body_size, struct istream ** stream_r) { struct rarules_mail * ra_mail = RARULES_MAIL_CONTEXT(mail); struct istream * stream = NULL; struct istream ** chunks = NULL; const unsigned int max_chunks = 4;
unsigned int i = 0; unsigned int cnt = 0; unsigned int exclude_cnt = 0; unsigned int include_cnt = 0;
int ret = 0;
#if 1 {/* Test code */ const char * str = "Subject"; const char * str2 = "X-DSPAM: test value\n\n";
array_append(&ra_mail->exclude_headers, &str, 1);
array_append(&ra_mail->include_headers, &str2, 1);
}
#endif
DPRINT("Standard get_stream for mail storage format");
ret = ra_mail->module_ctx.super.get_stream(mail, hdr_size, body_size,
&stream);
include_cnt = array_count(&ra_mail->include_headers);
exclude_cnt = array_count(&ra_mail->exclude_headers);
if ((!exclude_cnt && !include_cnt) || ret < 0) {
*stream_r = stream;
return ret;
}
DPRINT("Create message from chunks with new headers and skip excluded
headers");
chunks = t_new(struct istream *, max_chunks);
chunks[cnt++] = header_filter(stream, &ra_mail->exclude_headers,
exclude_cnt);
if (include_cnt) {
chunks[cnt++] = create_header_stream(&ra_mail->include_headers,
include_cnt);
}
chunks[cnt++] = create_stream_for_msgbody(stream);
chunks[cnt++] = NULL;
*stream_r = i_stream_create_concat(chunks);
DPRINT("Cleanup");
array_clear(&ra_mail->include_headers);
array_clear(&ra_mail->exclude_headers);
for (i = 0; chunks[i] != NULL; ++i) { i_stream_unref(&chunks[i]); }
i_stream_unref(&stream);
DPRINTF("Func `%s' executed", __FUNCTION__);
return ret;
}
inline static struct istream * create_stream_for_msgbody(struct istream * stream) { struct istream * tmp = stream; struct message_size hdr_size; struct message_size body_size;
DPRINTF("Func `%s' called", __FUNCTION__);
message_get_body_size(stream, &body_size, NULL);
message_get_header_size(stream, &hdr_size, NULL);
i_stream_seek(stream, hdr_size.physical_size);
stream = i_stream_create_limit(stream, body_size.physical_size);
i_stream_unref(&tmp);
return stream;
}
inline static struct istream *
header_filter(struct istream * stream, ARRAY_TYPE(const_string) *
headers_arr,
unsigned int count)
{
const char * const * headers = NULL;
DPRINTF("Func `%s' called", __FUNCTION__);
if (count) { headers = (const char **)array_idx(headers_arr, 0); }
return i_stream_create_header_filter(stream,
HEADER_FILTER_EXCLUDE |
HEADER_FILTER_NO_CR |
HEADER_FILTER_HIDE_BODY,
headers,
count,
null_header_filter_callback,
NULL);
}
inline static struct istream *
create_header_stream(ARRAY_TYPE(const_string) * headers_arr, unsigned
int count)
{
unsigned int i = 0;
struct istream * result = NULL;
struct istream ** chunks = NULL;
const char * const * headers = NULL;
DPRINTF("Func `%s' called", __FUNCTION__);
i_assert(count != 0);
headers = (const char **)array_idx(headers_arr, 0);
DPRINT("Create streams for new included headers from headers");
chunks = t_new(struct istream *, count + 1);
for (i = 0; i < count; ++i) {
struct istream * tmp = NULL;
tmp = i_stream_create_from_data(headers[i], strlen(headers[i]));
chunks[i] = i_stream_create_lf(tmp);
i_stream_unref(&tmp);
}
chunks[count] = NULL;
result = i_stream_create_concat(chunks);
for (i = 0; chunks[i] != NULL; ++i) { i_stream_unref(&chunks[i]); }
return result;
}
I fixed the problem and I created another :-)
I removed header "Subject" and added "X-DSPAM: test value\n\n". Now,
problem is message_get_header_size in create_stream_for_msgbody. It
returns 0 :-( I don't know how to extract message body properly. Help
me to understand usage of struct message_size.
Result: . fetch 1 rfc822.header
- 1 FETCH (RFC822.HEADER {625}
Return-Path: <pupkin@virtualworld.com>
Delivered-To: pitman@virtualworld.com
Received: from localhost.virtualworld.com (localhost [127.0.0.1])
by bsdman.virtualworld.com (Postfix) with ESMTP id 8AB84254
for <pitman@virtualworld.com>; Thu, 2 Apr 2009 05:07:51
+0400 (MSD) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: pupkin@virtualworld.com Reply-to: Konstantin@bsdman.virtualworld.com, Lepa@bsdman.virtualworld.com To: pitman@virtualworld.com Message-Id: <20090402010751.8AB84254@bsdman.virtualworld.com> Date: Thu, 2 Apr 2009 05:07:51 +0400 (MSD)
) . OK Fetch completed. . fetch 1 rfc822.text
- 1 FETCH (RFC822.TEXT {721} X-DSPAM: test value
X-DSPAM: test value
Return-Path: <pupkin@virtualworld.com>
Delivered-To: pitman@virtualworld.com
Received: from localhost.virtualworld.com (localhost [127.0.0.1])
by bsdman.virtualworld.com (Postfix) with ESMTP id 8AB84254
for <pitman@virtualworld.com>; Thu, 2 Apr 2009 05:07:51
+0400 (MSD)
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: 2009-04-02T05:07:51.464214+1
From: pupkin@virtualworld.com
Reply-to: Konstantin@bsdman.virtualworld.com,
Lepa@bsdman.virtualworld.com
To: pitman@virtualworld.com
Message-Id: <20090402010751.8AB84254@bsdman.virtualworld.com>
Date: Thu, 2 Apr 2009 05:07:51 +0400 (MSD)
Message 1 ) . OK Fetch completed.
On Apr 3, 2009, at 14:12 , Konstantin Lepa wrote:
Hello.
I wrote the hook function for deliver. I want to add support of
editheaders in the plug-in for dovecot. For this purpose I wrote the
function rarules_get_stream. Remover of headrs works properly, but
adding does not work. I took Timo Sirainen's advice from http://markmail.org/message/skb6arnll5gaopdr . Do I use a correct way of creation of a message?I give backtrace and a part of my code.
Thanks, Konstantin
uname -a: FreeBSD bsdman.virtualworld.com 6.4-RELEASE FreeBSD 6.4-RELEASE #0:
Wed Nov 26 11:43:51 UTC 2008 root@dessler.cse.buffalo.edu:/usr/ obj/usr/src/sys/GENERIC i386dovecot --version: 1.1.11
build: $ ./configure --localstatedir=/var --with-statedir=/var/db/dovecot
--without-shadow --enable-debug --with-ioloop=kqueue --disable-ipv6
--with-gssapi --without-vpopmail --without-ldap --without-pgsql -- with-mysql --without-sqlite --prefix=/usr/local --mandir=/usr/local/ man --infodir=/usr/local/info/ --build=i386-portbld-freebsd6.4patches: in freebsd ports
(gdb) bt #0 0x282f3a01 in memcpy () from /lib/libc.so.6 #1 0x080df555 in i_stream_concat_read_next (cstream=0x814aa00) at
istream-concat.c:79 #2 0x080df784 in i_stream_concat_read (stream=0x814aa00) at istream- concat.c:136 #3 0x080de659 in i_stream_read (stream=0x814aa28) at istream.c:78 #4 0x080cd99a in i_stream_header_filter_read (stream=0x814e400) at
istream-header-filter.c:322 #5 0x080de659 in i_stream_read (stream=0x814e428) at istream.c:78 #6 0x080dff26 in i_stream_crlf_read_common (cstream=0x814ad00) at
istream-crlf.c:41 #7 0x080e01b3 in i_stream_crlf_read_lf (stream=0x814ad00) at
istream-crlf.c:103 #8 0x080de659 in i_stream_read (stream=0x814ad28) at istream.c:78 #9 0x080e2611 in i_stream_tee_read (stream=0x814ae00) at istream- tee.c:122 #10 0x080de659 in i_stream_read (stream=0x814ae28) at istream.c:78 #11 0x080deea3 in i_stream_read_data (stream=0x814ae28,
data_r=0xbfbfea88, size_r=0xbfbfea8c, threshold=1) at istream.c:322 #12 0x080d1744 in message_parser_read_more (ctx=0x8156468,
block_r=0xbfbfea80, full_r=0xbfbfea27) at message-parser.c:117 #13 0x080d20ac in parse_next_body_to_eof (ctx=0x8156468,
block_r=0xbfbfea80) at message-parser.c:411 #14 0x080d2ccf in message_parser_parse_next_block (ctx=0x8156468,
block_r=0xbfbfea80) at message-parser.c:765 #15 0x080931d9 in index_mail_cache_parse_continue (_mail=0x8150060)
at index-mail.c:1316 #16 0x0807838d in mbox_save_continue (_ctx=0x811bb00) at mbox-save.c: 582 #17 0x080a05a8 in mailbox_save_continue (ctx=0x811bb00) at mail- storage.c:740 #18 0x0809d9df in mail_storage_copy (t=0x811b980, mail=0x8141860,
flags=0, keywords=0x0, dest_mail=0x0) at mail-copy.c:33 #19 0x080a0632 in mailbox_copy (t=0x811b980, mail=0x8141860,
flags=0, keywords=0x0, dest_mail=0x0) at mail-storage.c:763 #20 0x0805960d in deliver_save (namespaces=0x8121c68,
storage_r=0xbfbfee14, mailbox=0x811a370 "Draft", mail=0x8141860, flags=0, keywords=0x0) at deliver.c:234 #21 0x2831fe8f in store_in (arg=0x811a370 "Draft", md=0xbfbfed00)
at /home/pitman/work/rarules/src/actions.c:220 #22 0x2831f759 in rarules_execute_action
(type=RARULES_ACTION_STORE_IN, arg=0x811a370 "Draft", md=0xbfbfed00) at /home/pitman/work/rarules/src/actions.c:57 #23 0x2831e70d in execute_actions (action=0x811a360, md=0xbfbfed00)
at /home/pitman/work/rarules/src/rarules.c:98 #24 0x2831e692 in apply_rules (rule=0x811a320, md=0xbfbfed00) at / home/pitman/work/rarules/src/rarules.c:80 #25 0x2831e56a in rarules_main (namespaces=0x8121c68,
storage_r=0xbfbfee14, mail=0x8141860, db=0x8121000, destaddr=0xbfbfef62 "pitman@virtualworld.com",
username=0x8113525 "pitman@virtualworld.com", mailbox=0x80f2a19
"INBOX") at /home/pitman/work/rarules/src/rarules.c:52 #26 0x2831da37 in rarules_deliver_mail (namespaces=0x8121c68,
storage_r=0xbfbfee14, mail=0x8141860, destaddr=0xbfbfef62 "pitman@virtualworld.com", mailbox=0x80f2a19
"INBOX") at /home/pitman/work/rarules/src/rarules_plugin.c:126 #27 0x0805b69a in main (argc=3, argv=0xbfbfeeac) at deliver.c:1084(gdb) f 1 #1 0x080df555 in i_stream_concat_read_next (cstream=0x814aa00) at
istream-concat.c:79 79 memcpy(cstream->istream.w_buffer, data, data_size);(gdb) p data $4 = (const unsigned char *) 0x15 <Address 0x15 out of bounds> (gdb) p data_size $5 = 1
/////////////////////////////////////////My
code/////////////////////////////////////////////////////////static int rarules_get_stream(struct mail * mail, struct
message_size * hdr_size, struct message_size * body_size, struct istream ** stream_r) { struct rarules_mail * ra_mail = RARULES_MAIL_CONTEXT(mail); struct istream * stream = NULL; struct istream ** chunks = NULL; const unsigned int max_chunks = 4;unsigned int i = 0; unsigned int cnt = 0; unsigned int exclude_cnt = 0; unsigned int include_cnt = 0;
int ret = 0;
#if 1 {/* Test code */ const char * str = "Subject"; const char * str2 = "X-DSPAM: test value\n\n";
array_append(&ra_mail->exclude_headers, &str, 1); array_append(&ra_mail->include_headers, &str2, 1);
} #endif
DPRINT("Standard get_stream for mail storage format"); ret = ra_mail->module_ctx.super.get_stream(mail, hdr_size,
body_size, &stream);include_cnt = array_count(&ra_mail->include_headers); exclude_cnt = array_count(&ra_mail->exclude_headers);
if ((!exclude_cnt && !include_cnt) || ret < 0) { *stream_r = stream; return ret; }
DPRINT("Create message from chunks with new headers and skip
excluded headers"); chunks = t_new(struct istream *, max_chunks); chunks[cnt++] = header_filter(stream, &ra_mail->exclude_headers,
exclude_cnt); if (include_cnt) { chunks[cnt++] = create_header_stream(&ra_mail->include_headers,
include_cnt); } chunks[cnt++] = create_stream_for_msgbody(stream); chunks[cnt++] = NULL;*stream_r = i_stream_create_concat(chunks);
DPRINT("Cleanup");
array_clear(&ra_mail->include_headers); array_clear(&ra_mail->exclude_headers);
for (i = 0; chunks[i] != NULL; ++i) { i_stream_unref(&chunks[i]); } i_stream_unref(&stream);
DPRINTF("Func `%s' executed", __FUNCTION__);
return ret; }
inline static struct istream * create_stream_for_msgbody(struct istream * stream) { struct istream * tmp = stream; struct message_size hdr_size; struct message_size body_size;
DPRINTF("Func `%s' called", __FUNCTION__);
message_get_body_size(stream, &body_size, NULL); message_get_header_size(stream, &hdr_size, NULL);
i_stream_seek(stream, hdr_size.physical_size); stream = i_stream_create_limit(stream, body_size.physical_size);
i_stream_unref(&tmp);
return stream; }
inline static struct istream * header_filter(struct istream * stream, ARRAY_TYPE(const_string) *
headers_arr, unsigned int count) { const char * const * headers = NULL;DPRINTF("Func `%s' called", __FUNCTION__);
if (count) { headers = (const char **)array_idx(headers_arr, 0); }
return i_stream_create_header_filter(stream, HEADER_FILTER_EXCLUDE | HEADER_FILTER_NO_CR | HEADER_FILTER_HIDE_BODY, headers, count, null_header_filter_callback, NULL); }
inline static struct istream * create_header_stream(ARRAY_TYPE(const_string) * headers_arr,
unsigned int count) { unsigned int i = 0; struct istream * result = NULL; struct istream ** chunks = NULL; const char * const * headers = NULL;DPRINTF("Func `%s' called", __FUNCTION__); i_assert(count != 0);
headers = (const char **)array_idx(headers_arr, 0);
DPRINT("Create streams for new included headers from headers"); chunks = t_new(struct istream *, count + 1); for (i = 0; i < count; ++i) { struct istream * tmp = NULL;
tmp = i_stream_create_from_data(headers[i], strlen(headers[i])); chunks[i] = i_stream_create_lf(tmp); i_stream_unref(&tmp);
} chunks[count] = NULL; result = i_stream_create_concat(chunks);
for (i = 0; chunks[i] != NULL; ++i) { i_stream_unref(&chunks[i]); }
return result; }
Also, i'd like to know how to cut last '\n' from header stream. If I
don't remove a last lf symbol, then all my headers'll added to message
body :-(
On Apr 3, 2009, at 17:37 , Konstantin Lepa wrote:
I fixed the problem and I created another :-)
I removed header "Subject" and added "X-DSPAM: test value\n\n". Now,
problem is message_get_header_size in create_stream_for_msgbody. It
returns 0 :-( I don't know how to extract message body properly.
Help me to understand usage of struct message_size.Result: . fetch 1 rfc822.header
- 1 FETCH (RFC822.HEADER {625} Return-Path: <pupkin@virtualworld.com> Delivered-To: pitman@virtualworld.com Received: from localhost.virtualworld.com (localhost [127.0.0.1]) by bsdman.virtualworld.com (Postfix) with ESMTP id 8AB84254 for <pitman@virtualworld.com>; Thu, 2 Apr 2009 05:07:51
+0400 (MSD) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: pupkin@virtualworld.com Reply-to: Konstantin@bsdman.virtualworld.com, Lepa@bsdman.virtualworld.com To: pitman@virtualworld.com Message-Id: <20090402010751.8AB84254@bsdman.virtualworld.com> Date: Thu, 2 Apr 2009 05:07:51 +0400 (MSD)) . OK Fetch completed. . fetch 1 rfc822.text
- 1 FETCH (RFC822.TEXT {721} X-DSPAM: test value
X-DSPAM: test value
Return-Path: <pupkin@virtualworld.com> Delivered-To: pitman@virtualworld.com Received: from localhost.virtualworld.com (localhost [127.0.0.1]) by bsdman.virtualworld.com (Postfix) with ESMTP id 8AB84254 for <pitman@virtualworld.com>; Thu, 2 Apr 2009 05:07:51
+0400 (MSD) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: 2009-04-02T05:07:51.464214+1 From: pupkin@virtualworld.com Reply-to: Konstantin@bsdman.virtualworld.com, Lepa@bsdman.virtualworld.com To: pitman@virtualworld.com Message-Id: <20090402010751.8AB84254@bsdman.virtualworld.com> Date: Thu, 2 Apr 2009 05:07:51 +0400 (MSD)Message 1 ) . OK Fetch completed.
On Apr 3, 2009, at 14:12 , Konstantin Lepa wrote:
Hello.
I wrote the hook function for deliver. I want to add support of
editheaders in the plug-in for dovecot. For this purpose I wrote
the function rarules_get_stream. Remover of headrs works properly,
but adding does not work. I took Timo Sirainen's advice from http://markmail.org/message/skb6arnll5gaopdr . Do I use a correct way of creation of a message?I give backtrace and a part of my code.
Thanks, Konstantin
uname -a: FreeBSD bsdman.virtualworld.com 6.4-RELEASE FreeBSD 6.4-RELEASE #0:
Wed Nov 26 11:43:51 UTC 2008 root@dessler.cse.buffalo.edu:/usr/ obj/usr/src/sys/GENERIC i386dovecot --version: 1.1.11
build: $ ./configure --localstatedir=/var --with-statedir=/var/db/dovecot
--without-shadow --enable-debug --with-ioloop=kqueue --disable-ipv6
--with-gssapi --without-vpopmail --without-ldap --without-pgsql -- with-mysql --without-sqlite --prefix=/usr/local --mandir=/usr/local/ man --infodir=/usr/local/info/ --build=i386-portbld-freebsd6.4patches: in freebsd ports
(gdb) bt #0 0x282f3a01 in memcpy () from /lib/libc.so.6 #1 0x080df555 in i_stream_concat_read_next (cstream=0x814aa00) at
istream-concat.c:79 #2 0x080df784 in i_stream_concat_read (stream=0x814aa00) at
istream-concat.c:136 #3 0x080de659 in i_stream_read (stream=0x814aa28) at istream.c:78 #4 0x080cd99a in i_stream_header_filter_read (stream=0x814e400) at
istream-header-filter.c:322 #5 0x080de659 in i_stream_read (stream=0x814e428) at istream.c:78 #6 0x080dff26 in i_stream_crlf_read_common (cstream=0x814ad00) at
istream-crlf.c:41 #7 0x080e01b3 in i_stream_crlf_read_lf (stream=0x814ad00) at
istream-crlf.c:103 #8 0x080de659 in i_stream_read (stream=0x814ad28) at istream.c:78 #9 0x080e2611 in i_stream_tee_read (stream=0x814ae00) at istream- tee.c:122 #10 0x080de659 in i_stream_read (stream=0x814ae28) at istream.c:78 #11 0x080deea3 in i_stream_read_data (stream=0x814ae28,
data_r=0xbfbfea88, size_r=0xbfbfea8c, threshold=1) at istream.c:322 #12 0x080d1744 in message_parser_read_more (ctx=0x8156468,
block_r=0xbfbfea80, full_r=0xbfbfea27) at message-parser.c:117 #13 0x080d20ac in parse_next_body_to_eof (ctx=0x8156468,
block_r=0xbfbfea80) at message-parser.c:411 #14 0x080d2ccf in message_parser_parse_next_block (ctx=0x8156468,
block_r=0xbfbfea80) at message-parser.c:765 #15 0x080931d9 in index_mail_cache_parse_continue (_mail=0x8150060)
at index-mail.c:1316 #16 0x0807838d in mbox_save_continue (_ctx=0x811bb00) at mbox- save.c:582 #17 0x080a05a8 in mailbox_save_continue (ctx=0x811bb00) at mail- storage.c:740 #18 0x0809d9df in mail_storage_copy (t=0x811b980, mail=0x8141860,
flags=0, keywords=0x0, dest_mail=0x0) at mail-copy.c:33 #19 0x080a0632 in mailbox_copy (t=0x811b980, mail=0x8141860,
flags=0, keywords=0x0, dest_mail=0x0) at mail-storage.c:763 #20 0x0805960d in deliver_save (namespaces=0x8121c68,
storage_r=0xbfbfee14, mailbox=0x811a370 "Draft", mail=0x8141860, flags=0, keywords=0x0) at deliver.c:234 #21 0x2831fe8f in store_in (arg=0x811a370 "Draft", md=0xbfbfed00)
at /home/pitman/work/rarules/src/actions.c:220 #22 0x2831f759 in rarules_execute_action
(type=RARULES_ACTION_STORE_IN, arg=0x811a370 "Draft", md=0xbfbfed00) at /home/pitman/work/rarules/src/actions.c:57 #23 0x2831e70d in execute_actions (action=0x811a360, md=0xbfbfed00)
at /home/pitman/work/rarules/src/rarules.c:98 #24 0x2831e692 in apply_rules (rule=0x811a320, md=0xbfbfed00) at / home/pitman/work/rarules/src/rarules.c:80 #25 0x2831e56a in rarules_main (namespaces=0x8121c68,
storage_r=0xbfbfee14, mail=0x8141860, db=0x8121000, destaddr=0xbfbfef62 "pitman@virtualworld.com",
username=0x8113525 "pitman@virtualworld.com", mailbox=0x80f2a19
"INBOX") at /home/pitman/work/rarules/src/rarules.c:52 #26 0x2831da37 in rarules_deliver_mail (namespaces=0x8121c68,
storage_r=0xbfbfee14, mail=0x8141860, destaddr=0xbfbfef62 "pitman@virtualworld.com",
mailbox=0x80f2a19 "INBOX") at /home/pitman/work/rarules/src/rarules_plugin.c:126 #27 0x0805b69a in main (argc=3, argv=0xbfbfeeac) at deliver.c:1084(gdb) f 1 #1 0x080df555 in i_stream_concat_read_next (cstream=0x814aa00) at
istream-concat.c:79 79 memcpy(cstream->istream.w_buffer, data, data_size);(gdb) p data $4 = (const unsigned char *) 0x15 <Address 0x15 out of bounds> (gdb) p data_size $5 = 1
/////////////////////////////////////////My
code/////////////////////////////////////////////////////////static int rarules_get_stream(struct mail * mail, struct
message_size * hdr_size, struct message_size * body_size, struct istream ** stream_r) { struct rarules_mail * ra_mail = RARULES_MAIL_CONTEXT(mail); struct istream * stream = NULL; struct istream ** chunks = NULL; const unsigned int max_chunks = 4;unsigned int i = 0; unsigned int cnt = 0; unsigned int exclude_cnt = 0; unsigned int include_cnt = 0;
int ret = 0;
#if 1 {/* Test code */ const char * str = "Subject"; const char * str2 = "X-DSPAM: test value\n\n";
array_append(&ra_mail->exclude_headers, &str, 1); array_append(&ra_mail->include_headers, &str2, 1);
} #endif
DPRINT("Standard get_stream for mail storage format"); ret = ra_mail->module_ctx.super.get_stream(mail, hdr_size,
body_size, &stream);include_cnt = array_count(&ra_mail->include_headers); exclude_cnt = array_count(&ra_mail->exclude_headers);
if ((!exclude_cnt && !include_cnt) || ret < 0) { *stream_r = stream; return ret; }
DPRINT("Create message from chunks with new headers and skip
excluded headers"); chunks = t_new(struct istream *, max_chunks); chunks[cnt++] = header_filter(stream, &ra_mail->exclude_headers,
exclude_cnt); if (include_cnt) { chunks[cnt++] = create_header_stream(&ra_mail->include_headers,
include_cnt); } chunks[cnt++] = create_stream_for_msgbody(stream); chunks[cnt++] = NULL;*stream_r = i_stream_create_concat(chunks);
DPRINT("Cleanup");
array_clear(&ra_mail->include_headers); array_clear(&ra_mail->exclude_headers);
for (i = 0; chunks[i] != NULL; ++i) { i_stream_unref(&chunks[i]); } i_stream_unref(&stream);
DPRINTF("Func `%s' executed", __FUNCTION__);
return ret; }
inline static struct istream * create_stream_for_msgbody(struct istream * stream) { struct istream * tmp = stream; struct message_size hdr_size; struct message_size body_size;
DPRINTF("Func `%s' called", __FUNCTION__);
message_get_body_size(stream, &body_size, NULL); message_get_header_size(stream, &hdr_size, NULL);
i_stream_seek(stream, hdr_size.physical_size); stream = i_stream_create_limit(stream, body_size.physical_size);
i_stream_unref(&tmp);
return stream; }
inline static struct istream * header_filter(struct istream * stream, ARRAY_TYPE(const_string) *
headers_arr, unsigned int count) { const char * const * headers = NULL;DPRINTF("Func `%s' called", __FUNCTION__);
if (count) { headers = (const char **)array_idx(headers_arr, 0); }
return i_stream_create_header_filter(stream, HEADER_FILTER_EXCLUDE | HEADER_FILTER_NO_CR | HEADER_FILTER_HIDE_BODY, headers, count, null_header_filter_callback, NULL); }
inline static struct istream * create_header_stream(ARRAY_TYPE(const_string) * headers_arr,
unsigned int count) { unsigned int i = 0; struct istream * result = NULL; struct istream ** chunks = NULL; const char * const * headers = NULL;DPRINTF("Func `%s' called", __FUNCTION__); i_assert(count != 0);
headers = (const char **)array_idx(headers_arr, 0);
DPRINT("Create streams for new included headers from headers"); chunks = t_new(struct istream *, count + 1); for (i = 0; i < count; ++i) { struct istream * tmp = NULL;
tmp = i_stream_create_from_data(headers[i], strlen(headers[i])); chunks[i] = i_stream_create_lf(tmp); i_stream_unref(&tmp);
} chunks[count] = NULL; result = i_stream_create_concat(chunks);
for (i = 0; chunks[i] != NULL; ++i) { i_stream_unref(&chunks[i]); }
return result; }
On Fri, 2009-04-03 at 17:37 +0400, Konstantin Lepa wrote:
I fixed the problem and I created another :-)
I removed header "Subject" and added "X-DSPAM: test value\n\n". Now,
problem is message_get_header_size in create_stream_for_msgbody. It
returns 0 :-( I don't know how to extract message body properly. Help
me to understand usage of struct message_size.
Header comes first in the input stream, then body. So call message_get_header_size() first and message_get_body_size() next.
Yeah, but it doesn't work without i_stream_seek(stream, 0) before.
How can I remove EOH after i_stream_create_header_filter (second
'\n')? Is it possible?
I found next solution:
fname = t_strdup(mktemp("/tmp/temp.XXXXXX"));
fd = creat(fname, 0600);
output = o_stream_create_fd_file(fd, 0, TRUE);
o_stream_send_istream(output, tmp);
o_stream_flush(output);
// some fd manipulations
stream = i_stream_create_fd(fd, ...);
But it's so ugly and expensive :-( Maybe, another way?
On Apr 3, 2009, at 20:48 , Timo Sirainen wrote:
On Fri, 2009-04-03 at 17:37 +0400, Konstantin Lepa wrote:
I fixed the problem and I created another :-)
I removed header "Subject" and added "X-DSPAM: test value\n\n". Now, problem is message_get_header_size in create_stream_for_msgbody. It returns 0 :-( I don't know how to extract message body properly. Help me to understand usage of struct message_size.
Header comes first in the input stream, then body. So call message_get_header_size() first and message_get_body_size() next.
On Fri, 2009-04-03 at 21:25 +0400, Konstantin Lepa wrote:
Yeah, but it doesn't work without i_stream_seek(stream, 0) before.
How can I remove EOH after i_stream_create_header_filter (second
'\n')? Is it possible?
You can give i_stream_create_header_filter() a callback function, which gets called for each header line, and once for the EOH with hdr->eoh == TRUE. There you can set *matched = FALSE and it won't add the EOH.
Thank you very much :-)
On Apr 3, 2009, at 21:29 , Timo Sirainen wrote:
On Fri, 2009-04-03 at 21:25 +0400, Konstantin Lepa wrote:
Yeah, but it doesn't work without i_stream_seek(stream, 0) before.
How can I remove EOH after i_stream_create_header_filter (second '\n')? Is it possible?
You can give i_stream_create_header_filter() a callback function,
which gets called for each header line, and once for the EOH with hdr->eohTRUE. There you can set *matched = FALSE and it won't add the EOH.
It's my code of message creation:
chunks = t_new(struct istream *, max_chunks);
chunks[cnt++] = header_filter(stream, &ra_mail->exclude_headers,
exclude_cnt); /* calls i_stream_header_filter */
#if 0
if (include_cnt) { /* calls i_stream_create_from_data for my
headers */
chunks[cnt++] = create_header_stream(&ra_mail->include_headers,
include_cnt);
}
chunks[cnt++] = create_stream_for_msgbody(stream); /* calls
i_stream_create_limit for message body */
#endif
chunks[cnt++] = NULL;
*stream_r = i_stream_create_concat(chunks);
if I enable the block of code, then header_filter_callback is called
for message body only. Why?
I reviewed i_stream_header_filter' and noticed, that it returns
i_stream_create(&mstream->istream, input, -1)' where `input' is
parent stream. Maybe, is it reason of problem?
/************************************My
header_filter_callback:************************************/
static void rarules_header_filter_callback(struct message_header_line
hdr, bool * matched, void *
context) { DPRINTF("Func `%s' is called", __FUNCTION__);if (hdr && hdr->eoh == TRUE) { *matched = FALSE; } else { *matched =
TRUE; }
if (hdr) { DPRINTF("#%s: %s", hdr->name, hdr->value); }
}
/***************************************** My header_filter:
****************************************/
static struct istream *
header_filter(struct istream * stream, ARRAY_TYPE(const_string) *
headers_arr,
unsigned int count)
{
const char * const * headers = NULL;
DPRINTF("Func `%s' is called", __FUNCTION__);
if (count) { headers = (const char **)array_idx(headers_arr,
0); }
return i_stream_create_header_filter(stream,
HEADER_FILTER_EXCLUDE |
HEADER_FILTER_NO_CR |
HEADER_FILTER_HIDE_BODY,
headers,
N_ELEMENTS(headers),
rarules_header_filter_callback, NULL);
}
On Apr 3, 2009, at 21:29 , Timo Sirainen wrote:
On Fri, 2009-04-03 at 21:25 +0400, Konstantin Lepa wrote:
Yeah, but it doesn't work without i_stream_seek(stream, 0) before.
How can I remove EOH after i_stream_create_header_filter (second '\n')? Is it possible?
You can give i_stream_create_header_filter() a callback function,
which gets called for each header line, and once for the EOH with hdr->eohTRUE. There you can set *matched = FALSE and it won't add the EOH.
Konstantin Lepa schreef:
Hello.
I wrote the hook function for deliver. I want to add support of editheaders in the plug-in for dovecot. For this purpose I wrote the function rarules_get_stream. Remover of headrs works properly, but adding does not work. I took Timo Sirainen's advice from http://markmail.org/message/skb6arnll5gaopdr . Do I use a correct way of creation of a message?
Hmm, by the subject of this message it looks like you are working on the new editheader extension for the Sieve language. Looking at your backtrace, however, it seems as though you are building a dedicated plugin for editing messages.
So, what exactly are you doing? :)
Regards,
-- Stephan Bosch stephan@rename-it.nl
My company is migrating to dovecot from commercial soft. It wants to
use MySQL db instead sieve scripts. I must to write a new plug-in for
dovecot with support of editheaders.
On Apr 5, 2009, at 20:30 , Stephan Bosch wrote:
Hello. I wrote the hook function for deliver. I want to add support of
editheaders in the plug-in for dovecot. For this purpose I wrote
the function rarules_get_stream. Remover of headrs works properly,
but adding does not work. I took Timo Sirainen's advice from http://markmail.org/message/skb6arnll5gaopdr . Do I use a correct way of creation of a message? Hmm, by the subject of this message it looks like you are working onKonstantin Lepa schreef: the new editheader extension for the Sieve language. Looking at your
backtrace, however, it seems as though you are building a dedicated
plugin for editing messages.So, what exactly are you doing? :)
Regards,
-- Stephan Bosch stephan@rename-it.nl
participants (3)
-
Konstantin Lepa
-
Stephan Bosch
-
Timo Sirainen