#include "conf.h"

int8_t copy_new_mem(char *src, int src_len, char **dest)
{
    *dest = (char *)malloc(src_len + 1);
    if (*dest == NULL)
        return 1;
    memcpy(*dest, src, src_len);
    *((*dest) + src_len) = '\0';

    return 0;
}

/* 在content中，设置变量(var)的首地址，值(val)的位置首地址和末地址，返回下一行指针 */
static char *set_var_val_lineEnd(char *content, char **var, char **val_begin, char **val_end)
{

    char *p, *pn, *lineEnd;
    ;
    int val_len;

    while (1) {
        if (content == NULL)
            return NULL;

        for (; *content == ' ' || *content == '\t' || *content == '\r' || *content == '\n'; content++) ;
        if (*content == '\0')
            return NULL;
        *var = content;
        pn = strchr(content, '\n');
        p = strchr(content, '=');
        if (p == NULL) {
            if (pn) {
                content = pn + 1;
                continue;
            } else
                return NULL;
        }
        content = p;
        //将变量以\0结束
        for (p--; *p == ' ' || *p == '\t'; p--) ;
        *(p + 1) = '\0';
        //值的首地址
        for (content++; *content == ' ' || *content == '\t'; content++) ;
        if (*content == '\0')
            return NULL;
        //双引号引起来的值支持换行
        if (*content == '"') {
            *val_begin = content + 1;
            *val_end = strstr(*val_begin, "\";");
            if (*val_end != NULL)
                break;
        } else
            *val_begin = content;
        *val_end = strchr(content, ';');
        if (pn && *val_end > pn) {
            content = pn + 1;
            continue;
        }
        break;
    }

    if (*val_end) {
        **val_end = '\0';
        val_len = *val_end - *val_begin;
        lineEnd = *val_end;
    } else {
        val_len = strlen(*val_begin);
        *val_end = lineEnd = *val_begin + val_len;
    }
    *val_end = *val_begin + val_len;
    //printf("var[%s]\nbegin[%s]\n\n", *var, *val_begin);
    return lineEnd;
}

static void parse_global_module(char *content, conf * conf)
{
    char *var, *val_begin, *val_end, *lineEnd;
    int val_begin_len;

    while ((lineEnd = set_var_val_lineEnd(content, &var, &val_begin, &val_end)) != NULL) {
        if (strcasecmp(var, "DAEMON") == 0) {
            val_begin_len = val_end - val_begin;

            if (copy_new_mem(val_begin, val_begin_len, &conf->DAEMON) != 0)
                return;
        }

        if (strcasecmp(var, "TIME") == 0) {
            val_begin_len = val_end - val_begin;
            conf->TIME = atoi(val_begin);

        }
        
        if (strcasecmp(var, "IS_BLOCKED") == 0) {
            val_begin_len = val_end - val_begin;
            conf->IS_BLOCKED = atoi(val_begin);

        }

        if (strcasecmp(var, "REFUSE_NUMBER") == 0) {
            val_begin_len = val_end - val_begin;
            conf->REFUSE_NUMBER = atoi(val_begin);

        }

        if (strcasecmp(var, "IS_MAIL") == 0) {
            val_begin_len = val_end - val_begin;
            conf->IS_MAIL = atoi(val_begin);

        }

        if (strcasecmp(var, "IS_DING_WEBHOOK") == 0) {
            val_begin_len = val_end - val_begin;
            conf->IS_DING_WEBHOOK = atoi(val_begin);

        }

        if (strcasecmp(var, "PHONE") == 0) {
            val_begin_len = val_end - val_begin;
            if (copy_new_mem(val_begin, val_begin_len, &conf->PHONE) != 0)
                return;
        }

        if (strcasecmp(var, "DING_WEBHOOK") == 0) {
            val_begin_len = val_end - val_begin;
            if (copy_new_mem(val_begin, val_begin_len, &conf->DING_WEBHOOK) != 0)
                return;
        }

        if (strcasecmp(var, "IS_QQMAIL") == 0) {
            val_begin_len = val_end - val_begin;
            conf->IS_QQMAIL = atoi(val_begin);
        }

        if (strcasecmp(var, "SEND_QQ") == 0) {
            val_begin_len = val_end - val_begin;
            if (copy_new_mem(val_begin, val_begin_len, &conf->SEND_QQ) != 0)
                return;
        }

        if (strcasecmp(var, "QQMAIL_KEY") == 0) {
            val_begin_len = val_end - val_begin;
            if (copy_new_mem(val_begin, val_begin_len, &conf->QQMAIL_KEY) != 0)
                return;
        }

        if (strcasecmp(var, "RECV_MAIL") == 0) {
            val_begin_len = val_end - val_begin;
            if (copy_new_mem(val_begin, val_begin_len, &conf->RECV_MAIL) != 0)
                return;
        }
        
        if (strcasecmp(var, "PUBLIC_IP") == 0) {
            val_begin_len = val_end - val_begin;
            if (copy_new_mem(val_begin, val_begin_len, &conf->PUBLIC_IP) != 0)
                return;
        }
        
        // IP白名单
        if (strcasecmp(var, "IPV4_RESTRICTION") == 0) {
            val_begin_len = val_end - val_begin;
            conf->IPV4_RESTRICTION = atoi(val_begin);
        }
        if (strcasecmp(var, "IPV4_WHITE_LIST") == 0) {
            val_begin_len = val_end - val_begin;
            if (copy_new_mem(val_begin, val_begin_len, &conf->IPV4_WHITE_LIST) != 0)
                return;
        }
        
        // 地域白名单
        if (strcasecmp(var, "REGION") == 0) {
            val_begin_len = val_end - val_begin;
            conf->REGION = atoi(val_begin);
        }
        if (strcasecmp(var, "REGION_URL") == 0) {
            val_begin_len = val_end - val_begin;
            if (copy_new_mem(val_begin, val_begin_len, &conf->REGION_URL) != 0)
                return;
        }
        if (strcasecmp(var, "REGION_LIST") == 0) {
            val_begin_len = val_end - val_begin;
            if (copy_new_mem(val_begin, val_begin_len, &conf->REGION_LIST) != 0)
                return;
        }
        
        if (strcasecmp(var, "CLAMAV") == 0) {
            val_begin_len = val_end - val_begin;
            conf->CLAMAV = atoi(val_begin);
        }
        if (strcasecmp(var, "CLAMAV_TIME") == 0) {
            val_begin_len = val_end - val_begin;
            conf->CLAMAV_TIME_LEN = val_begin_len;
            if (copy_new_mem(val_begin, val_begin_len, &conf->CLAMAV_TIME) != 0)
                return;
        }

        content = strchr(lineEnd + 1, '\n');
    }
}

