/* $Cambridge: hermes/src/prayer/shared/request.h,v 1.3 2008/09/16 09:59:58 dpc22 Exp $ */
/************************************************
 *    Prayer - a Webmail Interface              *
 ************************************************/

/* Copyright (c) University of Cambridge 2000 - 2008 */
/* See the file NOTICE for conditions of use and distribution. */

/* Methods to process HTTP header */

typedef enum {
    UNKNOWN,
    OPTIONS,
    GET,
    HEAD,
    POST,
    PUT,
    DELETE,
    TRACE,
    CONNECT
} HTTP_METHOD;

typedef enum {
    REQUEST_METHOD,
    REQUEST_HDRS,
    REQUEST_BODY_SIMPLE,
    REQUEST_BODY_CHUNKED,
    REQUEST_COMPLETE
} REQUEST_STATE;

typedef enum {
    CHUNK_HDR,
    CHUNK_BODY,
    CHUNK_TRAILER,
    CHUNK_COMPLETE
} CHUNK_STATE;

struct request {
    /* Common fields */
    struct pool *pool;          /* Allocate memory from this pool */
    struct config *config;      /* Global configuration           */
    struct iostream *stream;    /* Bidirection pipe with client   */

    /* Input buffer */

    struct buffer *read_buffer; /* Incoming request */
    struct buffer *chunked;     /* Decoded version of chunked encoding */

    REQUEST_STATE state;        /* State of current request        */
    unsigned long method_size;  /* Offset to hdrs in read_buffer   */
    unsigned long hdrs_offset;  /* Offset to hdrs in read_buffer   */
    unsigned long hdrs_size;    /* Size of hdrs in read_buffer     */
    unsigned long hdrs_crlfs;   /* Size of hdrs in read_buffer     */
    unsigned long body_offset;  /* Offset to body in read_buffer   */
    unsigned long body_current; /* Current number of bytes fetched */
    unsigned long body_size;    /* Size of body in read_buffer     */
    CHUNK_STATE chunk_state;    /* State of current chunk          */
    unsigned long chunk_hdr_offset;     /* Offset for current chunk hdr    */
    unsigned long chunk_hdr_current;    /* Offset for current chunk hdr    */
    unsigned long chunk_hdr_size;       /* Size of current chunk header    */
    unsigned long chunk_body_offset;    /* Offset for current chunk hdr    */
    unsigned long chunk_body_current;   /* Offset for current chunk hdr    */
    unsigned long chunk_body_size;      /* Size of current chunk header    */
    unsigned long chunk_trlr_offset;    /* Offset to trailers, if used     */
    unsigned long chunk_trlr_size;      /* Size of trailer, if used        */
    unsigned long chunk_trlr_crlfs;     /* CRLFs in trailer, if used       */
    BOOL frontend;              /* Frontend server                 */
    BOOL preserve;              /* Preserve headers for proxy or telemetry */
    BOOL iseof;                 /* Reached EOF                     */
    BOOL error;                 /* Request generated error         */

    /* Decoded request */

    char *request;              /* Copy of request line          */
    unsigned long major;        /* Major HTTP revision           */
    unsigned long minor;        /* Minor HTTP revision           */
    char *url;                  /* Copy of original request URL  */
    char *url_host;             /* Host component in request URL */
    char *url_port;             /* Port component in request URL */
    char *url_path;             /* Path component in request URL */
    int argc;                   /* Number of components in path  */
    char **argv;                /* Individual components in path */
    char *get_suffix;           /* String following '?' in GET request */
    char *log_entry;            /* Replaces HTTP request in logs */

    /* Processed request */

    HTTP_METHOD method;         /* HTTP method */
    struct assoc *hdrs;         /* Headers used in this request */
    struct assoc *form;         /* Hash key->value for GET or POST request */

    /* Response information */
    unsigned long status;       /* Status of this request        */
    BOOL dump;                  /* XXX For templates */
    BOOL telemetry;             /* Send headers in telemetry     */
    BOOL telemetry_all;         /* Send everything in telemetry  */
    int telemetry_fd;           /* File descriptor for telemetry */
    struct buffer *response_hdrs;       /* Pending response              */
    struct buffer *write_buffer;        /* Body of Pending response      */
    struct buffer *gzip_buffer; /* Compressed response           */
    struct user_agent *user_agent;      /* Link to user-agent info       */
    BOOL use_http_1_1;          /* Using HTTP 1.1 in response    */
    BOOL persist;               /* Keep connection open after request */
    BOOL use_utf8;              /* Use UTF-8 in output           */
    BOOL allow_gzip;            /* Allow gzip encoding           */
    BOOL use_gzip;              /* Use gzip in output            */
    BOOL use_x_gzip;            /* Use x-gzip in output          */
};

#define REQUEST_PREFERRED_BLOCK_SIZE (8192)

struct request *request_create(struct config *config,
                               struct iostream *stream, BOOL isproxy);

void request_free(struct request *request);

void request_dump(struct request *request);

void request_telemetry(struct request *request, int fd, BOOL all);

void request_forge_redirect(struct request *request, char *url);

BOOL request_parse(struct request *request);

BOOL request_complete(struct request *request);

BOOL
request_decode_post_multipart(struct request *request,
                              struct assoc *hdrs, char **start,
                              char **end);

void request_decode_form(struct request *request);

void request_parse_argv(struct request *request);

void request_parse_charset(struct request *request);

void request_parse_encoding(struct request *request);

int request_test_referer(struct request *request, char *hostname);
