istream-dot.c revision da2aa032ccfa8e7e4a4380ef738014549f4d2c2d
/* Copyright (c) 2007-2009 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "istream-internal.h"
#include "istream-dot.h"
struct dot_istream {
struct istream_private istream;
/* how far in string "\r\n.\r" are we */
unsigned int state;
/* state didn't actually start with \r */
unsigned int state_no_cr:1;
/* state didn't contain \n either (only at the beginnign of stream) */
unsigned int state_no_lf:1;
/* we've seen the "." line, keep returning EOF */
unsigned int dot_eof:1;
unsigned int send_last_lf:1;
};
{
if (size == 0) {
/* we didn't see "." line */
}
return ret;
}
}
return -2;
return 1;
}
{
unsigned int i = 0;
}
{
unsigned int i = 0;
if (!dstream->state_no_cr)
if (dstream->state_no_lf)
else {
/* \r\n.\r seen, go back to \r state */
}
}
{
if (dstream->send_last_lf) {
}
}
static ssize_t
{
}
return ret;
}
{
/* @UNSAFE */
const unsigned char *data;
return -2;
} else {
}
}
/* we have to update stream->pos before reading more data */
if (ret1 != 0)
return ret1;
}
case 0:
break;
case 1:
/* CR seen */
if (data[i] == '\n')
else {
goto end;
}
break;
case 2:
/* [CR]LF seen */
if (data[i] == '.')
else {
goto end;
}
break;
case 3:
/* [CR]LF. seen */
if (data[i] == '\r')
else if (data[i] == '\n') {
/* EOF */
i++;
goto end;
} else {
/* drop the initial dot */
goto end;
}
break;
case 4:
/* [CR]LF.CR seen */
if (data[i] == '\n') {
/* EOF */
i++;
goto end;
} else {
/* drop the initial dot */
goto end;
}
}
if (data[i] == '\r') {
} else if (data[i] == '\n') {
} else {
}
}
}
end:
if (ret == 0)
return i_stream_dot_read(stream);
return ret;
}
static const struct stat *
{
}
{
struct dot_istream *dstream;
}