/***************************************************************************
 *
 * Copyright (c) 2000 BalaBit IT Ltd, Budapest, Hungary
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * $Id: http.h,v 1.20.2.1.2.2 2001/09/04 10:12:47 bazsi Exp $
 *
 * Author: Balazs Scheidler <bazsi@balabit.hu>
 * Auditor: 
 * Last audited version: 
 * Notes:
 *   Based on the code by: Viktor Peter Kovacs <vps__@freemail.hu>
 *
 ***************************************************************************/

#ifndef ZORP_MODULES_HTTP_H_INCLUDED
#define ZORP_MODULES_HTTP_H_INCLUDED

#include <zorp/zorp.h>
#include <zorp/proxy.h>
#include <zorp/readline.h>
#include <zorp/authorization.h>
#include <zorp/dimhash.h>

#define HTTP_REQ_ACCEPT       1
#define HTTP_REQ_DENY         2
#define HTTP_REQ_REJECT       3
#define HTTP_REQ_ABORT        4
#define HTTP_REQ_POLICY       6

#define HTTP_RSP_ACCEPT       1
#define HTTP_RSP_DENY         2
#define HTTP_RSP_REJECT       3
#define HTTP_RSP_ABORT        4
#define HTTP_RSP_POLICY       6

#define HTTP_HDR_ACCEPT        1
#define HTTP_HDR_ABORT         4
#define HTTP_HDR_DROP          5
#define HTTP_HDR_POLICY        6
#define HTTP_HDR_CHANGE_NAME   100
#define HTTP_HDR_CHANGE_VALUE  101
#define HTTP_HDR_CHANGE_BOTH   102
#define HTTP_HDR_CHANGE_REGEXP 103
#define HTTP_HDR_INSERT        104
#define HTTP_HDR_REPLACE       105

#define HTTP_CONNECTION_CLOSE		0
#define HTTP_CONNECTION_KEEPALIVE	1

#define HTTP_REQTYPE_SERVER        0     /* simple server request */
#define HTTP_REQTYPE_PROXY         1     /* proxy request */

#define HTTP_REQ_FLG_TRANSFER   1   //supported
#define HTTP_REQ_FLG_STOP       2   //unsupported
#define HTTP_REQ_FLG_DATA       4   //data follows
#define HTTP_REQ_FLG_HEAD       8   //no resp data requested
#define HTTP_REQ_FLG_CLOSE      16  //close connection after transfer
#define HTTP_REQ_FLG_ASTERIX    32  //use '*' instead of '/' if no url
#define HTTP_REQ_FLG_CONNECT    64  //connect as transparent

#define HTTP_RESP_FLG_TRANSFER  1   //supported
#define HTTP_RESP_FLG_STOP      2   //unsupported
#define HTTP_RESP_FLG_CONTINUE  4   //continue (unused)
#define HTTP_RESP_FLG_DATA      8   //data follows
#define HTTP_RESP_FLG_DATA_COND 16  //if not HEAD
#define HTTP_RESP_FLG_CLOSE     32  //close connection after transfer


#define HTTP_MAX_LINE           4096
#define HTTP_MAX_URL            4096
#define HTTP_BLOCKSIZE		4096

#define HTTP_MSG_OK             0
#define HTTP_MSG_CLIENT_SYNTAX  1
#define HTTP_MSG_SERVER_SYNTAX  2
#define HTTP_MSG_POLICY_SYNTAX  3
#define HTTP_MSG_POLICY_VIOLATION 4
#define HTTP_MSG_INVALID_URL    5
#define HTTP_MSG_CONNECT_ERROR  6
#define HTTP_MSG_IO_ERROR	7
#define HTTP_MSG_AUTH_REQUIRED  8
#define HTTP_MSG_CLIENT_TIMEOUT 9
#define HTTP_MSG_SERVER_TIMEOUT 10
#define HTTP_MSG_DEFAULT        11

typedef struct _HttpProxy
{
  ZProxy super;
  ZReadLine *readline[EP_MAX];
  guint timeout;
  guint timeout_request;

  GString *headers[EP_MAX];
  guint max_header_lines;
  
  GString *current_header_name, *current_header_value;
  
  ZAuthorization *auth;
  gint auth_inband_supported;
  GString *auth_realm;
  GString *old_auth_header;

  gchar request_method[16];
  guint request_flags;
  GString *request_url;
  GString *url_proto;
  GString *url_username;
  GString *url_passwd;
  GString *url_host;
  gint url_port;
  GString *url_file;
  gchar request_version[16];
  guint request_type;
  GString *target_port_range;

  gchar connected_server[256];
  guint connected_port;

  gchar remote_server[256];
  guint remote_port;

  guint default_port;
  
  gchar response_version[16];
  gchar response[4];
  guint response_flags;
  guint response_code;
  gchar response_msg[256];
  
  gboolean connection_mode;        /* 0:close 1:keep-alive */
  gboolean transparent_mode;       /* 0:non-transparent 1:transparent */
  gboolean permit_server_requests;
  gboolean permit_proxy_requests;

  GString *parent_proxy;        /* address, or hostname of the parent proxy, if empty direct connection is used */
  guint parent_proxy_port;

  gboolean rewrite_host_header;   /* rewrite host header when redirection is done */
  gboolean require_host_header;   /* require the existance of the Host: header */
  gboolean permit_null_response;  /* permit responses with no terminating CRLF and data */
  gboolean strict_header_checking; /* 0: accept rfc incompliant headers, 1: require them */

  guint proto_version;          /* version (updated by request and response) : 0x major minor (0x0009 0x0100 0x0101) */

  gint max_line_length;
  gint max_hostname_length;
  gint max_url_length;
  gint max_keepalive_requests;
  gint request_count;

  GHashTable *request_method_policy;     // policy chain to process on request methods
  GHashTable *request_header_policy;     // policy chain to process on request headers
  ZDimHashTable *response_policy;           // policy chain to process on response codes
  GHashTable *response_header_policy;    // policy chain to process on response headers

  int error_code;
  int error_status;
  GString *error_info;
  GString *error_headers;
  
} HttpProxy;

typedef gboolean (*HttpTransferFilter)(HttpProxy *self, gint from, gint to, gint content_length);

typedef guint (*HttpHeaderFilter)(HttpProxy *self, GString *header_name, GString *header_value);

gboolean http_read(HttpProxy *self, int side, gchar *buf, size_t buflen, guint *bytes_read);
gboolean http_write(HttpProxy *self, int side, gchar *buf, size_t buflen);

gboolean http_transfer_filter_copy(HttpProxy *self, int from, int to, gint content_length);
gboolean http_transfer_filter_chunked(HttpProxy *self, int from, int to, gint content_length);

int http_proto_request_lookup(char *req);
int http_proto_response_lookup(char *resp);

gboolean
http_split_url(gchar *url, 
	       gchar **proto, guint *proto_len,
	       gchar **user, guint *user_len,
	       gchar **passwd, guint *passwd_len,
	       gchar **host, guint *host_len,
	       guint *port,
	       gchar **file, guint *file_len);

gboolean
http_check_url(gchar *str);

gboolean
http_header_lookup(GString *headers, gchar *what, gchar **result, guint *length, int valueonly);


#endif
