#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <err.h>

#include "mohawk.h"
#include "dump.h"
#include "include.h"

void dump_ai(struct vhost *);
const char* on_off(bool);
void dump_vhost(struct vhost *, int);

void
dump_ai(struct vhost *vh)
{
	struct mohawk_address_info *ai;
	char hostname[NI_MAXHOST];
	char service[NI_MAXSERV];
	int error;

	if (!conf.debug && SLIST_EMPTY(&vh->address_infos))
		return;

	printf("\tlisten: ");
	SLIST_FOREACH(ai, &vh->address_infos, entry) {
		if ((error = getnameinfo(ai->ai->ai_addr, ai->ai->ai_addrlen,
			                     hostname, sizeof(hostname),
			                     service, sizeof(service),
			                     NI_NUMERICHOST | NI_NUMERICSERV)) != 0) {
			warnx("getnameinfo(): %s", gai_strerror(error));
		}
		printf("['%s' '%s'] ", hostname, service);
	}
	printf("\n");
}

const char *
on_off(bool flag)
{
	return flag ? "on" : "off";
}

void
dump_vhost(struct vhost *vh, int is_vhost)
{
	struct mohawk_list *list;
	struct mohawk_hash *hash;
	struct mohawk_network *network;
	struct vhost *location;
	const char *tab = is_vhost ? "\t" : "\t\t";

	if (is_vhost)
		printf("\nVirtual host '%s'\n", vh->host);
	else
		printf("\tLocation: '%s'\n", vh->location);

#define DUMP_BOOL(FIELD) \
	if (conf.debug || vh->FIELD) \
		printf("%s%s: '%s'\n", tab, #FIELD, on_off(vh->FIELD));

#define DUMP_CHAR(FIELD) \
	if (conf.debug || vh->FIELD) \
		printf("%s%s: '%s'\n", tab, #FIELD, vh->FIELD ? vh->FIELD : "");

#define DUMP_INT(FIELD) \
	if (conf.debug || vh->FIELD) \
		printf("%s%s: '%d'\n", tab, #FIELD, vh->FIELD);


	DUMP_CHAR(rootdir);
	DUMP_BOOL(hostname_in_rootdir);
	DUMP_CHAR(auth_path);
	DUMP_CHAR(charset);
	DUMP_CHAR(dirlist_css_url);
	DUMP_CHAR(mohawk_name);
	if (is_vhost)
		DUMP_CHAR(status_url);
	DUMP_BOOL(authentication);
#if defined(HAVE_BLACKLISTD) || defined(HAVE_BLOCKLISTD)
	DUMP_BOOL(auth_blacklistd);
#endif
	DUMP_BOOL(can_quick);
	DUMP_BOOL(cgi_expose_mohawk_version);
	DUMP_BOOL(dirlist);
	DUMP_INT(maxage);
	DUMP_BOOL(x_forwarded_for);
	DUMP_CHAR(email_admin);

#define DUMP_LIST(FIELD) \
	if (conf.debug || !SLIST_EMPTY(&vh->FIELD)) { \
		printf("%s%s: ", tab, #FIELD); \
		SLIST_FOREACH(list, &vh->FIELD, entry) { \
			printf("'%s' ", list->item); \
		} \
		printf("\n"); \
	}

	DUMP_LIST(auth_patterns);
#if defined(HAVE_BLACKLISTD) || defined(HAVE_BLOCKLISTD)
	DUMP_LIST(blacklist_patterns);
#endif
	DUMP_LIST(cgi_patterns);
	DUMP_LIST(index_names);
	DUMP_LIST(no_cgi_maps);
	DUMP_LIST(no_log_patterns);

#define DUMP_HASH(FIELD) \
	if (conf.debug || !SLIST_EMPTY(&vh->FIELD)) { \
		printf("%s%s: ", tab, #FIELD); \
		SLIST_FOREACH(hash, &vh->FIELD, entry) { \
			printf("['%s' => '%s'] ", hash->key, hash->value); \
		} \
		printf("\n"); \
	}

	DUMP_HASH(cgi_env);
	if (conf.debug || vh->cgi_env_count)
		printf("%scgi_env_count: '%d'\n", tab, vh->cgi_env_count);
	DUMP_HASH(cgi_map);

#define DUMP_NETWORK(FIELD) \
	if (conf.debug || !SLIST_EMPTY(&vh->FIELD)) { \
		printf("%s%s: ", tab, #FIELD); \
		SLIST_FOREACH(network, &vh->FIELD, entry) { \
			printf("'%s' ", network->item); \
		} \
		printf("\n"); \
	}

	DUMP_NETWORK(grant_access);

	if (is_vhost) {
		dump_ai(vh);

		if (conf.debug || !SLIST_EMPTY(&vh->locations)) {
			SLIST_FOREACH(location, &vh->locations, entry)
				dump_vhost(location, 0);
		}
	}

	printf("\n");
}

void
dump_config(void)
{
	struct vhost *vh;
	struct mohawk_hash *hash;

	printf("Dump mohawk config:\n\n");
	printf("debug: '%s'\n", on_off(conf.debug));
	if (conf.debug || conf.chroot)
		printf("chroot: '%s'\n", conf.chroot ? conf.chroot : "");
	if (conf.debug || conf.pidfile)
		printf("pidfile: '%s'\n", conf.pidfile ? conf.pidfile : "");
	printf("syslog facility: '%s'\n", conf.syslog_facility);
	printf("user: '%s'\n", conf.user);
#if defined(HAVE_BLACKLISTD) || defined(HAVE_BLOCKLISTD)
	printf("blacklistd: '%s'\n", on_off(conf.blacklistd));
#endif
	printf("mime_type:\n");
	SLIST_FOREACH(hash, &conf.mime_type, entry) {
		printf("\t['%s' => '%s']\n", hash->key, hash->value);
	}
	printf("\n");

	SLIST_FOREACH(vh, &conf.vhosts, entry)
		dump_vhost(vh, 1);

	if (!conf.debug)
		return;

	printf("Dump mohawk default values:\n\n"
"Auth file: '%s'\n"
"Http port: '%s'\n"
"Pid file: '%s'\n"
"Syslog facility: '%s'\n"
"Run as: '%s'\n"
"Max include depth: '%d'\n",
	DEFAULT_AUTH_FILE,
	DEFAULT_HTTP_PORT,
	DEFAULT_PIDFILE,
	DEFAULT_SYSLOG_FACILITY,
	DEFAULT_USER,
	MAX_INCLUDE_DEPTH
	);
}

/* vim: set sw=4 sts=4 ts=4 : */
