/*
 * Copyright (c) 2003-2011
 * Distributed Systems Software.  All rights reserved.
 * See the file LICENSE for redistribution information.
 *
 * $Id: http.h 2514 2011-09-23 18:30:55Z brachman $
 */

/*****************************************************************************
 * COPYRIGHT AND PERMISSION NOTICE
 * 
 * Copyright (c) 2001-2003 The Queen in Right of Canada
 * 
 * All rights reserved.
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation 
 * the rights to use, copy, modify, merge, publish, distribute, and/or sell
 * copies of the Software, and to permit persons to whom the Software is 
 * furnished to do so, provided that the above copyright notice(s) and this
 * permission notice appear in all copies of the Software and that both the
 * above copyright notice(s) and this permission notice appear in supporting
 * documentation.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE 
 * BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES,
 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
 * SOFTWARE.
 * 
 * Except as contained in this notice, the name of a copyright holder shall not
 * be used in advertising or otherwise to promote the sale, use or other
 * dealings in this Software without prior written authorization of the
 * copyright holder.
 ***************************************************************************/

#ifndef _HTTP_H_
#define _HTTP_H_

#include "ds.h"
#include "kwv.h"

enum {
  HTTP_DEFAULT_PORT            = 80,
  HTTP_DEFAULT_SSL_PORT        = 443,
  HTTP_MAX_RESPONSE_HEADER_LEN = 16384,
  HTTP_MAX_REDIRECTS           = 6
};

typedef enum {
  HTTP_GET_METHOD     = 1,
  HTTP_POST_METHOD    = 2,
  HTTP_HEAD_METHOD    = 3,
  HTTP_PUT_METHOD     = 4,
  HTTP_DELETE_METHOD  = 5,
  HTTP_OPTIONS_METHOD = 6,
  HTTP_TRACE_METHOD   = 7,
  HTTP_CONNECT_METHOD = 8,
  HTTP_UNKNOWN_METHOD = 9
} Http_method;

typedef struct Http_params {
  char *name;
  char *value;
  char *filename;
  int encoded;
} Http_params;

typedef enum {
  HTTP_SSL_OFF        = 0,		/* Do not use SSL */
  HTTP_SSL_URL_SCHEME = 1,		/* Use SSL only if url scheme is https */
  HTTP_SSL_ON         = 2,		/* Use SSL regardless of url scheme */
  HTTP_SSL_ON_VERIFY  = 3		/* Use SSL and verify peer cert */
} Http_connection_mode;

typedef struct Uri_query_arg {
  char *name;
  char *value;
} Uri_query_arg;

typedef struct Uri {
  char *uri;		/* The URI that was parsed */
  char *scheme;		/* Canonicalized to lowercase by uri_parse() */
  char *authority;
  char *host;		/* Canonicalized to lowercase by uri_parse() */
  char *userinfo;
  int host_is_dn;	/* Non-zero if host is a domain name */
  int host_is_ip;	/* Non-zero if host is an IP address */
  in_port_t port;	/* The port number, if not 0 */
  char *port_given;	/* The port string as specified in the URI, if any */
  char *server;		/* Host + port, when available and syntactically valid */
  char *path;		/* Decoded from the original URI */
  Dsvec *path_parts;	/* If non-NULL, components of original URI path */
  char *query_string;	/* If non-NULL, the original (encoded) query string */
  Dsvec *query_args;	/* If non-NULL, parsed and decoded query args */
  char *fragment;		/* If non-NULL, decoded fragment component */
} Uri;

typedef struct Proxy {
  char *hostname;
  char *portstr;
  in_port_t portnum;
} Proxy;

typedef struct Http_version {
  unsigned int major;
  unsigned int minor;
} Http_version;

typedef struct Http {
  int sd;
  Http_version *version;
  FILE *fp;
  char *content_type;
  Dsvec *ssl_args;
  int ssl_read_fd;
  int ssl_write_fd;
  int ssl_error_fd;
  char **ssl_env;
  Http_params *post_params;
  int npost_params;
  Dsvec *cookie_args;
  Dsvec *message_headers;	/* User-specified request headers */
  Ds *message_body;
  int in_data;
  Uri *uri;
  Http_method method;		/* RFC 2616, 9 */
  int server_options;
  Dsvec *response_headers;
  Kwv *response_kwv;
  char *status_line;
  int status_code;			/* RFC 2616, 6.1.1 & 10 */
  Proxy proxy;
} Http;

#ifdef __cplusplus
extern "C" {
#endif

extern Http *http_init(Http_version *version);
extern Http_params *http_param(Dsvec *dsv_params, char *name, char *value,
							   char *filename, int encoded);
extern int http_invoke(char *url, Http_method method,
					   Http_connection_mode mode,
					   int nparams, Http_params *params, Ds *body,
					   char **cookies,
					   char **reply, int *reply_len, int *status_code,
					   Dsvec *response_headers);
extern int http_get(char *url, Dsvec *more_args, char **cookies,
					char **reply, int *reply_len,
					int *status_code, Dsvec *response_headers);
extern int http_post(char *url, Dsvec *post_args, char **cookies, char **reply,
					 int *reply_len, int *status_code, Dsvec *response_headers);
extern Http *http_invoke_stream(char *url, Http_method method,
								Http_connection_mode mode,
								int nparams, Http_params *params, Ds *body,
								char **cookies, FILE **fp, int *status_code,
								Dsvec *response_headers, char **errmsg);
extern int http_invoke_request(Http *h, char *url, Http_connection_mode mode,
							   char **errmsg);
extern int http_get_response_body(Http *h, char **reply, int *reply_len);
extern void http_set_cookies(Http *, char **argv);
extern void http_set_post_params(Http *, int n, Http_params *p);
extern void http_set_ssl_params(Http *, Dsvec *v);
extern int http_request(Http *h, char *url);
extern void http_close(Http *h);
extern int http_read_response_body(Http *h, Ds *ds);
extern FILE *http_read_response_stream(Http *h);
extern Http_version *http_parse_version(char *version_str);

extern char *http_method_to_string(Http_method method);
extern Http_method http_string_to_method(char *m);
extern char *http_get_user_agent_string(void);
extern char *http_set_user_agent_string(char *str);

extern Uri *http_parse_uri(char *);
extern Uri *uri_init(Uri *u);
extern int uri_pqf(char *uri, char **path, char **query, char **fragment);
extern Uri *uri_parse(char *str);
extern int uri_parse_path(Uri *uri, char *str);
extern char *uri_parse_hier_part(Uri *url, char *str, int has_authority);
extern char *uri_scheme_authority(Uri *uri);
extern int uri_compare(Uri *uri1, Uri *uri2, int *match);
extern int uri_is_valid_path_part(char *part);
extern char *uri_to_str(Uri *uri);
extern Dsvec *parse_query_string(char *query_string);
extern Kwv *query_args_to_kwv(Dsvec *qa);
extern char *kwv_to_query_string(Kwv *kwv);

extern char *percent_encode_chars(char *url, char *chars_to_escape,
								  size_t url_len);
extern char *percent_encode_other_chars(char *url, char *chars_not_to_escape,
										size_t url_len);
extern char *url_encode(char *url, size_t len);
extern char *url_decode(char *url, int *non_printable, Ds **url_dsp);
extern char *percent_encode_chars(char *url, char *chars, size_t url_len);
extern int contains_invalid_url_char(char *str);

#ifdef __cplusplus
}
#endif

#endif
