/* PUBLIC */ void p_ibuf(Ibuffer ibuf) { int i = ibuf_read(ibuf); while (i != IBUF_EOF) { printf("%d ", i); i = ibuf_read(ibuf); } printf("\n"); } /* p_ibuf */
static int read_start(ibuf* in, uint32* end) { unsigned char buf[2048]; if (!ibuf_read(in, (char*)buf, sizeof buf)) return 0; *end = uint32_get_lsb(buf); return 1; }
static int read_cdb_pair(ibuf* in, str* key, str* data) { unsigned char buf[8]; uint32 keylen; uint32 datalen; if (!ibuf_read(in, (char*)buf, sizeof buf)) return 0; keylen = uint32_get_lsb(buf); datalen = uint32_get_lsb(buf+4); if (!str_ready(key, keylen) || !str_ready(data, datalen) || !ibuf_read(in, key->s, keylen) || !ibuf_read(in, data->s, datalen)) return 0; key->s[key->len = keylen] = 0; data->s[data->len = datalen] = 0; return 1; }
static void dump_msg(long num, long bodylines) { ibuf in; static char buf[4096]; int in_header; /* True until a blank line is seen */ int sol; /* True if at start of line */ if (!ibuf_open(&in, msgs[num-1].filename, 0)) return respond("-ERR Could not open that message"); respond(ok); sol = in_header = 1; while (ibuf_read(&in, buf, sizeof buf) || in.count) { const char* ptr = buf; const char* end = buf + in.count; while (ptr < end) { const char* lfptr; if (sol) { if (!in_header) if (--bodylines < 0) break; if (*ptr == '.') obuf_putc(&outbuf, '.'); } if ((lfptr = memchr(ptr, LF, end-ptr)) == 0) { obuf_write(&outbuf, ptr, end-ptr); ptr = end; sol = 0; } else { if (in_header && lfptr == ptr) in_header = 0; obuf_write(&outbuf, ptr, lfptr-ptr); obuf_puts(&outbuf, CRLF); ptr = lfptr + 1; sol = 1; } } } ibuf_close(&in); obuf_puts(&outbuf, CRLF); respond("."); }
/* This parser is rather liberal in what it accepts: The IMAP standard mandates seperate character sets for tags, commands, unquoted strings. Since they all must be seperated by spaces, this parser allows all non-whitespace characters for each of the above. */ static int parse_line(void) { #define RESPOND(T,S) do{ respond(T,S); return 0; }while(0) unsigned i; unsigned len; const char* ptr; str* arg; /* Parse out the command tag */ str_truncate(&tag, 0); for (i = 0, ptr = line.s; i < line.len && isspace(*ptr); ++i, ++ptr) ; for (; i < line.len && !isspace(*ptr); ++i, ++ptr) str_catc(&tag, line.s[i]); if (!tag.len) RESPOND(NOTAG, "BAD Syntax error"); if (i >= line.len) RESPOND(0, "BAD Syntax error"); /* Parse out the command itself */ str_truncate(&cmd, 0); for (; i < line.len && isspace(*ptr); ++i, ++ptr) ; for (; i < line.len && !isspace(*ptr); ++i, ++ptr) str_catc(&cmd, line.s[i]); if (!cmd.len) RESPOND(0, "BAD Syntax error"); /* Parse out the command-line args */ for (line_argc = 0; line_argc < MAX_ARGC; ++line_argc) { arg = &line_args[line_argc]; str_truncate(arg, 0); for (; i < line.len && isspace(*ptr); ++i, ++ptr) ; if (i >= line.len) break; switch (*ptr) { case LBRACE: /* Handle a string literal */ ++i, ++ptr; if (!isdigit(*ptr)) RESPOND(0, "BAD Syntax error: missing integer"); for (len = 0; i < line.len && *ptr != RBRACE; ++i, ++ptr) { if (!isdigit(*ptr)) RESPOND(0, "BAD Syntax error: invalid integer"); len = len * 10 + *ptr - '0'; } ++i, ++ptr; if (*ptr != 0) RESPOND(0, "BAD Syntax error: missing LF after integer"); str_ready(arg, len); respond(CONT, "OK"); if (len > 0) ibuf_read(&inbuf, arg->s, len); arg->s[arg->len = len] = 0; ibuf_getstr_crlf(&inbuf, &line); i = 0; ptr = line.s; break; case QUOTE: /* Handle a quoted string */ for (++i, ++ptr; i < line.len && *ptr != QUOTE; ++i, ++ptr) { if (*ptr == ESCAPE) { if (++i >= line.len) break; ++ptr; } str_catc(arg, *ptr); } if (i >= line.len || *ptr != QUOTE) RESPOND(0, "BAD Syntax error: unterminated quoted string"); ++i, ++ptr; break; default: /* Normal case is very simple */ for (; i < line.len && !isspace(*ptr); ++i, ++ptr) str_catc(arg, *ptr); } } for (; i < line.len && isspace(*ptr); ++i, ++ptr) ; if (i < line.len) RESPOND(0, "BAD Too many command arguments"); return 1; }