From: Alex Rousskov Date: Sat, 23 Mar 2013 02:07:38 +0000 (-0600) Subject: Initial support for "values with spaces" in ACL directives. X-Git-Tag: SQUID_3_4_0_2~14^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=56d8983f1d0f44207d0417052dce08385d0e9fc3;p=thirdparty%2Fsquid.git Initial support for "values with spaces" in ACL directives. Needs more work to support escape sequences, macros, and include files, but can be disabled using "configuration_includes_quoted_values off" in squid.conf. Needs better documentation. --- diff --git a/src/ConfigParser.cc b/src/ConfigParser.cc index ceac61590a..dfe393542c 100644 --- a/src/ConfigParser.cc +++ b/src/ConfigParser.cc @@ -41,6 +41,9 @@ char *ConfigParser::lastToken = NULL; std::queue ConfigParser::undo; + +int ConfigParser::RecognizeQuotedValues = true; + void ConfigParser::destruct() { @@ -63,6 +66,18 @@ ConfigParser::strtokFilePutBack(const char *tok) undo.push(tok); } +char * +xstrtok(char *str, const char *delimiters) +{ + assert(!str); // we are parsing the configuration file + // no support unless enabled in the configuration and + // no support for other delimiters (they may need to be eradicated!) + return (ConfigParser::RecognizeQuotedValues && + strcmp(delimiters, " \t\n\r") == 0) ? + ConfigParser::NextToken() : ::strtok(str, delimiters); +} + + char * ConfigParser::strtokFile(void) { @@ -77,9 +92,13 @@ ConfigParser::strtokFile(void) strncpy(undoToken, undo.front().c_str(), sizeof(undoToken)); undoToken[sizeof(undoToken) - 1] = '\0'; undo.pop(); - return undoToken; + return lastToken = undoToken; } + // XXX: add file:name support to the quoted string-aware parser + if (RecognizeQuotedValues) + return lastToken = ConfigParser::NextToken(); + lastToken = NULL; do { @@ -142,29 +161,62 @@ ConfigParser::strtokFile(void) return lastToken = t; } +/// returns token after stripping any comments +/// must be called in non-quoted context only +char * +ConfigParser::StripComment(char *token) +{ + if (!token) + return NULL; + + // we are outside the quoted string context + // assume that anything starting with a '#' is a comment + if (char *comment = strchr(token, '#')) { + *comment = '\0'; // remove the comment from this token + (void)strtok(NULL, ""); // remove the comment from the current line + if (!*token) + return NULL; // token was a comment + } + + return token; +} + void ConfigParser::ParseQuotedString(char **var, bool *wasQuoted) { - String sVar; - ParseQuotedString(&sVar, wasQuoted); - *var = xstrdup(sVar.termedBuf()); + if (const char *phrase = NextElement(wasQuoted)) + *var = xstrdup(phrase); + else + self_destruct(); } void ConfigParser::ParseQuotedString(String *var, bool *wasQuoted) { + if (const char *phrase = NextElement(wasQuoted)) + var->reset(phrase); + else + self_destruct(); +} + +char * +ConfigParser::NextElement(bool *wasQuoted) +{ + if (wasQuoted) + *wasQuoted = false; + // Get all of the remaining string char *token = strtok(NULL, ""); if (token == NULL) - self_destruct(); + return NULL; - if (*token != '"') { - token = strtok(token, w_space); - var->reset(token); - if (wasQuoted) - *wasQuoted = false; - return; - } else if (wasQuoted) + // skip leading whitespace (may skip the entire token that way) + while (xisspace(*token)) ++token; + + if (*token != '"') + return StripComment(strtok(token, w_space)); + + if (wasQuoted) *wasQuoted = true; char *s = token + 1; @@ -178,15 +230,27 @@ ConfigParser::ParseQuotedString(String *var, bool *wasQuoted) } if (*s != '"') { - debugs(3, DBG_CRITICAL, "ParseQuotedString: missing '\"' at the end of quoted string" ); + debugs(3, DBG_CRITICAL, "missing '\"' at the end of quoted string" ); self_destruct(); } strtok(s-1, "\""); /*Reset the strtok to point after the " */ *s = '\0'; - var->reset(token+1); + return (token+1); } +char * +ConfigParser::NextToken() +{ + return NextElement(NULL); + // TODO: support file:name syntax to auto-include files, but think how + // admins will be able to disable that interpretation w/o disabling + // macros and other special value processing. The "file:" prefix or + // any similar key construct would probably have to go outside the + // optionally quoted string for that to work: file:"name with $macros". +} + + const char * ConfigParser::QuoteString(String &var) { diff --git a/src/ConfigParser.h b/src/ConfigParser.h index c5807d8f5f..8564c34dd0 100644 --- a/src/ConfigParser.h +++ b/src/ConfigParser.h @@ -82,6 +82,22 @@ public: static char * strtokFile(); static void strtokFileUndo(); static void strtokFilePutBack(const char *); + + /** + Returns the body of the next element. The element is either a token or + a quoted string with optional escape sequences and/or macros. The body + of a quoted string element does not include quotes or escape sequences. + Future code will want to see Elements and not just their bodies. + */ + static char *NextToken(); + + /// configuration_includes_quoted_values in squid.conf + static int RecognizeQuotedValues; + +protected: + static char *NextElement(bool *wasQuoted); + static char *StripComment(char *token); + private: static char *lastToken; static std::queue undo; @@ -89,4 +105,9 @@ private: int parseConfigFile(const char *file_name); +/// XXX: Used for temporary hacks to allow old code to handle quoted values +/// without replacing every strtok() call. +extern char *xstrtok(char *str, const char *delimiters); + + #endif /* SQUID_CONFIGPARSER_H */ diff --git a/src/acl/Acl.cc b/src/acl/Acl.cc index 2eeef57fab..f550cdac7d 100644 --- a/src/acl/Acl.cc +++ b/src/acl/Acl.cc @@ -431,6 +431,14 @@ acl_access::operator delete (void *address) cbdataFree(t); } +/// XXX: Temporary hack to allow old ACL code to handle quoted values without +/// replacing every strtok() call. +char * +ACL::strtok(char *str, const char *delimiters) +{ + return xstrtok(str, delimiters); +} + ACL::Prototype::Prototype() : prototype (NULL), typeString (NULL) {} ACL::Prototype::Prototype (ACL const *aPrototype, char const *aType) : prototype (aPrototype), typeString (aType) diff --git a/src/acl/Acl.h b/src/acl/Acl.h index e7ae5af6f3..168293ba5b 100644 --- a/src/acl/Acl.h +++ b/src/acl/Acl.h @@ -151,6 +151,9 @@ public: typedef Vector::const_iterator const_iterator; void registerMe(); }; + +protected: + static char *strtok(char *str, const char *delimiters); }; /// \ingroup ACLAPI diff --git a/src/acl/Data.h b/src/acl/Data.h index 1ea9e061e3..342a15b3a2 100644 --- a/src/acl/Data.h +++ b/src/acl/Data.h @@ -33,6 +33,8 @@ #define SQUID_ACLDATA_H class wordlist; +extern char *xstrtok(char *str, const char *delimiters); + /// \ingroup ACLAPI template @@ -50,6 +52,11 @@ public: virtual void prepareForUse() {} virtual bool empty() const =0; + + + /// XXX: Temporary hack to allow old ACL code to handle quoted values without + /// replacing every strtok() call. + char *strtok(char *str, const char *dels) { return xstrtok(str, dels); } }; #endif /* SQUID_ACLDATA_H */ diff --git a/src/cache_cf.cc b/src/cache_cf.cc index da7e93d6b2..fcd2701efc 100644 --- a/src/cache_cf.cc +++ b/src/cache_cf.cc @@ -1302,6 +1302,7 @@ dump_acl(StoreEntry * entry, const char *name, ACL * ae) while (v != NULL) { debugs(3, 3, "dump_acl: " << name << " " << ae->name << " " << v->key); + // XXX: use something like ConfigParser::QuoteString() here storeAppendPrintf(entry, "%s ", v->key); v = v->next; } diff --git a/src/cf.data.pre b/src/cf.data.pre index e38603b1b5..7d642a3aa7 100644 --- a/src/cf.data.pre +++ b/src/cf.data.pre @@ -65,6 +65,19 @@ COMMENT_START configuration files. + Values with spaces, quotes, and other special characters + + Squid supports directive parameters with spaces, quotes, and other + special characters. Surround such parameters with "double quotes". Use + the configuration_includes_quoted_values directive to enable or + disable that support. + + XXX: Document escaping and macro substitution rules inside quoted + strings. + + XXX: Support single-quoted strings that prevent macro substitution. + + Conditional configuration If-statements can be used to make configuration directives @@ -8142,6 +8155,17 @@ COMMENT_START ----------------------------------------------------------------------------- COMMENT_END +NAME: configuration_includes_quoted_values +COMMENT: on|off +TYPE: onoff +DEFAULT: on +LOC: ConfigParser::RecognizeQuotedValues +DOC_START + If set, Squid will recognize each "quoted string" as a single + configuration directive parameter. The quotes are stripped before the + parameter value is interpreted or used. XXX: Give more details. +DOC_END + NAME: memory_pools COMMENT: on|off TYPE: onoff