Proper String and Regexp parsing and escaping.
Added parsing of dialplan style %pattern% that is converted internally to regexp. This allows for example %+1xxxxxxxxxx% to be same as /^\+1[0-9]{10}$/i git-svn-id: http://yate.null.ro/svn/yate/trunk@5070 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
parent
3ac7372757
commit
06cf56e116
|
@ -316,22 +316,67 @@ bool ExpEvaluator::getString(const char*& expr)
|
|||
XDebug(this,DebugAll,"getString '%.30s'",expr);
|
||||
char c = skipComments(expr);
|
||||
if (c == '"' || c == '\'') {
|
||||
char sep = c;
|
||||
const char* start = ++expr;
|
||||
while ((c = *expr++)) {
|
||||
if (c != sep)
|
||||
continue;
|
||||
String str(start,expr-start-1);
|
||||
DDebug(this,DebugAll,"Found '%s'",str.safe());
|
||||
String str;
|
||||
if (getString(expr,str)) {
|
||||
addOpcode(str);
|
||||
return true;
|
||||
}
|
||||
expr--;
|
||||
return gotError("Expecting string end");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ExpEvaluator::getString(const char*& expr, String& str)
|
||||
{
|
||||
char sep = *expr++;
|
||||
const char* start = expr;
|
||||
while (char c = *expr++) {
|
||||
if (c != '\\' && c != sep)
|
||||
continue;
|
||||
String tmp(start,expr-start-1);
|
||||
str += tmp;
|
||||
if (c == sep) {
|
||||
DDebug(this,DebugAll,"Found '%s'",str.safe());
|
||||
return true;
|
||||
}
|
||||
tmp.clear();
|
||||
if (!getEscape(expr,tmp,sep))
|
||||
break;
|
||||
str += tmp;
|
||||
start = expr;
|
||||
}
|
||||
expr--;
|
||||
return gotError("Expecting string end");
|
||||
}
|
||||
|
||||
bool ExpEvaluator::getEscape(const char*& expr, String& str, char sep)
|
||||
{
|
||||
char c = *expr++;
|
||||
switch (c) {
|
||||
case '\0':
|
||||
return false;
|
||||
case 'b':
|
||||
c = '\b';
|
||||
break;
|
||||
case 'f':
|
||||
c = '\f';
|
||||
break;
|
||||
case 'n':
|
||||
c = '\n';
|
||||
break;
|
||||
case 'r':
|
||||
c = '\r';
|
||||
break;
|
||||
case 't':
|
||||
c = '\t';
|
||||
break;
|
||||
case 'v':
|
||||
c = '\v';
|
||||
break;
|
||||
}
|
||||
str = c;
|
||||
return true;
|
||||
}
|
||||
|
||||
int ExpEvaluator::getKeyword(const char* str) const
|
||||
{
|
||||
int len = 0;
|
||||
|
|
|
@ -103,6 +103,8 @@ public:
|
|||
JsObject* parseArray(const char*& expr, bool constOnly);
|
||||
JsObject* parseObject(const char*& expr, bool constOnly);
|
||||
protected:
|
||||
virtual bool getString(const char*& expr);
|
||||
virtual bool getEscape(const char*& expr, String& str, char sep);
|
||||
virtual bool keywordChar(char c) const;
|
||||
virtual int getKeyword(const char* str) const;
|
||||
virtual char skipComments(const char*& expr, GenObject* context = 0) const;
|
||||
|
@ -381,6 +383,117 @@ bool JsCode::link()
|
|||
return true;
|
||||
}
|
||||
|
||||
bool JsCode::getString(const char*& expr)
|
||||
{
|
||||
if (inError())
|
||||
return false;
|
||||
char c = skipComments(expr);
|
||||
if (c != '/' && c != '%')
|
||||
return ExpEvaluator::getString(expr);
|
||||
String str;
|
||||
if (!ExpEvaluator::getString(expr,str))
|
||||
return false;
|
||||
bool extended = true;
|
||||
bool insensitive = false;
|
||||
if (c == '%') {
|
||||
// dialplan pattern - turn it into a regular expression
|
||||
insensitive = true;
|
||||
String tmp = str;
|
||||
tmp.toUpper();
|
||||
str = "^";
|
||||
char last = '\0';
|
||||
int count = 0;
|
||||
bool esc = false;
|
||||
for (unsigned int i = 0; ; i++) {
|
||||
c = tmp.at(i);
|
||||
if (last && c != last) {
|
||||
switch (last) {
|
||||
case 'X':
|
||||
str << "[0-9]";
|
||||
break;
|
||||
case 'Z':
|
||||
str << "[1-9]";
|
||||
break;
|
||||
case 'N':
|
||||
str << "[2-9]";
|
||||
break;
|
||||
case '.':
|
||||
str << ".+";
|
||||
count = 1;
|
||||
break;
|
||||
}
|
||||
if (count > 1)
|
||||
str << "{" << count << "}";
|
||||
last = '\0';
|
||||
count = 0;
|
||||
}
|
||||
if (!c) {
|
||||
str << "$";
|
||||
break;
|
||||
}
|
||||
switch (c) {
|
||||
case '.':
|
||||
if (esc) {
|
||||
str << c;
|
||||
break;
|
||||
}
|
||||
// fall through
|
||||
case 'X':
|
||||
case 'Z':
|
||||
case 'N':
|
||||
last = c;
|
||||
count++;
|
||||
break;
|
||||
case '+':
|
||||
case '*':
|
||||
str << "\\";
|
||||
// fall through
|
||||
default:
|
||||
str << c;
|
||||
}
|
||||
esc = (c == '\\');
|
||||
}
|
||||
}
|
||||
else {
|
||||
// regexp - check for flags
|
||||
do {
|
||||
c = *expr;
|
||||
switch (c) {
|
||||
case 'i':
|
||||
expr++;
|
||||
insensitive = true;
|
||||
break;
|
||||
case 'b':
|
||||
expr++;
|
||||
extended = false;
|
||||
break;
|
||||
default:
|
||||
c = 0;
|
||||
}
|
||||
} while (c);
|
||||
}
|
||||
XDebug(this,DebugInfo,"Regexp '%s' flags '%s%s'",str.c_str(),
|
||||
(insensitive ? "i" : ""),(extended ? "" : "b"));
|
||||
addOpcode(str);
|
||||
//m_opcodes.append(new ExpWrapper(obj));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JsCode::getEscape(const char*& expr, String& str, char sep)
|
||||
{
|
||||
if (sep != '\'' && sep != '"') {
|
||||
// this is not a string but a regexp or dialplan template
|
||||
char c = *expr++;
|
||||
if (!c)
|
||||
return false;
|
||||
if (c != '\\' && c != sep)
|
||||
str << '\\';
|
||||
str << c;
|
||||
return true;
|
||||
}
|
||||
return ExpEvaluator::getEscape(expr,str,sep);
|
||||
}
|
||||
|
||||
bool JsCode::keywordChar(char c) const
|
||||
{
|
||||
return ExpEvaluator::keywordChar(c) || (c == '$');
|
||||
|
|
|
@ -561,6 +561,23 @@ protected:
|
|||
*/
|
||||
virtual bool getFunction(const char*& expr);
|
||||
|
||||
/**
|
||||
* Helper method - get a string, advance parsing pointer past it
|
||||
* @param expr Pointer to string separator, gets advanced on success
|
||||
* @param str String in which the result is returned
|
||||
* @return True if succeeded
|
||||
*/
|
||||
virtual bool getString(const char*& expr, String& str);
|
||||
|
||||
/**
|
||||
* Helper method - get an escaped component of a string
|
||||
* @param expr Pointer past escape character, gets advanced on success
|
||||
* @param str String in which the result is returned
|
||||
* @param sep String separator character
|
||||
* @return True if succeeded
|
||||
*/
|
||||
virtual bool getEscape(const char*& expr, String& str, char sep);
|
||||
|
||||
/**
|
||||
* Get a field keyword, advance parsing pointer past it
|
||||
* @param expr Pointer to text to parse, gets advanced on success
|
||||
|
|
Loading…
Reference in New Issue