Fixed parsing optional ACL names following the new acess_log config style. ACLs were treated as name=value options because the options loop lacked the termination condition (other than the end of all tokens on the line). The correct termination condition is a non-option token (the one that does not contain '='). As a side-effect of this change, ACL parts of http_access, access_log and other ACL-driven rules support inclusion of ACL names from files using standard quoted "filename" syntax. === modified file 'src/acl/Gadgets.cc' --- src/acl/Gadgets.cc 2012-09-05 14:49:29 +0000 +++ src/acl/Gadgets.cc 2013-04-16 04:46:27 +0000 @@ -192,41 +192,41 @@ A->cfgline = xstrdup(config_input_line); /* Append to the end of this list */ for (B = *head, T = head; B; T = &B->next, B = B->next); *T = A; /* We lock _acl_access structures in ACLChecklist::matchNonBlocking() */ } void aclParseAclList(ConfigParser &parser, ACLList ** head) { ACLList **Tail = head; /* sane name in the use below */ ACL *a = NULL; char *t; /* next expect a list of ACL names, possibly preceeded * by '!' for negation */ - while ((t = strtok(NULL, w_space))) { + while ((t = parser.strtokFile())) { ACLList *L = new ACLList; if (*t == '!') { L->negated (true); ++t; } debugs(28, 3, "aclParseAclList: looking for ACL name '" << t << "'"); a = ACL::FindByName(t); if (a == NULL) { debugs(28, DBG_CRITICAL, "aclParseAclList: ACL name '" << t << "' not found."); delete L; parser.destruct(); continue; } L->_acl = a; *Tail = L; Tail = &L->next; === modified file 'src/cache_cf.cc' --- src/cache_cf.cc 2013-04-12 16:29:21 +0000 +++ src/cache_cf.cc 2013-04-16 04:46:27 +0000 @@ -4052,63 +4052,66 @@ const char *token = strtok(NULL, w_space); if (!token) { self_destruct(); return; } if (strcmp(token, "none") == 0) { cl->type = Log::Format::CLF_NONE; aclParseAclList(LegacyParser, &cl->aclList); while (*logs) logs = &(*logs)->next; *logs = cl; return; } const char *logdef_name = NULL; // new style must start with a logger=... option if (strncasecmp(token, "logger=", 7) == 0) { cl->filename = xstrdup(token+7); - while ((token = strtok(NULL, w_space)) != NULL) { + while ((token = ConfigParser::strtokFile()) != NULL) { if (strncasecmp(token, "on-error=", 9) == 0) { if (strncasecmp(token+9, "die", 3) == 0) { cl->fatal = true; } else if (strncasecmp(token+9, "drop", 4) == 0) { cl->fatal = false; } else { debugs(3, DBG_CRITICAL, "Unknown value for on-error '" << token << "' expected 'drop' or 'die'"); self_destruct(); } } else if (strncasecmp(token, "buffer-size=", 12) == 0) { parseBytesOptionValue(&cl->bufferSize, B_BYTES_STR, token+12); } else if (strncasecmp(token, "logger=", 7) == 0) { debugs(3, DBG_CRITICAL, "duplicate access_log logger=... " << "option near " << token); self_destruct(); } else if (strncasecmp(token, "logformat=", 10) == 0) { logdef_name = token+10; - } else { + } else if (strchr(token, '=') != NULL) { debugs(3, DBG_CRITICAL, "Unknown access_log option " << token); self_destruct(); - return; + } else { + // put back the token; it must be an ACL + ConfigParser::strtokFileUndo(); + break; // done with name=value options, now to ACLs } } } else { // old or ancient style cl->filename = xstrdup(token); logdef_name = strtok(NULL, w_space); // may be nil } if (logdef_name == NULL) logdef_name = "squid"; debugs(3, 9, "Log definition name '" << logdef_name << "' file '" << cl->filename << "'"); /* look for the definition pointer corresponding to this name */ Format::Format *lf = Log::TheConfig.logformats; while (lf != NULL) { debugs(3, 9, "Comparing against '" << lf->name << "'"); if (strcmp(lf->name, logdef_name) == 0)