message-send.c revision 907035872354e895a0c4431e1e42cd21d456f3ea
45312f52ff3a3d4c137447be4c7556500c2f8bf2Timo Sirainen/* Copyright (C) 2002 Timo Sirainen */
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "lib.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "istream.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "ostream.h"
3343a61404603b21c246783a7963b77833095f31Timo Sirainen#include "message-send.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "message-size.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainenint message_send(OStream *output, IStream *input, MessageSize *msg_size,
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen uoff_t virtual_skip, uoff_t max_virtual_size)
0a601ada15c7fe82f0db895fc2068b71b3a5243cTimo Sirainen{
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen const unsigned char *msg;
573f0491a5733fe21fa062a455acb4790b4e0499Timo Sirainen uoff_t old_limit, limit;
573f0491a5733fe21fa062a455acb4790b4e0499Timo Sirainen size_t i, size;
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen int cr_skipped, add_cr, ret;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if (msg_size->physical_size == 0 ||
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen virtual_skip >= msg_size->virtual_size)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen return TRUE;
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if (max_virtual_size > msg_size->virtual_size - virtual_skip)
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen max_virtual_size = msg_size->virtual_size - virtual_skip;
04ab375449dd97eed50ada88dd0df2abab01cfeeTimo Sirainen
42456ec33fe65feb411890f99d436071e0185ee3Timo Sirainen if (msg_size->physical_size == msg_size->virtual_size) {
04ab375449dd97eed50ada88dd0df2abab01cfeeTimo Sirainen /* no need to kludge with CRs, we can use sendfile() */
04ab375449dd97eed50ada88dd0df2abab01cfeeTimo Sirainen i_stream_skip(input, virtual_skip);
04ab375449dd97eed50ada88dd0df2abab01cfeeTimo Sirainen
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen old_limit = input->v_limit;
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen limit = input->v_offset + max_virtual_size;
42456ec33fe65feb411890f99d436071e0185ee3Timo Sirainen i_stream_set_read_limit(input, I_MIN(limit, old_limit));
42456ec33fe65feb411890f99d436071e0185ee3Timo Sirainen ret = o_stream_send_istream(output, input) > 0;
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen i_stream_set_read_limit(input, old_limit);
3f190f4cbb9233a3a6830956cb5c7ae56a577b79Timo Sirainen
3f190f4cbb9233a3a6830956cb5c7ae56a577b79Timo Sirainen return ret;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen }
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen message_skip_virtual(input, virtual_skip, NULL, &cr_skipped);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen /* go through the message data and insert CRs where needed. */
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen while (max_virtual_size > 0 &&
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen i_stream_read_data(input, &msg, &size, 0) > 0) {
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen add_cr = FALSE;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen for (i = 0; i < size && max_virtual_size > 0; i++) {
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen max_virtual_size--;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen if (msg[i] == '\n') {
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen if ((i == 0 && !cr_skipped) ||
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen (i > 0 && msg[i-1] != '\r')) {
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen /* missing CR */
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen add_cr = TRUE;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen break;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen }
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen }
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen }
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if (o_stream_send(output, msg, i) < 0)
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen return FALSE;
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen
0d16525a729011f4fced989a3da74d755ea49e6dTimo Sirainen if (add_cr) {
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen if (o_stream_send(output, "\r", 1) < 0)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen return FALSE;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen cr_skipped = TRUE;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen } else {
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen cr_skipped = i > 0 && msg[i-1] == '\r';
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen }
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen i_stream_skip(input, i);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen }
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen
04ab375449dd97eed50ada88dd0df2abab01cfeeTimo Sirainen return TRUE;
42456ec33fe65feb411890f99d436071e0185ee3Timo Sirainen}
8ed8c821ba8aab0b4ed0375f87d48737ef0e0d8eTimo Sirainen