aboutsummaryrefslogtreecommitdiff
/* C */
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <ctype.h>
#include <limits.h>
#include <stdlib.h>

/* Losedows */
#include <fileapi.h>

/* local */
#include "utilities.h"
#include "iniparser.h"

#define BUFSIZE 4096

static const char *get_string(dictionary *ini, const char *key)
{
	const char *value;
	char *new_string;
	size_t length;

	value = iniparser_getstring(ini, key, NULL);
	if (!value)
		return NULL;

	length = strlen(value);
	new_string = dirtyalloc(length + 1);
	memcpy(new_string, value, length + 1);
	return new_string;
}

static enum bool_param get_bool(dictionary *ini, const char *key)
{
	int value = iniparser_getboolean(ini, key, 2);

	return value == 2 ? PARAM_NOT_GIVEN :
	  value == 1 ? PARAM_YES : PARAM_NO;
}

static size_t get_msg(dictionary *ini, const char **dest)
{
	int nkeys, i;
	const char **keys;
	const char *line;
	size_t msg_size = 0;
	char *msg, *msg_pos;

	nkeys = iniparser_getsecnkeys(ini, "MSG");
	if (nkeys == 0) {
		*dest = NULL;
		return 0;
	}

	keys = dirtyalloc(nkeys * sizeof(const char*));
	iniparser_getseckeys(ini, "MSG", keys);

	for (i = 0; i < nkeys; i++)
		msg_size += strlen(iniparser_getstring(ini, keys[i], "")) + 1;

	msg = dirtyalloc(msg_size);
	msg_pos = msg;

	for (i = 0; i < nkeys; i++) {
		line = iniparser_getstring(ini, keys[i], "");
		while (*line)
			*(msg_pos++) = *(line++);
		*(msg_pos++) = '\n';
	}

	free(keys);
	*(msg_pos - 1) = '\0';
	*dest = msg;

	/* Exclude terminating null byte from returned size */
	return msg_size - 1;
}

static size_t get_list(dictionary *ini, const char *section,
		       const char ***dest)
{
	int nkeys, i;
	const char **keys, **items;
	const char *line;
	char *copied_line;
	size_t length;

	nkeys = iniparser_getsecnkeys(ini, section);

	if (nkeys == 0) {
		*dest = NULL;
		return 0;
	}

	keys = dirtyalloc(nkeys * sizeof(const char *));
	items = dirtyalloc(nkeys * sizeof(const char *));
	iniparser_getseckeys(ini, section, keys);

	for (i = 0; i < nkeys; i++) {
		line = iniparser_getstring(ini, keys[i], "");
		length = strlen(line) + 1;
		copied_line = dirtyalloc(length);
		memcpy(copied_line, line, length);
		items[i] = copied_line;
	}

	free(keys);
	*dest = items;
	return nkeys;
}

static dictionary *check_file_and_load_ini(const char *filename)
{
	int retval;
	char full_pathname[BUFSIZE];
	dictionary *ini;

	retval = GetFullPathName(filename, BUFSIZE, full_pathname, NULL);

	if (retval == 0)
		FAIL(MSG_CONF_PATH_EXPAND_FAIL, filename);

	if (access(full_pathname, F_OK) != 0)
		FAIL(MSG_CONF_NOT_EXIST, full_pathname);

	if (access(full_pathname, R_OK) != 0)
		FAIL(MSG_CONF_NOT_READABLE, full_pathname);

	ini = iniparser_load(full_pathname);

	if (!ini)
		FAIL(MSG_INVALID_INI_FILE, full_pathname);

	return ini;
}

void print_config(struct config *config);

