#ifndef MIME_H
#define MIME_H
#ifdef __cplusplus
extern "C" {
#endif
#include "defines.h"
#include "rstring.h"
#define MIME_BFSZ BFSZ
#define MIME_PARTMAX 100
typedef struct BOUND {char bound[MIME_BFSZ]; int level; int n; struct BOUND *next;} Bound;
typedef struct MIME {
	Bound *blist; int level; int isend; int gotline;
	Bound *cur[100];
	int inhead; char nextline[MIME_BFSZ];
	int encoding; char content[MIME_BFSZ];
	char content_id[MIME_BFSZ];
	char part[MIME_BFSZ];
	int ismime;
	int partid[MIME_PARTMAX];
	int partlvl;
	int resync;
	char fname[MIME_BFSZ];
	int mem_len;
	char *mem;
	char *mem_at;
	int return_all; // If true, then return continuation lines
	int append_lines; // If true then append continuation lines for all headers.
	char lost[MIME_BFSZ];
	int islost;
	int unstuff; // If true we are reading a queue file and must undotstuff
	int bound_end; // true if we just read the end of boundaries boundary
	int loose_header; // if true then treat a line with only spaces as end of headers
	int one_level; // If true then only go one level deep, don't stop at sub parts.
	int done_level; // flag used to rememver if we've finished reading boundaries. 
	char * (*read)(char *, int, void *);
    RString *rdecode;  // Try more error robust mime decoding (for non rfc compliant lines
                       // ie. too long and incorrectly linesplit lines
    int rlen_prev;     // prevent infinite loop
	int needcrlf; // require boundaries end with 'crlf' as intended.
	char lastbound[MIME_BFSZ];
} Mime ;

enum {MIME_END,MIME_HEADER,MIME_BODY,MIME_BOUNDARY,MIME_CONTENT,MIME_HEADER_END};
enum {MIME_NONE,MIME_BASE64,MIME_QUOTED};

int mime_setfn(Mime *m, char * (*read)(char *, int, void *));
int mime_setmem(Mime *m, char *mem, int len);

int mime_encode_quoted(char *in, int inlen, char *out, int outlen);
int mime_encode_quoted_real(char *in, int inlen, char *out, int outlen, int *prcc);
int mime_decode_file(char *fname, char *big, int maxbig);


#define mime_new(a) mime_new_real(a,__FILE__,__LINE__) 
int mime_new_real(Mime **m, char *src, int line);
int mime_free(Mime **m);
int mime_addbound(Mime *m, char *hdr);
int mime_isbound(Mime *m, char *bf, char *part, int *isend);
void mime_robust_decode(Mime *m);
char *mime_header_inplace(char *bf);
int mime_charset(char *content, char *res, int bfsz);
char *mime_header_decode(char *header, char *res, int bfsz);

int mime_set_encoding(Mime *m, char *tmp);

//pass a FILE * to these unless you're using mime_setfn
int mime_line(Mime *m, void *f, char *raw, char *bin, int *len, int bfsz);
int mime_header(Mime *m, void *f, char *bf, char *hdr);
int mime_encrypt_string(char *in, char *out);
int mime_decrypt_string(char *in, char *out);
int mime_set_unstuff(Mime *m, int x);
int mime_tobin(Mime *m, char *raw, char *bin, int *len, int bfsz);
int mime_decode_base64(char *buf, char *out, int bfsz);
int mime_decode_quoted(char *s, char *xout, int bfsz);
int mime_encode_base64_bad(char *xin, int inlen, char *xout, int outlen);
void mime_set_emsg(int (*vemsg)(const char * arg_list, ...));
int word_isbound(Wordlist *list, char *bf, int *pisend);
int word_add_boundary(Wordlist **w, char *hdr);

void mime_log(char*txt, char*line, int k, int fn(const char * arg_list, ...));
char *mime_clean_line_breaks(char *bf);


#ifdef __cplusplus
}
#endif
#endif
