#ifndef ENCODING_H
#define ENCODING_H  1


/* ========================================================================== */
/* Include files */

#include <limits.h>

#include "conf.h"
#include "core.h"
#include "unicode.h"


/*! \addtogroup ENCODING */
/*! @{ */


/* ========================================================================== */
/* Data types */

/*! \brief IDs for supported MIME content types */
enum enc_mime_ct_type
{
   ENC_CT_UNKNOWN,
   ENC_CT_TEXT,          /*!< Text */
   ENC_CT_IMAGE,         /*!< Picture */
   ENC_CT_AUDIO,         /*!< Audio */
   ENC_CT_VIDEO,         /*!< Video */
   ENC_CT_MULTIPART,     /*!< Content consists of multiple parts */
   ENC_CT_MESSAGE,       /*!< Content consists of an encapsulated message */
   ENC_CT_APPLICATION    /*!< Content for unknown application */
};

/*! \brief IDs for supported MIME content subtypes */
enum enc_mime_ct_subtype
{
   ENC_CTS_UNKNOWN,
   ENC_CTS_PLAIN,        /*!< Plain without enrichment */
   ENC_CTS_MIXED,        /*!< Independent parts with a particular order */
   ENC_CTS_ALTERNATIVE,  /*!< Different representations of same content */
   ENC_CTS_DIGEST,       /*!< Default media type message/rfc822 */
   ENC_CTS_RFC822,       /*!< Encapulated message */
   ENC_CTS_OCTETSTREAM   /*!< Raw octet stream */
};

/*! \brief IDs for supported MIME content transfer encodings */
enum enc_mime_cte
{
   ENC_CTE_UNKNOWN,
   ENC_CTE_7BIT,         /*!< ASCII text */
   ENC_CTE_8BIT,         /*!< Raw non ASCII text */
   ENC_CTE_BIN,          /*!< Arbitrary binary data */
   ENC_CTE_Q,            /*!< MIME quoted-printable */
   ENC_CTE_B             /*!< MIME base64 */
};

/*! \brief IDs for supported MIME character sets */
enum enc_mime_cs
{
   ENC_CS_UNKNOWN,
   ENC_CS_ASCII,         /*!< ANSI X3.4 */
   ENC_CS_ISO8859_1,     /*!< ISO 8859-1 */
   ENC_CS_ISO8859_2,     /*!< ISO 8859-2 */
   ENC_CS_ISO8859_3,     /*!< ISO 8859-3 */
   ENC_CS_ISO8859_4,     /*!< ISO 8859-4 */
   ENC_CS_ISO8859_5,     /*!< ISO 8859-5 */
   ENC_CS_ISO8859_6,     /*!< ISO 8859-6 */
   ENC_CS_ISO8859_7,     /*!< ISO 8859-7 */
   ENC_CS_ISO8859_8,     /*!< ISO 8859-8 */
   ENC_CS_ISO8859_9,     /*!< ISO 8859-9 */
   ENC_CS_ISO8859_10,    /*!< ISO 8859-10 */
   ENC_CS_ISO8859_11,    /*!< ISO 8859-11 */
   ENC_CS_ISO8859_13,    /*!< ISO 8859-13 */
   ENC_CS_ISO8859_14,    /*!< ISO 8859-14 */
   ENC_CS_ISO8859_15,    /*!< ISO 8859-15 */
   ENC_CS_ISO8859_16,    /*!< ISO 8859-16 */
   ENC_CS_ISO8859_X,     /*!< Generic fallback (handle only ASCII characters) */
   ENC_CS_MACINTOSH,     /*!< Mac Roman */
   ENC_CS_KOI8R,         /*!< Kod Obmena Informatsiey 8 bit (russion) */
   ENC_CS_KOI8U,         /*!< Kod Obmena Informatsiey 8 bit (ukrainian) */
   ENC_CS_WINDOWS_1250,  /*!< Windows codepage 1250 */
   ENC_CS_WINDOWS_1251,  /*!< Windows codepage 1251 */
   ENC_CS_WINDOWS_1252,  /*!< Windows codepage 1252 */
   ENC_CS_WINDOWS_1253,  /*!< Windows codepage 1253 */
   ENC_CS_WINDOWS_1254,  /*!< Windows codepage 1254 */
   ENC_CS_WINDOWS_1255,  /*!< Windows codepage 1255 */
   ENC_CS_WINDOWS_1256,  /*!< Windows codepage 1256 */
   ENC_CS_WINDOWS_1257,  /*!< Windows codepage 1257 */
   ENC_CS_WINDOWS_1258,  /*!< Windows codepage 1258 */
   ENC_CS_IBM437,        /*!< IBM codepage 437 */
   ENC_CS_IBM775,        /*!< IBM codepage 775 */
   ENC_CS_IBM850,        /*!< IBM codepage 850 */
   ENC_CS_IBM852,        /*!< IBM codepage 852 */
   ENC_CS_IBM858,        /*!< IBM codepage 858 */
   ENC_CS_ISO2022_JP,    /*!< ISO 2022-JP */
   ENC_CS_CESU_8,        /*!< Compatibility Encoding Scheme for UTF-16 */
   ENC_CS_UTF_7,         /*!< UCS Transformation Format 7 bit */
   ENC_CS_UTF_8,         /*!< UCS Transformation Format 8 bit */
   ENC_CS_UTF_16BE       /*!< UCS Transformation Format 16 bit big endian */
};

/*! \brief IDs for supported MIME content disposition */
enum enc_mime_cd
{
   ENC_CD_UNKNOWN,
   ENC_CD_INLINE,
   ENC_CD_ATTACHMENT
};

