diff --git a/src/load/json.c b/src/load/json.c index 4371bf3..3ff434a 100644 --- a/src/load/json.c +++ b/src/load/json.c @@ -4,26 +4,72 @@ #include "cJSON.h" #include "common.h" #include "logger.h" +#include "structure.h" int json_int_value(char *key, cJSON *json) { // json int or string value -> int if (cJSON_IsNumber(json)) { return json->valueint; } else if (cJSON_IsString(json)) { char *p; - return (int)strtol(json->valuestring, &p, 10); + int int_ret = (int)strtol(json->valuestring, &p, 10); + if (int_ret == 0 && strcmp(json->valuestring, "0") != 0) { // invalid number in string + log_fatal("`%s` not a valid number", key); + } + return int_ret; } else { log_fatal("`%s` must be number or string", key); } return 0; // never reach } -uint8_t json_bool_value(char *key, cJSON *json) { // json bool value -> bool - if (cJSON_IsBool(json)) { - return json->valueint; +char* json_string_value(char* key, cJSON *json) { + if (!cJSON_IsString(json)) { + log_fatal("`%s` must be string", key); + } + return json->valuestring; +} + +char** json_string_list_value(char *key, cJSON *json, char **string_list) { + if (cJSON_IsString(json)) { + string_list = string_list_append(string_list, json->valuestring); + } else if (cJSON_IsArray(json)) { + json = json->child; + while (json != NULL) { + if (!cJSON_IsString(json)) { + log_fatal("`%s` must be string array", key); + } + string_list = string_list_append(string_list, json->valuestring); + json = json->next; // next field + } + } else { + log_fatal("`%s` must be array or string", key); + } + return string_list; +} + +uint32_t** json_uint32_list_value(char *key, cJSON *json, uint32_t **uint32_list) { + if (cJSON_IsNumber(json)) { + uint32_list = uint32_list_append(uint32_list, json->valueint); + } else if (cJSON_IsArray(json)) { + json = json->child; + while (json != NULL) { + if (!cJSON_IsNumber(json)) { + log_fatal("`%s` must be number array", key); + } + uint32_list = uint32_list_append(uint32_list, json->valueint); + json = json->next; // next field + } } else { + log_fatal("`%s` must be array or number", key); + } + return uint32_list; +} + +uint8_t json_bool_value(char *key, cJSON *json) { // json bool value -> bool + if (!cJSON_IsBool(json)) { log_fatal("`%s` must be boolean", key); } - return FALSE; + return json->valueint; } void json_cache_parser(cache_config *config, cJSON *json) { // cache options parser @@ -41,6 +87,42 @@ void json_cache_parser(cache_config *config, cJSON *json) { // cache options par } } +void json_diverter_parser(diverter_config *config, cJSON *json) { // diverter options parser + while (json != NULL) { + if (!strcmp(json->string, "port")) { + config->port = json_int_value("diverter.port", json); + } + if (!strcmp(json->string, "gfwlist")) { + config->gfwlist = json_string_list_value("diverter.gfwlist", json, config->gfwlist); + } + if (!strcmp(json->string, "china-ip")) { + config->china_ip = json_string_list_value("diverter.china-ip", json, config->china_ip); + } + if (!strcmp(json->string, "chinalist")) { + config->chinalist = json_string_list_value("diverter.chinalist", json, config->chinalist); + } + json = json->next; // next field + } +} + +void json_adguard_parser(adguard_config *config, cJSON *json) { // adguard options parser + while (json != NULL) { + if (!strcmp(json->string, "port")) { + config->port = json_int_value("adguard.port", json); + } + if (!strcmp(json->string, "enable")) { + config->enable = json_bool_value("adguard.enable", json); + } + if (!strcmp(json->string, "username")) { + config->username = json_string_value("adguard.username", json); + } + if (!strcmp(json->string, "password")) { + config->password = json_string_value("adguard.password", json); + } + json = json->next; // next field + } +} + void json_config_parser(cleardns_config *config, const char *config_file) { // JSON format configure char *config_content = read_file(config_file); cJSON *json = cJSON_Parse(config_content); @@ -59,12 +141,21 @@ void json_config_parser(cleardns_config *config, const char *config_file) { // J // domestic // foreign - // diverter - // adguard - // reject - // hosts - // ttl - + if (!strcmp(json->string, "diverter")) { + json_diverter_parser(&config->diverter, json->child); + } + if (!strcmp(json->string, "adguard")) { + json_adguard_parser(&config->adguard, json->child); + } + if (!strcmp(json->string, "reject")) { + config->reject = json_uint32_list_value("reject", json, config->reject); + } + if (!strcmp(json->string, "hosts")) { + config->hosts = json_string_list_value("hosts", json, config->hosts); + } + if (!strcmp(json->string, "ttl")) { + config->ttl = json_string_list_value("ttl", json, config->ttl); + } json = json->next; // next field } cJSON_free(json); // free JSON struct diff --git a/src/overture.c b/src/overture.c index b5cba78..d1a5acd 100644 --- a/src/overture.c +++ b/src/overture.c @@ -110,7 +110,7 @@ char* overture_config(overture *info) { // generate json configure from overture if (info->host_file != NULL) { cJSON_AddStringToObject(host_file, "hostsFile", info->host_file); } - cJSON_AddStringToObject(host_file, "finder", "full-map"); + cJSON_AddStringToObject(host_file, "finder", "regex-list"); cJSON_AddItemToObject(config, "hostsFile", host_file); if (info->ttl_file != NULL) {