void read_config(const char *filename, struct config *config)
{
	dictionary *ini;

	ini = check_file_and_load_ini(filename);

	memset(config, '\0', sizeof(struct config)); /* not really needed */

	config->host      = get_string(ini, "SERVER:host");
	config->login     = get_string(ini, "SERVER:login");
	config->password  = get_string(ini, "SERVER:password");
	config->dest_dir  = get_string(ini, "SERVER:outputdir");

	config->reply_to  = get_string(ini, "MAIL:replyto");
	config->from      = get_string(ini, "MAIL:from");

	if (!config->reply_to)
		config->reply_to  = get_string(ini, "SERVER:replyto");
	if (!config->from)
		config->from  = get_string(ini, "SERVER:from");

	config->subject   = get_string(ini, "MAIL:subject");

	config->use_SSL   = get_bool(ini, "SERVER:ssl");
	config->use_AUTH  = get_bool(ini, "SERVER:auth");
	config->del_msgs  = get_bool(ini, "SERVER:delete_msg");
	config->save_body = get_bool(ini, "SERVER:save_body");
	config->save_subj = get_bool(ini, "SERVER:save_subject");
	config->port_POP3 = iniparser_getint(ini, "SERVER:port_pop3", -1);
	config->port_SMTP = iniparser_getint(ini, "SERVER:port_smtp", -1);
	config->timeout   = iniparser_getint(ini, "SERVER:timeout",   1000000);
	config->nfiles    = get_list(ini, "FILES", &config->files);
	config->nto       = get_list(ini, "CC",    &config->to);
	config->msg_size  = get_msg (ini, &config->msg_body);

	iniparser_freedict(ini);

	/* print_config(config); */
}

void get_config(int argc, const char **argv, struct config *config)
{
	int config_arg_idx = 1;

	if (argc < 2)
		goto bad_args;

	if (strcmp(argv[1], "--wide-chars") == 0) {
		config_arg_idx = 2;
		iniparser_set_fgetc_impl(provisional_wide_char_fgetc);
	}

	if (argc <= config_arg_idx)
		goto bad_args;

	iniparser_set_error_callback(dummy_errback);
	iniparser_set_process_multiline(false);
	read_config(argv[config_arg_idx], config);
	return;

bad_args:
	FAIL(MSG_BAD_ARGS_NUM, argv[0]);
}

void free_config(struct config *config)
{
	//TODO
}

void print_config(struct config *config)
{
	size_t i;

	if (config->host)
		printf("host: %s\n", config->host);
	else
		puts("host not set");

	if (config->login)
		printf("login: %s\n", config->login);
	else
		puts("login not set");

	if (config->password)
		printf("password: %s\n", config->password);
	else
		puts("password not set");

	if (config->reply_to)
		printf("reply_to: %s\n", config->reply_to);
	else
		puts("reply_to not set");

	if (config->from)
		printf("from: %s\n", config->from);
	else
		puts("from not set");

	if (config->dest_dir)
		printf("dest_dir: %s\n", config->dest_dir);
	else
		puts("dest_dir not set");

	if (config->subject)
		printf("subject: %s\n", config->subject);
	else
		puts("subject not set");

	printf("SSL: %s\n", config->use_SSL ? "True" : "False");

	printf("AUTH: %s\n", config->use_AUTH ? "True" : "False");

	printf("port_POP3: %d\n", config->port_POP3);

	printf("port_SMTP: %d\n", config->port_SMTP);

	printf("timeout: %d\n", config->timeout);

	printf("delete: %s\n", config->del_msgs ? "True" : "False");

	printf("save_body: %s\n", config->save_body ? "True" : "False");

	printf("save_subject: %s\n", config->save_subj ? "True" : "False");

	if (config->nfiles) {
		puts("files:");
		for (i = 0; i < config->nfiles; i++)
			printf("  %s\n", config->files[i]);
	} else {
		puts("no files");
	}

	if (config->nto) {
		puts("recipients:");
		for (i = 0; i < config->nto; i++)
			printf("  %s\n", config->to[i]);
	} else {
		puts("no recipients");
	}

	if (config->msg_body) {
		printf("message (length %lu):\n",
		       (unsigned long)config->msg_size);
		puts(config->msg_body);
	} else {
		puts("no message");
	}
}