/*! \brief MIME content type information */
struct enc_mime_ct
{
   enum enc_mime_ct_type  type;        /*!< Content type ID */
   enum enc_mime_ct_subtype  subtype;  /*!< Content subtype ID */
   enum enc_mime_cs  charset;          /*!< Character set ID */
   /*! Content type flags (use \c ENC_CT_FLAG_* constants) */
   unsigned int  flags;
};

/*! \brief Locations of MIME multipart entities */
struct enc_mime_mpe
{
   const char*  start;   /*!< Start index of entity */
   size_t       len;     /*!< Length of entity */
};

/*! \brief URI schemes */
enum enc_uri_scheme
{
   ENC_URI_SCHEME_INVALID,
   ENC_URI_SCHEME_HTTP,     /*!< Hyper Text Transfer Protocol */
   ENC_URI_SCHEME_FTP,      /*!< File Transfer Protocol */
   ENC_URI_SCHEME_NEWS,     /*!< News group or article */
   ENC_URI_SCHEME_MAILTO    /*!< E-mail */
};

/*! \brief Wildmat array element (for RFC 3977 wildmat-pattern) */
struct enc_wm_pattern
{
   int  negate;
   const char*  ere;
};


/* ========================================================================== */
/* Constants */

/*! \brief Buffer size for content transfer encoding name strings */
#define ENC_CTE_BUFLEN  (size_t) 32

/*! \brief Buffer size for character set name strings */
#define ENC_CS_BUFLEN  (size_t) 32

/*! \name Content type flags according to RFC 3676
 *
 * The flags can be bitwise ORed together.
 *
 * \note The parameter "InsLine" is experimental (not defined in RFC 3676).
 */
/*! @{ */
#define ENC_CT_FLAG_FLOWED   0x01U
#define ENC_CT_FLAG_DELSP    0x02U
#define ENC_CT_FLAG_INSLINE  0x04U
/*! @} */

/*! \brief Buffer size for multipart boundary strings
 *
 * RFC 2046 limits the length of the boundary delimiter to 70 characters.
 * There are always two hyphens before the boundary delimiter.
 * At the end of the multipart body, there are 2 hyphens after the boundary
 * delimiter.
 * Finally we need space for the NUL character to terminate the string.
 * Result: 70 + 2 + 2 + 1 = 75
 */
#define ENC_BO_BUFLEN  (size_t) 75

/*! \brief Delimiter string to print between article header and body parts */
#define ENC_DELIMITER \
   "________________________________________" \
   "_______________________________________|" "\n" \
   "                                        " \
   "                                       |" "\n"

/*! @} */


/* ========================================================================== */
/* Function prototypes */

const char*  enc_create_name_addr(const char*, size_t);
unsigned long int  enc_lines_decode(const char*);
void  enc_convert_lines_to_string(char*, unsigned long int);
core_time_t  enc_timestamp_decode(const char*);
int  enc_convert_posix_to_iso8601(char*, core_time_t);
int  enc_get_iso8601_utc(char*);
int  enc_convert_iso8601_to_posix(core_time_t*, const char*);
int  enc_convert_iso8601_to_timestamp(const char**, const char*);
int  enc_convert_anum_to_ascii(char[17], size_t*, core_anum_t);
int  enc_convert_ascii_to_anum(core_anum_t*, const char*, int);
int  enc_convert_octet_to_hex(char*, unsigned int);
void  enc_rot13(char*);
const char*  enc_extract_addr_spec(const char*);
int  enc_ascii_check(const char*);
int  enc_ascii_check_alpha(const char*);
int  enc_ascii_check_digit(const char*);
int  enc_ascii_check_printable(const char*);
void  enc_ascii_convert_to_printable(char*);
void  enc_ascii_convert_distribution(char*);
int  enc_uc_check_utf8(const char*);
const char*  enc_uc_repair_utf8(const char*);
void  enc_uc_encode_utf8(char*, size_t*, long int*, size_t*);
int  enc_create_wildmat(struct enc_wm_pattern**, const char*);
void  enc_destroy_wildmat(struct enc_wm_pattern**, int);
const char*  enc_convert_canonical_to_posix(const char*, int, int);
const char*  enc_convert_posix_to_canonical(const char*);
const char*  enc_convert_to_utf8_nfc(enum enc_mime_cs, const char*);
const char*  enc_convert_to_8bit(enum enc_mime_cs*, const char*, const char**);
int  enc_mime_encode_base64(const char**, const char*, size_t);
int  enc_mime_word_encode(const char**, const char*, size_t);
int  enc_mime_word_decode(const char**, const char*);
int  enc_mime_para_decode(const char**, const char*, int);
void  enc_mime_get_ct(struct enc_mime_ct*, const char*, char*);
enum enc_mime_cte  enc_mime_get_cte(const char*);
void  enc_mime_get_cd(const char*, enum enc_mime_cd*, const char**);
int enc_mime_save_to_file(const char*, enum enc_mime_cte, const char*);
const char*  enc_mime_decode(enum enc_mime_cte, enum enc_mime_cs, const char*);
const char*  enc_mime_flowed_decode(const char*, unsigned int, unsigned int);
size_t  enc_mime_message(const char*, size_t, struct enc_mime_mpe**);
size_t  enc_mime_multipart(const char*, const char*, struct enc_mime_mpe**);
int  enc_percent_decode(char*, int);
const char*  enc_uri_percent_encode(const char*, enum enc_uri_scheme);
int  enc_uc_search(const char*, size_t, const char*, size_t*, size_t*);
void  enc_free(void*);


#endif  /* ENCODING_H */

/* EOF */
