]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
mod_macro improvements to bypass "expected" warnings and conflicts
authorJim Jagielski <jim@apache.org>
Tue, 22 Nov 2016 14:06:28 +0000 (14:06 +0000)
committerJim Jagielski <jim@apache.org>
Tue, 22 Nov 2016 14:06:28 +0000 (14:06 +0000)
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1770843 13f79535-47bb-0310-9956-ffa450edef68

docs/manual/mod/mod_macro.xml
modules/core/mod_macro.c

index cf39ed6e720da43bd8861d34f16f370171a296f7..9a22d5ae3c2371add20a0d3bc70382b27e18ee21 100644 (file)
@@ -277,4 +277,32 @@ UndefMacro RestrictedAccessPolicy
 </usage>
 </directivesynopsis>
 
+<!-- MacroIgnoreEmptyArg -->
+<directivesynopsis>
+<name>MacroIgnoreEmptyArgs</name>
+<description>Ignore warnings, and does not log, about empty Macro argument(s)</description>
+
+<syntax>MacroIgnoreEmptyArgs</syntax>
+<contextlist>
+<context>server config</context>
+<context>virtual host</context>
+<context>directory</context>
+</contextlist>
+
+</directivesynopsis>
+
+<!-- MacroIgnoreBadNesting -->
+<directivesynopsis>
+<name>MacroIgnoreBadNesting</name>
+<description>Ignore warnings, and does not log, about bad nesting of Macros</description>
+
+<syntax>MacroIgnoreBadNesting</syntax>
+<contextlist>
+<context>server config</context>
+<context>virtual host</context>
+<context>directory</context>
+</contextlist>
+
+</directivesynopsis>
+
 </modulesynopsis>
index dae4fcd297150d06e32bb9fe7dedff7da28f36a2..09ff430570ddc3950cd7ec5c955ad112820dfdf0 100644 (file)
@@ -49,6 +49,10 @@ module AP_MODULE_DECLARE_DATA macro_module;
 
 /********************************************************** MACRO MANAGEMENT */
 
+/* Global warning modifiers */
+int ignore_empty = FALSE;             /* no warning about empty argument */
+int ignore_bad_nesting = FALSE;       /* no warning about bad nesting */
+
 /*
   this is a macro: name, arguments, contents, location.
 */
@@ -58,6 +62,8 @@ typedef struct
     apr_array_header_t *arguments; /* of char*, macro parameter names */
     apr_array_header_t *contents;  /* of char*, macro body */
     char *location;                /* of macro definition, for error messages */
+    int ignore_empty;             /* no warning about empty argument */
+    int ignore_bad_nesting;       /* no warning about bad nesting */
 } ap_macro_t;
 
 /* configuration tokens.
@@ -67,7 +73,11 @@ typedef struct
 #define USE_MACRO   "Use"
 #define UNDEF_MACRO "UndefMacro"
 
-/*
+#define IGNORE_EMPTY_MACRO_FLAG             "/IgnoreEmptyArgs"
+#define IGNORE_BAD_NESTING_MACRO_FLAG       "/IgnoreBadNesting"
+#define IGNORE_EMPTY_MACRO_DIRECTIVE        "MacroIgnoreEmptyArgs"
+#define IGNORE_BAD_NESTING_MACRO_DIRECTIVE  "MacroIgnoreBadNesting"
+ /*
   Macros are kept globally...
   They are not per-server or per-directory entities.
 
@@ -135,7 +145,8 @@ static char *get_lines_till_end_token(apr_pool_t * pool,
                                       const char *end_token,
                                       const char *begin_token,
                                       const char *where,
-                                      apr_array_header_t ** plines)
+                                      apr_array_header_t ** plines,
+                                      int ignore_nesting)
 {
     apr_array_header_t *lines = apr_array_make(pool, 1, sizeof(char *));
     char line[MAX_STRING_LEN];  /* sorry, but this is expected by getline:-( */
