#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_MULTIPART,     /*!< Content consists of multiple parts */
   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_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,     /*!< ISO8859-1 */
   ENC_CS_ISO8859_2,     /*!< ISO8859-2 */
   ENC_CS_ISO8859_3,     /*!< ISO8859-3 */
   ENC_CS_ISO8859_4,     /*!< ISO8859-4 */
   ENC_CS_ISO8859_5,     /*!< ISO8859-5 */
   ENC_CS_ISO8859_6,     /*!< ISO8859-6 */
   ENC_CS_ISO8859_7,     /*!< ISO8859-7 */
   ENC_CS_ISO8859_8,     /*!< ISO8859-8 */
   ENC_CS_ISO8859_9,     /*!< ISO8859-9 */
   ENC_CS_ISO8859_10,    /*!< ISO8859-10 */
   ENC_CS_ISO8859_11,    /*!< ISO8859-11 */
   ENC_CS_ISO8859_13,    /*!< ISO8859-13 */
   ENC_CS_ISO8859_14,    /*!< ISO8859-14 */
   ENC_CS_ISO8859_15,    /*!< ISO8859-15 */
   ENC_CS_ISO8859_16,    /*!< ISO8859-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 version) */
   ENC_CS_WINDOWS_1250,  /*!< Windows codepage 1250 */
   ENC_CS_WINDOWS_1251,  /*!< Windows codepage 1251 */
   ENC_CS_WINDOWS_1252,  /*!< Windows codepage 1252 */
   ENC_CS_WINDOWS_1256,  /*!< Windows codepage 1256 */
   ENC_CS_IBM437,        /*!< IBM codepage 437 */
   ENC_CS_IBM850,        /*!< IBM codepage 850 */
   ENC_CS_IBM858,        /*!< IBM codepage 858 */
   ENC_CS_ISO2022_JP,    /*!< ISO2022-JP */
   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 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 RFC3977 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 RFC3676
 *
 * The flags can be bitwise ORed together.
 */
/* @{ */
#define ENC_CT_FLAG_FLOWED  0x01U
#define ENC_CT_FLAG_DELSP   0x02U
/* @} */

/*! \brief MIME word encoder folding behaviour
 *
 * If this is defined to nonzero, all lines of RFC2047 compliant header fields
 * that contain MIME encoded words are folded before 76 characters. Otherwise
 * all lines that contain no encoded-words are not folded before 998 characters.
 *
 * RFC2047 is ambigous regarding this rule:
 * <br>
 * https://tools.ietf.org/html/rfc2047#section-2
 * <br>
 * The default value 1 is safe in any case. Please read section 2, paragraph 5
 * carefully before redefining this to 0!
 */
#define ENC_MIME_HEADER_FOLD_ASCII_LINES  1

/*! \brief Buffer size for multipart boundary strings
 *
 * RFC2046 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 */

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


#endif  /* ENCODING_H */

/* EOF */
