blob: 151b77111e9edc1af6f7c894e07e2aafbd6f2fed [file] [log] [blame]
/** @file
A brief file description
@section license License
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "libts.h"
#include "GenericParser.h"
/***************************************************************************
* Token
* a token is a name/value pairs of data. The data are of the type char *.
* The setName and setValue are not meant for data encapsulation, but
* free callers from allocating the memory.
***************************************************************************/
Token::Token():name(NULL), value(NULL)
{
}
Token::~Token()
{
ats_free(name);
ats_free(value);
}
void
Token::setName(const char *str)
{
name = (char *) strtrim(str);
//name = ats_strdup(str_copy); DOESN't WORK
}
//
// need to allocate more memory than the actual str len in case
// more characters are appended to the value
//
void
Token::setValue(const char *str)
{
char *str_copy = (char *) strtrim(str);
// Can't use ats_strdup after strtrim?
// value = ats_strdup(str);
ink_assert(value == NULL);
if (str_copy) {
size_t len = strlen(str_copy);
value = (char *)ats_malloc(sizeof(char) * (BUFSIZ));
len = (len < BUFSIZ) ? len : BUFSIZ - 1;
memcpy(value, str_copy, len);
value[len] = '\0';
ats_free(str_copy);
}
}
void
Token::appendValue(const char *str)
{
char *str_copy = (char *) strtrim(str);
static bool firstTime = true;
if (value == NULL) {
setValue(str_copy);
} else {
if (!firstTime) {
ink_strlcat(value, " ", BUFSIZ);
}
ink_strlcat(value, str_copy, BUFSIZ);
}
firstTime = false;
ats_free(str_copy);
}
void
Token::Print()
{
ink_assert(name != NULL);
printf(" (%s", name);
if (value != NULL) {
printf(", %s", value);
}
printf("),");
}
/***************************************************************************
* TokenList
* a token list is a list of token (obviously). It uses List.h to link
* the tokens together. This object includes some queue and stack manlipuation
* function calls in addition to the common length() and the debugging
* print() member functions.
***************************************************************************/
TokenList::TokenList():length(0)
{
}
TokenList::~TokenList()
{
Token *token = NULL;
while ((token = dequeue())) {
delete(token);
}
}
void
TokenList::Print()
{
printf("\tRULE -->");
for (Token * token = first(); token; token = next(token)) {
token->Print();
}
printf("\n");
}
/***************************************************************************
* Rule
* a rule is nothing more than just a token list. This object also
* contains a very important member function -- parse(). Depending on
* on the configuration file type, a specific parse function is invoked.
* Since the user of "Rule" are not expected to access the member data
* driectly, the get/set member functions are used for data encapsulation.
***************************************************************************/
Rule::Rule()
: tokenList(NULL),
m_filetype(TS_FNAME_UNDEFINED), m_filename(NULL), m_ruleStr(NULL), m_comment(NULL), m_errorHint(NULL)
{
}
void
Rule::setRuleStr(const char *str)
{
ink_assert(m_comment == NULL);
m_ruleStr = ats_strdup(str);
}
void
Rule::setComment(const char *str)
{
ink_assert(m_comment == NULL);
m_comment = ats_strdup(str);
}
void
Rule::setErrorHint(const char *str)
{
ink_assert(m_errorHint == NULL);
m_errorHint = ats_strdup(str);
}
Rule::~Rule()
{
delete tokenList;
ats_free(m_comment);
ats_free(m_errorHint);
ats_free(m_ruleStr);
ats_free(m_filename);
}
void
Rule::Print()
{
if (tokenList) {
tokenList->Print();
}
if (m_errorHint) {
printf("\treason: %s\n", m_errorHint);
}
}
TokenList *
Rule::parse(const char *const_rule, TSFileNameT filetype)
{
char *rule = (char *) const_rule;
m_filetype = filetype;
switch (m_filetype) {
case TS_FNAME_CACHE_OBJ: /* cache.config */
return cacheParse(rule);
case TS_FNAME_CONGESTION: /* congestion.config */
return congestionParse(rule, 1, 15);
case TS_FNAME_HOSTING: /* hosting.config */
return hostingParse(rule);
case TS_FNAME_ICP_PEER: /* icp.config */
return icpParse(rule, 8, 8);
case TS_FNAME_IP_ALLOW: /* ip_allow.config */
return ip_allowParse(rule);
case TS_FNAME_LOGS_XML: /* logs_xml.config */
return logs_xmlParse(rule);
case TS_FNAME_PARENT_PROXY: /* parent.config */
return parentParse(rule);
case TS_FNAME_VOLUME: /* volume.config */
return volumeParse(rule);
case TS_FNAME_PLUGIN: /* plugin.config */
return pluginParse(rule);
case TS_FNAME_REMAP: /* remap.config */
return remapParse(rule);
case TS_FNAME_SOCKS: /* socks.config */
return socksParse(rule);
case TS_FNAME_SPLIT_DNS: /* splitdns.config */
return splitdnsParse(rule);
case TS_FNAME_STORAGE: /* storage.config */
return storageParse(rule);
case TS_FNAME_UPDATE_URL: /* update.config */
return updateParse(rule);
case TS_FNAME_VADDRS: /* vaddrs.config */
return vaddrsParse(rule);
default:
return NULL;
}
}
/**
* arm_securityParse
**/
TokenList *
Rule::arm_securityParse(char *rule)
{
Tokenizer ruleTok(" \t");
ruleTok.Initialize(rule);
tok_iter_state ruleTok_state;
const char *tokenStr = ruleTok.iterFirst(&ruleTok_state);
Token *token = (Token *) NULL;
TokenList *m_tokenList = NEW(new TokenList());
// ASSUMPTIONS:
// every token starts with a non-digit character is a "name"
// every token starts with a digit is a "value" or part of a "value"
// NO SPACE for port/ip range
for (; tokenStr; tokenStr = ruleTok.iterNext(&ruleTok_state)) {
// If 1st element is non-digit, it is a value
if (!ParseRules::is_digit(tokenStr[0])) {
// it is a name
if (token != (Token *) NULL) {
// We have a token that hasn't been enqueue, enqueue it
m_tokenList->enqueue(token);
}
token = NEW(new Token()); // Create a new token
token->setName(tokenStr); // Set token Name
} else if (token != (Token *) NULL) {
// it is a value or part of a value
token->appendValue(tokenStr); // ISA port# or IP; append to value
}
}
if (token != (Token *) NULL) { // Enqueue the last token -- we haven't done it yet.
m_tokenList->enqueue(token);
}
return m_tokenList;
}
/**
* cacheParse
* CAUTION: This function is used for number of similar formatted
* configureation file parsing. Modification to this function
* will manifest changes to other parsing function.
**/
TokenList *
Rule::cacheParse(char *rule, unsigned short minNumToken, unsigned short maxNumToken)
{
Tokenizer ruleTok(" \t");
int numRuleTok = ruleTok.Initialize(rule);
tok_iter_state ruleTok_state;
const char *tokenStr = ruleTok.iterFirst(&ruleTok_state);
Token *token = NULL;
bool insideQuote = false;
const char *newStr;
// Sanity Check -- number of token
if (numRuleTok < minNumToken) {
setErrorHint("Expecting more space delimited tokens!");
return NULL;
}
if (numRuleTok > maxNumToken) {
setErrorHint("Expecting less space delimited tokens!");
return NULL;
}
// Sanity Check -- no space before or after '='
if (strstr(rule, " =")) {
setErrorHint("Expected space before '='");
return NULL;
}
if (strstr(rule, "= ")) {
setErrorHint("Expected space after '='");
return NULL;
}
TokenList *m_tokenList = NEW(new TokenList());
for (; tokenStr; tokenStr = ruleTok.iterNext(&ruleTok_state)) {
if (!insideQuote) {
Tokenizer subruleTok("=");
int numSubRuleTok = subruleTok.Initialize(tokenStr);
tok_iter_state subruleTok_state;
const char *subtoken = subruleTok.iterFirst(&subruleTok_state);
// Every token must have a '=' sign
if (numSubRuleTok < 2) {
setErrorHint("'=' is expected in space-delimited token");
return NULL;
}
token = NEW(new Token());
/* set the name */
token->setName(subtoken);
/* set the value */
if (numSubRuleTok == 2) {
subtoken = subruleTok.iterNext(&subruleTok_state);
} else {
/* Ignore the first "=" sign and treat the rest as one token
for TSqa09488 */
const char *secondEqual = strstr(strstr(tokenStr, "="), "=");
secondEqual++;
subtoken = ats_strdup(secondEqual);
}
insideQuote = inQuote(subtoken);
newStr = strtrim(subtoken, '\"');
if (!insideQuote) {
// printf("!insideQuote: %s\n", subtoken);
token->setValue(newStr);
m_tokenList->enqueue(token);
} else {
// printf("insideQuote: %s\n", subtoken);
// printf("%s 1\n", subtoken);
token->appendValue(newStr);
}
ats_free((void*)newStr);
} else {
// printf("%s 2\n", tokenStr);
newStr = strtrim(tokenStr, '\"');
token->appendValue(newStr);
ats_free((void*)newStr);
insideQuote = inQuote(tokenStr);
if (insideQuote) {
// printf("enqueue\n");
m_tokenList->enqueue(token);
insideQuote = false;
} else {
insideQuote = true;
}
}
}
return m_tokenList;
}
/**
* congestionParse
**/
TokenList *
Rule::congestionParse(char *rule, unsigned short minNumToken, unsigned short maxNumToken)
{
return cacheParse(rule, minNumToken, maxNumToken);
}
/**
* hostingParse
**/
TokenList *
Rule::hostingParse(char *rule)
{
// ASSUMPTIONS:
// NO SPACE around "=" sign
// NO SPACE around ","
return cacheParse(rule, 2, 2);
}
/**
* icpParse
* - mimic proxy/ICPConfig/icp_config_change_callback
**/
TokenList *
Rule::icpParse(char *rule, unsigned short minNumToken, unsigned short maxNumToken)
{
Tokenizer ruleTok(":");
int numRuleTok = ruleTok.Initialize(rule, ALLOW_EMPTY_TOKS);
tok_iter_state ruleTok_state;
const char *tokenStr = ruleTok.iterFirst(&ruleTok_state);
Token *token;
TokenList *m_tokenList = NEW(new TokenList());
// Sanity Check -- number of token
if (numRuleTok < minNumToken) {
setErrorHint("Expecting more ':' delimited tokens!");
return NULL;
}
if (numRuleTok > maxNumToken + 1 ||
(numRuleTok == maxNumToken + 1 && strspn(ruleTok[maxNumToken], " ") != strlen(ruleTok[maxNumToken]))) {
setErrorHint("Expecting less ':' delimited tokens!");
return NULL;
}
for (; tokenStr; tokenStr = ruleTok.iterNext(&ruleTok_state)) {
token = NEW(new Token());
token->setName(tokenStr);
m_tokenList->enqueue(token);
}
return m_tokenList;
}
/**
* ip_allowParse
**/
TokenList *
Rule::ip_allowParse(char *rule)
{
// ASSUMPTIONS:
// NO SPACE around "=" sign
// NO SPACE around "-"
return cacheParse(rule, 2, 2);
}
/**
* logsParse
**/
TokenList *
Rule::logsParse(char * /* rule ATS_UNUSED */)
{
return NULL;
}
/**
* log_hostsParse
**/
TokenList *
Rule::log_hostsParse(char *rule)
{
if (strstr(rule, " ")) {
return NULL;
}
Token *token = NEW(new Token());
TokenList *m_tokenList = NEW(new TokenList());
token->setName(rule);
m_tokenList->enqueue(token);
return m_tokenList;
}
/**
* logs_xmlParse
**/
TokenList *
Rule::logs_xmlParse(char * /* rule ATS_UNUSED */)
{
return NULL;
}
/**
* parentParse
**/
TokenList *
Rule::parentParse(char *rule)
{
return cacheParse(rule, 2);
}
/**
* volumeParse
**/
TokenList *
Rule::volumeParse(char *rule)
{
return cacheParse(rule, 3, 3);
}
/**
* pluginParse
**/
TokenList *
Rule::pluginParse(char *rule)
{
Tokenizer ruleTok(" \t");
ruleTok.Initialize(rule);
tok_iter_state ruleTok_state;
const char *tokenStr = ruleTok.iterFirst(&ruleTok_state);
Token *token;
TokenList *m_tokenList = NEW(new TokenList());
for (; tokenStr; tokenStr = ruleTok.iterNext(&ruleTok_state)) {
token = NEW(new Token());
token->setName(tokenStr);
m_tokenList->enqueue(token);
}
return m_tokenList;
}
/**
* remapParse
**/
TokenList *
Rule::remapParse(char *rule)
{
Tokenizer ruleTok(" \t");
int numRuleTok = ruleTok.Initialize(rule);
tok_iter_state ruleTok_state;
const char *tokenStr = ruleTok.iterFirst(&ruleTok_state);
if ((numRuleTok != 3) && (numRuleTok != 4)) {
setErrorHint("Expecting exactly 4 space delimited tokens");
return NULL;
}
Token *token;
TokenList *m_tokenList = NEW(new TokenList());
token = NEW(new Token());
token->setName(tokenStr);
m_tokenList->enqueue(token);
tokenStr = ruleTok.iterNext(&ruleTok_state);
token = NEW(new Token());
token->setName(tokenStr);
tokenStr = ruleTok.iterNext(&ruleTok_state);
token->setValue(tokenStr);
m_tokenList->enqueue(token);
// Just to make sure that there are no left overs
tokenStr = ruleTok.iterNext(&ruleTok_state);
if (tokenStr) {
token = NEW(new Token());
token->setName(tokenStr);
m_tokenList->enqueue(token);
ruleTok.iterNext(&ruleTok_state);
}
return m_tokenList;
}
/**
* socksParse
**/
TokenList *
Rule::socksParse(char *rule)
{
Tokenizer ruleTok(" \t");
int numRuleTok = ruleTok.Initialize(rule);
tok_iter_state ruleTok_state;
const char *tokenStr = ruleTok.iterFirst(&ruleTok_state);
Token *token = NULL;
bool insideQuote = false;
const char *newStr;
if (numRuleTok < 2) {
setErrorHint("Expecting at least 2 space delimited tokens");
return NULL;
}
TokenList *m_tokenList = NEW(new TokenList());
/* check which rule type it is */
if (strcmp(tokenStr, "no_socks") == 0) { /* TS_SOCKS_BYPASS rule type */
/* the token name = "no socks", the value = "list of ip addresses" */
token = NEW(new Token());
token->setName(tokenStr);
for (; (tokenStr = ruleTok.iterNext(&ruleTok_state));) {
token->appendValue(tokenStr);
}
m_tokenList->enqueue(token);
} else if (strcmp(tokenStr, "auth") == 0) { /* TS_SOCKS_AUTH rule type */
/* first token: name = "auth", value = "u"
second token: name = <username>
third token: name = <password> */
token = NEW(new Token());
token->setName(tokenStr);
tokenStr = ruleTok.iterNext(&ruleTok_state);
token->setValue(tokenStr); /* should be "u" authoriziation type */
m_tokenList->enqueue(token);
/* create tokens for username and password */
for (; (tokenStr = ruleTok.iterNext(&ruleTok_state));) {
token = NEW(new Token());
token->setName(tokenStr);
m_tokenList->enqueue(token);
}
} else { /* TS_SOCKS_MULTIPLE rule type */
for (; tokenStr; tokenStr = ruleTok.iterNext(&ruleTok_state)) {
/* token is a name-value pair separated with = sign */
if (!insideQuote) {
Tokenizer subruleTok("=");
int numSubRuleTok = subruleTok.Initialize(tokenStr);
tok_iter_state subruleTok_state;
const char *subtoken = subruleTok.iterFirst(&subruleTok_state);
// Every token must have a '=' sign
if (numSubRuleTok < 2) {
setErrorHint("'=' is expected in space-delimited token");
return NULL;
}
token = NEW(new Token());
/* set the name */
token->setName(subtoken);
/* set the value */
if (numSubRuleTok == 2) {
subtoken = subruleTok.iterNext(&subruleTok_state);
} else {
/* Ignore the first "=" sign and treat the rest as one token
for TSqa09488 */
const char *secondEqual = strstr(strstr(tokenStr, "="), "=");
secondEqual++;
subtoken = ats_strdup(secondEqual);
}
insideQuote = inQuote(subtoken);
newStr = strtrim(subtoken, '\"');
if (!insideQuote) {
// printf("!insideQuote: %s\n", subtoken);
token->setValue(newStr);
m_tokenList->enqueue(token);
} else {
// printf("insideQuote: %s\n", subtoken);
// printf("%s 1\n", subtoken);
token->appendValue(newStr);
}
ats_free((void*)newStr);
} else {
// printf("%s 2\n", tokenStr);
newStr = strtrim(tokenStr, '\"');
token->appendValue(newStr);
ats_free((void*)newStr);
insideQuote = inQuote(tokenStr);
if (insideQuote) {
// printf("enqueue\n");
m_tokenList->enqueue(token);
insideQuote = false;
} else {
insideQuote = true;
}
}
} /* end for loop */
}
return m_tokenList;
}
/**
* splitdnsParse
**/
TokenList *
Rule::splitdnsParse(char *rule)
{
Tokenizer ruleTok(" \t");
int numRuleTok = ruleTok.Initialize(rule);
tok_iter_state ruleTok_state;
const char *tokenStr = ruleTok.iterFirst(&ruleTok_state);
Token *token = NULL;
bool insideQuote = false;
const char *newStr;
// Sanity Check -- number of token
if (numRuleTok < 0) {
setErrorHint("Expecting more space delimited tokens!");
return NULL;
}
if (numRuleTok > 10) {
setErrorHint("Expecting less space delimited tokens!");
return NULL;
}
// Sanity Check -- no space before or after '='
if (strstr(rule, " =")) {
setErrorHint("Expected space before '='");
return NULL;
}
if (strstr(rule, "= ")) {
setErrorHint("Expected space after '='");
return NULL;
}
TokenList *m_tokenList = NEW(new TokenList());
for (; tokenStr; tokenStr = ruleTok.iterNext(&ruleTok_state)) {
if (!insideQuote) {
Tokenizer subruleTok("=");
int numSubRuleTok = subruleTok.Initialize(tokenStr);
tok_iter_state subruleTok_state;
const char *subtoken = subruleTok.iterFirst(&subruleTok_state);
// Every token must have a '=' sign
if (numSubRuleTok < 2) {
setErrorHint("'=' is expected in space-delimited token");
return NULL;
}
token = NEW(new Token());
token->setName(subtoken);
subtoken = subruleTok.iterNext(&subruleTok_state);
insideQuote = inQuote(subtoken);
newStr = strtrim(subtoken, '\"');
if (!insideQuote) {
token->setValue(newStr);
m_tokenList->enqueue(token);
} else {
// printf("%s 1\n", subtoken);
token->appendValue(newStr);
}
ats_free((void*)newStr);
} else {
// printf("%s 2\n", tokenStr);
newStr = strtrim(tokenStr, '\"');
token->appendValue(newStr);
ats_free((void*)newStr);
insideQuote = inQuote(tokenStr);
if (insideQuote) {
// printf("enqueue\n");
m_tokenList->enqueue(token);
insideQuote = false;
} else {
insideQuote = true;
}
}
}
return m_tokenList;
// return cacheParse(rule, 2);
}
/**
* updateParse
**/
TokenList *
Rule::updateParse(char *rule)
{
Tokenizer ruleTok("\\");
int numRuleTok = ruleTok.Initialize(rule, ALLOW_EMPTY_TOKS);
tok_iter_state ruleTok_state;
const char *tokenStr = ruleTok.iterFirst(&ruleTok_state);
// NOTE: ignore white spaces before/after the '\'
// There should only be 5 tokens; if there are 6 tokens, the
// sixth token must be all white spaces
if (numRuleTok<5 || numRuleTok> 6 || (numRuleTok == 6 && strspn(ruleTok[5], " ") != strlen(ruleTok[5]))) {
setErrorHint("Expecting exactly 5 '\' delimited tokens");
return NULL;
}
Token *token;
TokenList *m_tokenList = NEW(new TokenList());
for (; tokenStr; tokenStr = ruleTok.iterNext(&ruleTok_state)) {
token = NEW(new Token());
token->setName(tokenStr);
m_tokenList->enqueue(token);
}
return m_tokenList;
}
/**
* vaddrsParse
**/
TokenList *
Rule::vaddrsParse(char *rule)
{
// ASSUMPTIONS:
// UNIX: IP_address device subinterface
// Win: IP_address interface
Tokenizer ruleTok(" \t");
ruleTok.Initialize(rule);
tok_iter_state ruleTok_state;
const char *tokenStr = ruleTok.iterFirst(&ruleTok_state);
Token *token;
TokenList *m_tokenList = NEW(new TokenList());
for (; tokenStr; tokenStr = ruleTok.iterNext(&ruleTok_state)) {
token = NEW(new Token());
token->setName(tokenStr);
m_tokenList->enqueue(token);
}
return m_tokenList;
}
/**
* storageParse
* ------------
* the token value is pathname; if a size is specified, that is stored as
* the token's value
**/
TokenList *
Rule::storageParse(char *rule)
{
Tokenizer ruleTok(" \t");
int numRuleTok = ruleTok.Initialize(rule);
tok_iter_state ruleTok_state;
const char *tokenStr = ruleTok.iterFirst(&ruleTok_state);
if ((numRuleTok != 1) && (numRuleTok != 2)) {
setErrorHint("Expecting one or two tokens");
return NULL;
}
Token *token;
TokenList *m_tokenList = NEW(new TokenList());
// at least one token, anyways
token = NEW(new Token());
token->setName(tokenStr);
if (numRuleTok > 1) { // numRulTok == 2
tokenStr = ruleTok.iterNext(&ruleTok_state);
token->setValue(tokenStr);
}
m_tokenList->enqueue(token);
return m_tokenList;
}
/*
* bool Rule::inQuote(char *str)
* Counts the number of quote found in "str"
* RETURN true if "str" contains odd number of quotes (")
* false if "str" contains even number of quotes (including zero)
*/
bool Rule::inQuote(const char *str)
{
unsigned
numQuote = 0;
for (const char *ptr = str; *ptr != '\0'; ptr++) {
if (*ptr == '\"') {
numQuote++;
}
}
return (numQuote & 1);
}
/***************************************************************************
* RuleList
* a rule list is a list of rule; which compose to a configuration file.
* Again some queue and stack manlipation member functions are included.
* The important function is this object is also parse() which breaks up
* the file into individual lines and passes on to the Rule object to
* continue parsing each rule.
* NOTE: a rule that spans more than one line would be a problem in here.
***************************************************************************/
RuleList::RuleList()
: length(0), m_filename(NULL)
{
m_filetype = TS_FNAME_UNDEFINED;
}
RuleList::~RuleList()
{
ats_free(m_filename);
Rule *rule = NULL;
while ((rule = dequeue())) {
delete rule;
}
}
void
RuleList::Print()
{
printf("RULELIST-->\n");
for (Rule * rule = first(); rule; rule = next(rule)) {
rule->Print();
}
printf("length: %u\n", length);
}
/*
* void RuleList::parse(char *fileBuf, const char *filename)
* Takes configuration file buffer, tokenize the buffer according carriage
* return. For each line, pasre it.
*
*/
void
RuleList::parse(char *fileBuf, const char *filename)
{
m_filename = ats_strdup(filename);
if (strstr(filename, "cache.config")) {
m_filetype = TS_FNAME_CACHE_OBJ; /* cache.config */
} else if (strstr(filename, "congestion.config")) {
m_filetype = TS_FNAME_CONGESTION; /* congestion.config */
} else if (strstr(filename, "hosting.config")) {
m_filetype = TS_FNAME_HOSTING; /* hosting.config */
} else if (strstr(filename, "icp.config")) {
m_filetype = TS_FNAME_ICP_PEER; /* icp.config */
} else if (strstr(filename, "ip_allow.config")) {
m_filetype = TS_FNAME_IP_ALLOW; /* ip_allow.config */
} else if (strstr(filename, "logs_xml.config")) {
m_filetype = TS_FNAME_LOGS_XML; /* logs_xml.config */
} else if (strstr(filename, "parent.config")) {
m_filetype = TS_FNAME_PARENT_PROXY; /* parent.config */
} else if (strstr(filename, "volume.config")) {
m_filetype = TS_FNAME_VOLUME; /* volume.config */
} else if (strstr(filename, "plugin.config")) {
m_filetype = TS_FNAME_PLUGIN; /* plugin.config */
} else if (strstr(filename, "remap.config")) {
m_filetype = TS_FNAME_REMAP; /* remap.config */
} else if (strstr(filename, "socks.config")) {
m_filetype = TS_FNAME_SOCKS; /* socks.config */
} else if (strstr(filename, "splitdns.config")) {
m_filetype = TS_FNAME_SPLIT_DNS; /* splitdns.config */
} else if (strstr(filename, "update.config")) {
m_filetype = TS_FNAME_UPDATE_URL; /* update.config */
} else if (strstr(filename, "vaddrs.config")) {
m_filetype = TS_FNAME_VADDRS; /* vaddrs.config */
} else if (strstr(filename, "plugin.config")) {
m_filetype = TS_FNAME_UNDEFINED; /* plugin.config */
} else if (strstr(filename, "storage.config")) {
m_filetype = TS_FNAME_STORAGE; /* storage.config */
}
else {
m_filetype = TS_FNAME_UNDEFINED;
}
// Call the proper function
this->parse(fileBuf, m_filetype);
}
/*
* void RuleList::parse(char *fileBuf, TSFileNameT filetype)
* Takes configuration file buffer, tokenize the buffer according carriage
* return. For each line, pasre it.
* NOTE: (1) comment line must start with '#' as the first character without
* leading spaces
* (2) a line must
*
*/
void
RuleList::parse(char *fileBuf, TSFileNameT filetype)
{
Tokenizer lineTok("\n");
tok_iter_state lineTok_state;
const char *line;
if (filetype == TS_FNAME_LOGS_XML) {
printf("Yes Yes! XML!\n");
// InkXmlConfigFile(NULL);
return;
}
lineTok.Initialize(fileBuf);
line = lineTok.iterFirst(&lineTok_state);
while (line) {
Rule *rule = NEW(new Rule());
if (line[0] == '#') { // is this comment
rule->setComment(line);
} else {
TokenList *m_tokenList = rule->parse(line, filetype);
if (m_tokenList) {
rule->setRuleStr(line);
rule->tokenList = m_tokenList;
} else {
//rule->setComment("## WARNING: The following configuration rule is invalid!");
size_t error_rule_size = sizeof(char) * (strlen(line) + strlen("#ERROR: ") + 1);
char *error_rule = (char *)ats_malloc(error_rule_size);
snprintf(error_rule, error_rule_size, "#ERROR: %s", line);
rule->setComment(error_rule);
ats_free(error_rule);
}
}
//rule->Print();
this->enqueue(rule);
// Get next line
line = lineTok.iterNext(&lineTok_state);
}
//this->Print();
}
/***************************************************************************
* General Routines
***************************************************************************/
// Concatenate two strings together and return the resulting string
/*
char *
strtrim(char *str) {
while(isspace(*str)) {
str++;
}
while(isspace(str[strlen(str)-1])) {
str[strlen(str)-1] = '\0';
}
return str;
}
*/
//
// This function ALLOCATES MEMORY FOR A NEW STRING!!
//
const char *
strtrim(const char *str_in, char chr)
{
char *str = ats_strdup(str_in);
char *str_ptr = str; // so we can free str later if it changes
while (*str == chr) {
str++;
}
while (str[strlen(str) - 1] == chr) {
str[strlen(str) - 1] = '\0';
}
char *newStr = ats_strdup(str);
ats_free(str_ptr);
return newStr;
}