@@ -153,7 +164,7 @@ static char *get_lines_till_end_token(apr_pool_t * pool,
             /* detect nesting... */
             if (!strncmp(first, "</", 2)) {
                 any_nesting--;
-                if (any_nesting < 0) {
+                if (!ignore_nesting && (any_nesting < 0)) {
                     ap_log_error(APLOG_MARK, APLOG_WARNING,
                                  0, NULL, APLOGNO(02793)
                                  "bad (negative) nesting on line %d of %s",
@@ -180,7 +191,7 @@ static char *get_lines_till_end_token(apr_pool_t * pool,
 
                 macro_nesting--;
                 if (!macro_nesting) {
-                    if (any_nesting) {
+                    if (!ignore_nesting && any_nesting) {
                         ap_log_error(APLOG_MARK,
                                      APLOG_WARNING, 0, NULL, APLOGNO(02795)
                                      "bad cumulated nesting (%+d) in %s",
@@ -255,6 +266,13 @@ static const char *check_macro_arguments(apr_pool_t * pool,
                          tab[i], i + 1, ARG_PREFIX);
         }
 
+               if ((tab[i][0] == '$') && (tab[i][1] == '{')) {
+                       ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, APLOGNO(02805)
+                               "macro '%s' (%s) "
+                               "argument name '%s' (#%d) clashes with 'Define' syntax '${...}', better use '$(...)'.",
+                               macro->name, macro->location, tab[i], i + 1);
+               }
+
         for (j = i + 1; j < nelts; j++) {
             size_t ltabj = strlen(tab[j]);
 
@@ -757,7 +775,25 @@ static const char *macro_section(cmd_parms * cmd,
                      where, ARG_PREFIX);
     }
 
-    /* get macro parameters */
+       /* get/remove macro modifiers from parameters */
+#define CHECK_MACRO_FLAG(arg_, flag_str, flag_val)  if (!strncasecmp(arg_, flag_str, strlen(flag_str))) { flag_val = TRUE; arg_ += strlen(flag_str); if (!*arg) break;}
+       while (*arg == '/') {
+               CHECK_MACRO_FLAG(arg, IGNORE_EMPTY_MACRO_FLAG, macro->ignore_empty);
+               CHECK_MACRO_FLAG(arg, IGNORE_BAD_NESTING_MACRO_FLAG, macro->ignore_bad_nesting);
+               if (*arg != ' ') {
+                       char *c = ap_strchr(arg, ' ');
+                       if (c) *c = '\0';
+                       ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, APLOGNO(02804)
+                               "%s: unknown flag '%s'", where, arg);
+                       if (c) {
+                               *c = ' ';
+                               arg = c;
+                       }
+               }
+               arg++;
+       }
+
+       /* get macro parameters */
     macro->arguments = get_arguments(pool, arg);
 
     errmsg = check_macro_arguments(cmd->temp_pool, macro);
@@ -768,7 +804,7 @@ static const char *macro_section(cmd_parms * cmd,
 
     errmsg = get_lines_till_end_token(pool, cmd->config_file,
                                       END_MACRO, BEGIN_MACRO,
-                                      where, &macro->contents);
+                                      where, &macro->contents, ignore_bad_nesting || macro->ignore_bad_nesting);
 
     if (errmsg) {
         return apr_psprintf(cmd->temp_pool,
@@ -854,7 +890,8 @@ static const char *use_macro(cmd_parms * cmd, void *dummy, const char *arg)
                          cmd->config_file->line_number,
                          cmd->config_file->name);
 
-    check_macro_use_arguments(where, replacements);
+    if (!ignore_empty && !macro->ignore_empty)
+               check_macro_use_arguments(where, replacements);
 
     errmsg = process_content(cmd->temp_pool, macro, replacements,
                              NULL, &contents);
@@ -905,6 +942,18 @@ static const char *undef_macro(cmd_parms * cmd, void *dummy, const char *arg)
     return NULL;
 }
 
+static const char *macro_ignore_empty(cmd_parms * cmd, void *dummy)
+{
+       ignore_empty = TRUE;
+       return NULL;
+}
+
+static const char *macro_ignore_bad_nesting(cmd_parms * cmd, void *dummy)
+{
+       ignore_bad_nesting = TRUE;
+       return NULL;
+}
+
 static int macro_pre_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp)
 {
     ap_macros = NULL;
@@ -925,6 +974,10 @@ static const command_rec macro_cmds[] = {
                      "Use of a macro."),
     AP_INIT_TAKE1(UNDEF_MACRO, undef_macro, NULL, EXEC_ON_READ | OR_ALL,
                   "Remove a macro definition."),
+       AP_INIT_NO_ARGS(IGNORE_EMPTY_MACRO_DIRECTIVE, macro_ignore_empty, NULL, EXEC_ON_READ | OR_ALL,
+                     "Globally ignore warnings about empty arguments."),
+       AP_INIT_NO_ARGS(IGNORE_BAD_NESTING_MACRO_DIRECTIVE, macro_ignore_bad_nesting, NULL, EXEC_ON_READ | OR_ALL,
+                     "Globally ignore warnings about bad nesting."),
 
     {NULL}
 };