/* 在buff中读取模块(global http https httpdns httpudp)内容 */
static char *read_module(char *buff, const char *module_name)
{
    int len;
    char *p, *p0;

    len = strlen(module_name);
    p = buff;
    while (1) {
        while (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n')
            p++;
        if (strncasecmp(p, module_name, len) == 0) {
            p += len;
            while (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n')
                p++;
            if (*p == '{')
                break;
        }
        if ((p = strchr(p, '\n')) == NULL)
            return NULL;
    }

    if ((p0 = strchr(++p, '}')) == NULL)
        return NULL;
    return strndup(p, p0 - p);
}

void read_conf(char *filename, conf * configure)
{
    char *buff, *global_content;
    FILE *file;
    long file_size;
    int return_val;

    file = fopen(filename, "r");
    if (file == NULL)
        perror("cannot open config file.");
    fseek(file, 0, SEEK_END);
    file_size = ftell(file);
    buff = (char *)alloca(file_size + 1);
    if (buff == NULL)
        perror("out of memory.");
    rewind(file);
    if (1 > (return_val = fread(buff, file_size, 1, file)))
        perror("fread");
    fclose(file);
    buff[file_size] = '\0';

    if ((global_content = read_module(buff, "global")) == NULL) {
        perror("read global module error");
    }
    parse_global_module(global_content, configure);
    free(global_content);
}

void free_conf(conf * conf)
{
    if (conf->DAEMON)
        free(conf->DAEMON);
    if (conf->PHONE)
        free(conf->PHONE);
    if (conf->DING_WEBHOOK)
        free(conf->DING_WEBHOOK);
    if (conf->SEND_QQ)
        free(conf->SEND_QQ);
    if (conf->QQMAIL_KEY)
        free(conf->QQMAIL_KEY);
    if (conf->RECV_MAIL)
        free(conf->RECV_MAIL);
    if (conf->PUBLIC_IP)
        free(conf->PUBLIC_IP);
    if (conf->IPV4_WHITE_LIST)
        free(conf->IPV4_WHITE_LIST);
    
    if (conf->REGION_LIST)
        free(conf->REGION_LIST);
    if (conf->REGION_URL)
        free(conf->REGION_URL);
    
    if (conf->CLAMAV_TIME)
        free(conf->CLAMAV_TIME);
    
    
    return;
}

void ptintf_conf(conf * conf)
{
    if (conf->DAEMON)
        printf("%s\n", conf->DAEMON);
    printf("%d\n", conf->TIME);
    printf("%d\n", conf->REFUSE_NUMBER);
    printf("%d\n", conf->IS_MAIL);
    printf("%d\n", conf->IS_DING_WEBHOOK);
    if (conf->PHONE)
        printf("%s\n", conf->PHONE);
    if (conf->DING_WEBHOOK)
        printf("%s\n", conf->DING_WEBHOOK);
    printf("%d\n", conf->IS_QQMAIL);
    if (conf->SEND_QQ)
        printf("%s\n", conf->SEND_QQ);
    if (conf->QQMAIL_KEY)
        printf("%s\n", conf->QQMAIL_KEY);
    if (conf->RECV_MAIL)
        printf("%s\n", conf->RECV_MAIL);
    if (conf->PUBLIC_IP)
        printf("%s\n", conf->PUBLIC_IP);
    
    printf("%d\n", conf->IPV4_RESTRICTION);
    if (conf->IPV4_WHITE_LIST)
        printf("%s\n", conf->IPV4_WHITE_LIST);
    
    printf("%d\n", conf->REGION);
    if (conf->REGION_LIST)
        printf("%s\n", conf->REGION_LIST);
}

void split_string(char string[], char delims[], char (*whitelist_ip)[WHITELIST_IP_NUM])
{
    int i = 0;
    char *result = NULL;
    result = strtok(string, delims);
    while (result != NULL) {
        i++;
        strcpy(whitelist_ip[i], result);
        result = strtok(NULL, delims);
    }
}
