+
+/*********************************************************************
+ *
+ * Function : filter_type_to_string
+ *
+ * Description : Converts a filter type enum into a string.
+ *
+ * Parameters :
+ * 1 : filter_type = filter_type as enum
+ *
+ * Returns : Pointer to static string.
+ *
+ *********************************************************************/
+static const char *filter_type_to_string(enum filter_type filter_type)
+{
+ switch (filter_type)
+ {
+ case FT_CONTENT_FILTER:
+ return "content filter";
+ case FT_CLIENT_HEADER_FILTER:
+ return "client-header filter";
+ case FT_SERVER_HEADER_FILTER:
+ return "server-header filter";
+ case FT_CLIENT_HEADER_TAGGER:
+ return "client-header tagger";
+ case FT_SERVER_HEADER_TAGGER:
+ return "server-header tagger";
+#ifdef FEATURE_EXTERNAL_FILTERS
+ case FT_EXTERNAL_CONTENT_FILTER:
+ return "external content filter";
+#endif
+ case FT_SUPPRESS_TAG:
+ return "suppress tag filter";
+ case FT_INVALID_FILTER:
+ return "invalid filter type";
+ }
+
+ return "unknown filter type";
+
+}
+
+/*********************************************************************
+ *
+ * Function : referenced_filters_are_missing
+ *
+ * Description : Checks if any filters of a certain type referenced
+ * in an action spec are missing.
+ *
+ * Parameters :
+ * 1 : csp = Current client state (buffers, headers, etc...)
+ * 2 : cur_action = The action spec to check.
+ * 3 : multi_index = The index where to look for the filter.
+ * 4 : filter_type = The filter type the caller is interested in.
+ *
+ * Returns : 0 => All referenced filters exist, everything else is an error.
+ *
+ *********************************************************************/
+static int referenced_filters_are_missing(const struct client_state *csp,
+ const struct action_spec *cur_action, int multi_index, enum filter_type filter_type)
+{
+ struct list_entry *filtername;
+
+ for (filtername = cur_action->multi_add[multi_index]->first;
+ filtername; filtername = filtername->next)
+ {
+ if (NULL == get_filter(csp, filtername->str, filter_type))
+ {
+ log_error(LOG_LEVEL_ERROR, "Missing %s '%s'",
+ filter_type_to_string(filter_type), filtername->str);
+ return 1;
+ }
+ }
+
+ return 0;
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : action_spec_is_valid
+ *
+ * Description : Should eventually figure out if an action spec
+ * is valid, but currently only checks that the
+ * referenced filters are accounted for.
+ *
+ * Parameters :
+ * 1 : csp = Current client state (buffers, headers, etc...)
+ * 2 : cur_action = The action spec to check.
+ *
+ * Returns : 0 => No problems detected, everything else is an error.
+ *
+ *********************************************************************/
+static int action_spec_is_valid(struct client_state *csp, const struct action_spec *cur_action)
+{
+ struct {
+ int multi_index;
+ enum filter_type filter_type;
+ } filter_map[] = {
+ {ACTION_MULTI_FILTER, FT_CONTENT_FILTER},
+ {ACTION_MULTI_CLIENT_HEADER_FILTER, FT_CLIENT_HEADER_FILTER},
+ {ACTION_MULTI_SERVER_HEADER_FILTER, FT_SERVER_HEADER_FILTER},
+ {ACTION_MULTI_CLIENT_HEADER_TAGGER, FT_CLIENT_HEADER_TAGGER},
+ {ACTION_MULTI_SERVER_HEADER_TAGGER, FT_SERVER_HEADER_TAGGER}
+ };
+ int errors = 0;
+ int i;
+
+ for (i = 0; i < SZ(filter_map); i++)
+ {
+ errors += referenced_filters_are_missing(csp, cur_action,
+ filter_map[i].multi_index, filter_map[i].filter_type);
+ }
+
+ return errors;
+
+}
+
+