mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-04-11 03:31:36 +00:00
MEDIUM: cfgparse: introduce weak and strong quoting
This patch introduces quoting which allows to write configuration string including spaces without escaping them. Strong (with single quotes) and weak (with double quotes) quoting are supported. Weak quoting supports escaping and special characters when strong quoting does not interpret anything. This patch could break configuration files where ' and " where used.
This commit is contained in:
parent
e428b08ee7
commit
f9873ba63a
@ -39,8 +39,9 @@ Summary
|
||||
|
||||
2. Configuring HAProxy
|
||||
2.1. Configuration file format
|
||||
2.2. Time format
|
||||
2.3. Examples
|
||||
2.2. Quoting and escaping
|
||||
2.3. Time format
|
||||
2.4. Examples
|
||||
|
||||
3. Global parameters
|
||||
3.1. Process management and security
|
||||
@ -366,12 +367,61 @@ HAProxy's configuration process involves 3 major sources of parameters :
|
||||
|
||||
The configuration file syntax consists in lines beginning with a keyword
|
||||
referenced in this manual, optionally followed by one or several parameters
|
||||
delimited by spaces. If spaces have to be entered in strings, then they must be
|
||||
preceded by a backslash ('\') to be escaped. Backslashes also have to be
|
||||
escaped by doubling them.
|
||||
delimited by spaces.
|
||||
|
||||
|
||||
2.2. Time format
|
||||
2.2. Quoting and escaping
|
||||
-------------------------
|
||||
|
||||
HAProxy's configuration introduces a quoting and escaping system similar to
|
||||
many programming languages. The configuration file supports 3 types: escaping
|
||||
with a backslash, weak quoting with double quotes, and strong quoting with
|
||||
single quotes.
|
||||
|
||||
If spaces have to be entered in strings, then they must be escaped by preceding
|
||||
them by a backslash ('\') or by quoting them. Backslashes also have to be
|
||||
escaped by doubling or strong quoting them.
|
||||
|
||||
Escaping is achieved by preceding a special character by a backslash ('\'):
|
||||
|
||||
\ to mark a space and differentiate it from a delimiter
|
||||
\# to mark a hash and differentiate it from a comment
|
||||
\\ to use a backslash
|
||||
\' to use a single quote and differentiate it from strong quoting
|
||||
\" to use a double quote and differentiate it from weak quoting
|
||||
|
||||
Weak quoting is achieved by using double quotes (""). Weak quoting prevents
|
||||
the interpretation of:
|
||||
|
||||
space as a parameter separator
|
||||
' single quote as a strong quoting delimiter
|
||||
# hash as a comment start
|
||||
|
||||
But interpretation of escaping and special characters are not prevented by weak
|
||||
quoting.
|
||||
|
||||
Strong quoting is achieved by using single quotes (''). Inside single quotes,
|
||||
nothing is interpreted, it's the efficient way to quote regexes.
|
||||
|
||||
Quoted and escaped strings are replaced in memory by their interpreted
|
||||
equivalent, it allows you to perform concatenation.
|
||||
|
||||
Example:
|
||||
# those are equivalents:
|
||||
log-format %{+Q}o\ %t\ %s\ %{-Q}r
|
||||
log-format "%{+Q}o %t %s %{-Q}r"
|
||||
log-format '%{+Q}o %t %s %{-Q}r'
|
||||
log-format "%{+Q}o %t"' %s %{-Q}r'
|
||||
log-format "%{+Q}o %t"' %s'\ %{-Q}r
|
||||
|
||||
# those are equivalents:
|
||||
reqrep "^([^\ :]*)\ /static/(.*)" \1\ /\2
|
||||
reqrep "^([^ :]*)\ /static/(.*)" '\1 /\2'
|
||||
reqrep "^([^ :]*)\ /static/(.*)" "\1 /\2"
|
||||
reqrep "^([^ :]*)\ /static/(.*)" "\1\ /\2"
|
||||
|
||||
|
||||
2.3. Time format
|
||||
----------------
|
||||
|
||||
Some parameters involve values representing time, such as timeouts. These
|
||||
@ -388,7 +438,7 @@ for every keyword. Supported units are :
|
||||
- d : days. 1d = 24h = 1440m = 86400s = 86400000ms
|
||||
|
||||
|
||||
2.3. Examples
|
||||
2.4. Examples
|
||||
-------------
|
||||
|
||||
# Simple configuration for an HTTP proxy listening on port 80 on all
|
||||
|
@ -6207,6 +6207,8 @@ int readcfgfile(const char *file)
|
||||
char *end;
|
||||
char *args[MAX_LINE_ARGS + 1];
|
||||
char *line = thisline;
|
||||
int dquote = 0; /* double quote */
|
||||
int squote = 0; /* simple quote */
|
||||
|
||||
linenum++;
|
||||
|
||||
@ -6224,15 +6226,31 @@ int readcfgfile(const char *file)
|
||||
/* skip leading spaces */
|
||||
while (isspace((unsigned char)*line))
|
||||
line++;
|
||||
|
||||
|
||||
arg = 0;
|
||||
args[arg] = line;
|
||||
|
||||
while (*line && arg < MAX_LINE_ARGS) {
|
||||
if (*line == '"' && !squote) { /* double quote outside single quotes */
|
||||
if (dquote)
|
||||
dquote = 0;
|
||||
else
|
||||
dquote = 1;
|
||||
memmove(line, line + 1, end - (line + 1));
|
||||
end--;
|
||||
}
|
||||
else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
|
||||
if (squote)
|
||||
squote = 0;
|
||||
else
|
||||
squote = 1;
|
||||
memmove(line, line + 1, end - (line + 1));
|
||||
end--;
|
||||
}
|
||||
else if (*line == '\\' && !squote) {
|
||||
/* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
|
||||
* C equivalent value. Other combinations left unchanged (eg: \1).
|
||||
*/
|
||||
if (*line == '\\') {
|
||||
int skip = 0;
|
||||
if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
|
||||
*line = line[1];
|
||||
@ -6241,7 +6259,7 @@ int readcfgfile(const char *file)
|
||||
else if (line[1] == 'r') {
|
||||
*line = '\r';
|
||||
skip = 1;
|
||||
}
|
||||
}
|
||||
else if (line[1] == 'n') {
|
||||
*line = '\n';
|
||||
skip = 1;
|
||||
@ -6264,6 +6282,12 @@ int readcfgfile(const char *file)
|
||||
Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
|
||||
err_code |= ERR_ALERT | ERR_FATAL;
|
||||
}
|
||||
} else if (line[1] == '"') {
|
||||
*line = '"';
|
||||
skip = 1;
|
||||
} else if (line[1] == '\'') {
|
||||
*line = '\'';
|
||||
skip = 1;
|
||||
}
|
||||
if (skip) {
|
||||
memmove(line + 1, line + 1 + skip, end - (line + skip));
|
||||
@ -6271,12 +6295,12 @@ int readcfgfile(const char *file)
|
||||
}
|
||||
line++;
|
||||
}
|
||||
else if (*line == '#' || *line == '\n' || *line == '\r') {
|
||||
else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
|
||||
/* end of string, end of loop */
|
||||
*line = 0;
|
||||
break;
|
||||
}
|
||||
else if (isspace((unsigned char)*line)) {
|
||||
else if (!squote && !dquote && isspace((unsigned char)*line)) {
|
||||
/* a non-escaped space is an argument separator */
|
||||
*line++ = '\0';
|
||||
while (isspace((unsigned char)*line))
|
||||
@ -6287,6 +6311,15 @@ int readcfgfile(const char *file)
|
||||
line++;
|
||||
}
|
||||
}
|
||||
if (dquote) {
|
||||
Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
|
||||
err_code |= ERR_ALERT | ERR_FATAL;
|
||||
}
|
||||
|
||||
if (squote) {
|
||||
Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
|
||||
err_code |= ERR_ALERT | ERR_FATAL;
|
||||
}
|
||||
|
||||
/* empty line */
|
||||
if (!**args)
|
||||
|
Loading…
Reference in New Issue
Block a user