+ !list_is_empty(action->multi[ACTION_MULTI_FILTER]) ||
+ !list_is_empty(action->multi[ACTION_MULTI_EXTERNAL_FILTER]));
+}
+
+
+/*********************************************************************
+ *
+ * Function : filters_available
+ *
+ * Description : Checks whether there are any filters available.
+ *
+ * Parameters :
+ * 1 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : TRUE for yes, FALSE otherwise.
+ *
+ *********************************************************************/
+int filters_available(const struct client_state *csp)
+{
+ int i;
+ for (i = 0; i < MAX_AF_FILES; i++)
+ {
+ const struct file_list *fl = csp->rlist[i];
+ if ((NULL != fl) && (NULL != fl->f))
+ {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+#ifdef FEATURE_EXTENDED_STATISTICS
+
+struct filter_statistics_entry
+{
+ char *filter;
+ unsigned long long executions;
+ unsigned long long response_bodies_modified;
+ unsigned long long hits;
+
+ struct filter_statistics_entry *next;
+};
+
+static struct filter_statistics_entry *filter_statistics = NULL;
+
+
+/*********************************************************************
+ *
+ * Function : register_filter_for_statistics
+ *
+ * Description : Registers a filter so we can gather statistics for
+ * it unless the filter has already been registered
+ * before.
+ *
+ * Parameters :
+ * 1 : filter = Name of the filter to register
+ *
+ * Returns : void
+ *
+ *********************************************************************/
+void register_filter_for_statistics(const char *filter)
+{
+ struct filter_statistics_entry *entry;
+
+ privoxy_mutex_lock(&filter_statistics_mutex);
+
+ if (filter_statistics == NULL)
+ {
+ filter_statistics = zalloc_or_die(sizeof(struct filter_statistics_entry));
+ entry = filter_statistics;
+ entry->filter = strdup_or_die(filter);
+ privoxy_mutex_unlock(&filter_statistics_mutex);
+ return;
+ }
+ entry = filter_statistics;
+ while (entry != NULL)
+ {
+ if (!strcmp(entry->filter, filter))
+ {
+ /* Already registered, nothing to do. */
+ break;
+ }
+ if (entry->next == NULL)
+ {
+ entry->next = zalloc_or_die(sizeof(struct filter_statistics_entry));
+ entry->next->filter = strdup_or_die(filter);
+ break;
+ }
+ entry = entry->next;
+ }
+
+ privoxy_mutex_unlock(&filter_statistics_mutex);
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : update_filter_statistics
+ *
+ * Description : Updates the statistics for a filter.
+ *
+ * Parameters :
+ * 1 : filter = Name of the filter to update
+ * 2 : hits = Hit count.
+ *
+ * Returns : void
+ *
+ *********************************************************************/
+void update_filter_statistics(const char *filter, int hits)
+{
+ struct filter_statistics_entry *entry;
+
+ privoxy_mutex_lock(&filter_statistics_mutex);
+
+ entry = filter_statistics;
+ while (entry != NULL)
+ {
+ if (!strcmp(entry->filter, filter))
+ {
+ entry->executions++;
+ if (hits != 0)
+ {
+ entry->response_bodies_modified++;
+ entry->hits += (unsigned)hits;
+ }
+ break;
+ }
+ entry = entry->next;
+ }
+
+ privoxy_mutex_unlock(&filter_statistics_mutex);
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : get_filter_statistics
+ *
+ * Description : Gets the statistics for a filter.
+ *
+ * Parameters :
+ * 1 : filter = Name of the filter to get statistics for.
+ * 2 : executions = Storage for the execution count.
+ * 3 : response_bodies_modified = Storage for the number
+ * of modified response bodies.
+ * 4 : hits = Storage for the number of hits.
+ *
+ * Returns : void
+ *
+ *********************************************************************/
+void get_filter_statistics(const char *filter, unsigned long long *executions,
+ unsigned long long *response_bodies_modified,
+ unsigned long long *hits)
+{
+ struct filter_statistics_entry *entry;
+
+ privoxy_mutex_lock(&filter_statistics_mutex);
+
+ entry = filter_statistics;
+ while (entry != NULL)
+ {
+ if (!strcmp(entry->filter, filter))
+ {
+ *executions = entry->executions;
+ *response_bodies_modified = entry->response_bodies_modified;
+ *hits = entry->hits;
+ break;
+ }
+ entry = entry->next;
+ }
+
+ privoxy_mutex_unlock(&filter_statistics_mutex);
+