/*
 * Copyright (c) 2003-2012
 * Distributed Systems Software.  All rights reserved.
 * See the file LICENSE for redistribution information.
 *
 * $Id: mime.h 2594 2012-10-19 17:28:49Z brachman $
 */

#ifndef _MIME_H_
#define _MIME_H_

#include <stdio.h>

/* RFC 2045 */
typedef enum {
  MIME_TYPE_TEXT        = 0,
  MIME_TYPE_IMAGE       = 1,
  MIME_TYPE_AUDIO       = 2,
  MIME_TYPE_VIDEO       = 3,
  MIME_TYPE_APPLICATION = 4,
  MIME_TYPE_MESSAGE     = 5,
  MIME_TYPE_MULTIPART   = 6,
  MIME_TYPE_UNKNOWN     = 7,
  MIME_TYPE_ERROR       = 8
} Mime_type;

typedef enum {
  MIME_ENCODING_7BIT            = 0,
  MIME_ENCODING_8BIT            = 1,
  MIME_ENCODING_BINARY          = 2,
  MIME_ENCODING_QUOTEDPRINTABLE = 3,
  MIME_ENCODING_BASE64          = 4,
  MIME_ENCODING_ERROR           = 5
} Mime_encoding;

typedef enum {
  MIME_FORMAT_FIXED   = 0,
  MIME_FORMAT_FLOWED  = 1,
  MIME_FORMAT_UNKNOWN = 2
} Mime_format;

typedef enum {
  MIME_DISPOSITION_INLINE     = 0,
  MIME_DISPOSITION_ATTACHMENT = 1,
  MIME_DISPOSITION_FORMDATA   = 2,
  MIME_DISPOSITION_UNKNOWN    = 3
} Mime_disposition;

typedef enum {
  MIME_HEADER_CONTENT_TYPE                 = 0,
  MIME_HEADER_CONTENT_TRANSFER_ENCODING    = 1,
  MIME_HEADER_CONTENT_DISPOSITION          = 2,
  MIME_HEADER_CONTENT_DESCRIPTION          = 3,
  MIME_HEADER_MIME_VERSION                 = 4,
  MIME_HEADER_CONTENT_ID                   = 5,
  MIME_HEADER_UNKNOWN                      = 6
} Mime_header_type;

typedef struct Mime_parameter {
  char *attrname;			/* XXX May be encoded RFC 2388, 5.4 */
  char *attrvalue;			/* XXX May be encoded RFC 2388, 5.4 */
  struct Mime_parameter *next;
} Mime_parameter;

typedef struct Mime_content_type {
  Mime_type content_type;
  char *subtype;
  char *charset;
  char *name;
  char *boundary;
  size_t boundary_length;
  char *format;
  char *octet_stream_type;
  char *octet_stream_padding;
  char *partial_id;
  char *partial_number;
  char *partial_total;
  /* XXX RFC 2046 5.2.3 message/external-body parameters not implemented */
  Mime_parameter *params;
} Mime_content_type;

typedef struct Mime_content_disposition {
  Mime_disposition disposition;
  char *name;
  char *filename;
  char *creation_date;
  char *modification_date;
  char *read_date;
  char *size;
} Mime_content_disposition;

typedef struct Mime_part {
  char *version;
  Mime_content_type *type;
  Mime_encoding encoding;
  Mime_content_disposition *disposition;
  Mime_format format;
  char *content_id;
  char *description;
  Ds *body;
  int truncated;
  int decoded;
  struct Mime_part *next;
} Mime_part;

typedef struct Mime_header {
  char *field_name;
  char *field_body;
} Mime_header;

typedef struct Mime {
  char *version;
  Dsvec *raw_mime_headers;
  Dsvec *mime_headers;
  Mime_content_type content_type;
  Mime_encoding encoding;
  Mime_part *parts;
  Ds *preamble;
  Ds *epilogue;
  int error_occurred;
  char *sandbox;
  size_t in_mem_limit;
  char *(*header_resolver)(char *, void *);
  void *header_resolver_arg;
} Mime;

typedef struct Mime_file_type {
  char *type_name;
  char **extensions;
} Mime_file_type;

#ifdef __cplusplus
extern "C" {
#endif

extern void mime_init(Mime *mime, char *(*resolver)(char *, void *),
					  void *resolver_arg);
extern int mime_parse_message_headers(Mime *mime, CGI_input *input);
extern Mime_type mime_parse_content_type(char *field_body,
											   Mime_content_type *ctp);
extern void mime_dump_content_type(Mime_content_type *ct);
extern Ds *mime_next_line(CGI_input *in);
extern int mime_parse(Mime *mime, CGI_input *input, Kwv *kwv);
extern char *mime_parse_content_id(char *header);
extern char *mime_parse_content_description(char *header);
extern Mime_encoding mime_parse_content_transfer_encoding(char *header);

extern int mime_parse_urlencoded(CGI_input *in, Kwv *kwv);

extern long mime_decode_quotedprintable(char *str, char **decoded);
extern Ds *mime_encode_quotedprintable(char *str, size_t len);
extern long mime_decode_base64(char *str, unsigned char **decoded);
extern long mime_encode_base64(unsigned char *str, unsigned int nbytes,
							   char **encoded);

extern Dsvec *mime_get_file_types(char *pathname);
extern Mime_file_type *mime_find_file_type(Dsvec *dsv, char *extension);

#ifdef __cplusplus
}
#endif

#endif
