#include "objconf.h"
#include "logging.h"
#include <string.h>
#include <cx/utils.h>
ObjectConfig *load_object_config(
char *file) {
FILE *in = fopen(file,
"r");
if(in ==
NULL) {
return NULL;
}
ObjectConfig *conf = malloc(
sizeof(ObjectConfig));
conf->parser.parse = objconf_parse;
conf->file = file;
conf->levels =
NULL;
conf->objects = cxLinkedListCreate(cxDefaultAllocator,
NULL,
CX_STORE_POINTERS);
int r = cfg_parse_basic_file((ConfigParser*)conf, in);
if(r !=
0) {
return NULL;
}
fclose(in);
return conf;
}
ObjectConfig2* objectconf_load(
const char *file) {
CxMempool *mp = cxBasicMempoolCreate(
512);
if(!mp) {
return NULL;
}
ConfigParser2 parser;
memset(&parser,
0,
sizeof(ConfigParser2));
parser.mp = mp;
parser.filename = file;
parser.delim =
"()/*%";
parser.validateDirective = objectconf_validate_directive;
parser.validateObjBegin = objectconf_validate_objbegin;
parser.validateObjEnd = objectconf_validate_objend;
parser.allow_hierarchy =
1;
ConfigNode *obj_config = serverconfig_load_file(&parser, file);
if(!obj_config) {
cxMempoolDestroy(mp);
return NULL;
}
ObjectConfig2 *conf = cxMalloc(mp->allocator,
sizeof(ObjectConfig2));
if(!conf) {
cxMempoolDestroy(mp);
return NULL;
}
conf->mp = mp;
conf->root = obj_config;
return conf;
}
void objectconf_free(ObjectConfig2 *objconf) {
cxMempoolDestroy(objconf->mp);
}
int objectconf_validate_directive(ConfigParser2 *parser, ConfigNode *node) {
const char *objnames[] = {
"Object",
"Client",
"If",
"ElseIf",
"Else" };
size_t typeindex;
if(!serverconfig_validate_directive_name(node, objnames,
5, &typeindex)) {
return 0;
}
const char *dirtypes[] = {
"AuthTrans",
"NameTrans",
"PathCheck",
"ObjectType",
"Service",
"AddLog",
"Error" };
if(serverconfig_validate_directive_name(node, dirtypes,
7, &typeindex)) {
return 1;
}
ConfigParam *param_err;
if(serverconfig_check_param_names(node, ¶m_err)) {
return 1;
}
cxstring fn = serverconfig_directive_get_arg(node, cx_str(
"fn"));
if(fn.length ==
0) {
return 1;
}
return 0;
}
static int validate_else_node(ConfigNode *node) {
ConfigNode *prev = serverconfig_previous_dir_or_obj(node);
const char *allowed_prev_types[] = {
"If",
"ElseIf" };
size_t typeindex;
if(serverconfig_validate_directive_name(prev, allowed_prev_types,
2, &typeindex)) {
return 1;
}
return node->args ?
1 :
0;
}
static int validate_elseif_node(ConfigNode *node) {
const char *allowed_prev_types[] = {
"If",
"ElseIf" };
size_t typeindex;
ConfigNode *prev = serverconfig_previous_dir_or_obj(node);
while(prev) {
if(serverconfig_validate_directive_name(prev, allowed_prev_types,
2, &typeindex)) {
return 1;
}
if(typeindex ==
0) {
return 0;
}
prev = serverconfig_previous_dir_or_obj(node);
}
return 1;
}
int objectconf_validate_objbegin(ConfigParser2 *parser, ConfigNode *node) {
const char *objnames[] = {
"Object",
"Client",
"If",
"ElseIf",
"Else" };
size_t typeindex;
if(serverconfig_validate_directive_name(node, objnames,
5, &typeindex)) {
return 1;
}
if(typeindex ==
4) {
return validate_else_node(node);
}
if(typeindex ==
3 && validate_elseif_node(node)) {
return 1;
}
if(typeindex ==
0) {
ConfigParam *err;
if(serverconfig_check_param_names(node, &err)) {
return 1;
}
return 0;
}
return node->args ?
0 :
1;
}
int objectconf_validate_objend(ConfigParser2 *parser, ConfigNode *node) {
return 0;
}
void free_object_config(ObjectConfig *conf) {
if(conf->levels) {
}
free(conf);
}
int objconf_parse(
void *p, ConfigLine *begin, ConfigLine *end, cxmutstr line) {
ObjectConfig *conf = p;
begin->type = cfg_get_line_type(line);
switch(begin->type) {
case LINE_BEGIN_TAG: {
ConfigTag *tag = cfg_parse_begin_tag(line, conf->parser.mp);
if(tag ==
NULL) {
ws_cfg_log(
LOG_FAILURE,
"Parse error in %s", conf->file);
exit(-
1);
}
tag->begin = begin;
tag->end = end;
tag->type_num = cfg_get_tag_type(cx_strcast(tag->name));
if(objconf_on_begin_tag(conf, tag) !=
0) {
fprintf(stderr,
"1error\n");
exit(-
1);
}
break;
}
case LINE_END_TAG: {
cxmutstr tag = cfg_get_end_tag_name(line);
if(objconf_on_end_tag(conf, tag) !=
0) {
fprintf(stderr,
"2error\n");
exit(-
1);
}
break;
}
case LINE_DIRECTIVE: {
ConfigDirective *dir = cfg_parse_directive(
line,
conf->parser.mp);
dir->begin = begin;
dir->end = end;
if(objconf_on_directive(conf, dir) !=
0) {
fprintf(stderr,
"3error\n");
exit(-
1);
}
}
}
return 0;
}
int objconf_on_begin_tag(ObjectConfig *conf, ConfigTag *tag) {
CxAllocator *mp = conf->parser.mp;
if(tag->type_num !=
TAG_OBJECT) {
ConfigParserLevel *l = conf->levels;
if(l->tag->type_num !=
TAG_OBJECT) {
tag->parent = l->tag;
}
}
switch(tag->type_num) {
case TAG_OBJECT: {
ConfigObject *obj =
OBJ_NEW_N(mp, ConfigObject);
obj->begin = tag->begin;
obj->end = tag->end;
obj->name = cfg_param_get(tag->param, cx_str(
"name"));
obj->ppath = cfg_param_get(tag->param, cx_str(
"ppath"));
conf->obj = obj;
cxListAdd(conf->objects, obj);
ConfigParserLevel *lvl =
OBJ_NEW(mp, ConfigParserLevel);
lvl->iftag =
NULL;
lvl->levelnum =
1;
lvl->tag = tag;
lvl->next =
NULL;
CFG_LEVEL_PREPEND(&conf->levels, lvl);
break;
}
case TAG_IF: {
ConfigParserLevel *last_lvl = conf->levels;
ConfigParserLevel *lvl =
OBJ_NEW(mp, ConfigParserLevel);
lvl->iftag =
NULL;
lvl->levelnum = last_lvl->levelnum +
1;
lvl->tag = tag;
CFG_LEVEL_PREPEND(&conf->levels, lvl);
last_lvl->iftag = tag;
break;
}
case TAG_ELSEIF: {
}
case TAG_ELSE: {
ConfigParserLevel *last_lvl = conf->levels;
tag->iftag = last_lvl->iftag;
ConfigParserLevel *lvl =
OBJ_NEW(
conf->parser.mp,
ConfigParserLevel);
lvl->iftag = last_lvl->tag;
lvl->levelnum = last_lvl->levelnum +
1;
lvl->tag = tag;
CFG_LEVEL_PREPEND(&conf->levels, lvl);
break;
}
case TAG_CLIENT: {
break;
}
default: {
ws_cfg_log(
LOG_FAILURE,
"objconf: unknown tag");
return 1;
}
}
return 0;
}
int objconf_on_end_tag(ObjectConfig *conf, cxmutstr tagname) {
int type = cfg_get_tag_type(cx_strcast(tagname));
if(type == -
1) {
ws_cfg_log(
LOG_FAILURE,
"objconf: unknown tag");
return 1;
}
else {
if(type ==
TAG_OBJECT) {
conf->obj =
NULL;
}
conf->levels = conf->levels->next;
}
return 0;
}
int objconf_on_directive(ObjectConfig *conf, ConfigDirective *dir) {
ConfigParserLevel *lvl = conf->levels;
if(lvl->tag->type_num !=
TAG_OBJECT) {
dir->condition = lvl->tag;
}
ConfigDirectiveList *dir_entry = cxMalloc(conf->parser.mp,
sizeof(ConfigDirectiveList));
dir_entry->directive = dir;
dir_entry->next =
NULL;
CFG_DIRECTIVES_ADD(&conf->obj->directives[dir->type_num], dir_entry);
return 0;
}