... if FEATURE_EXTENDED_STATISTICS is enabled.
Sponsored by: Robert Klemme
return JB_ERR_PARSE;
}
}
+#ifdef FEATURE_EXTENDED_STATISTICS
+ if (0 == strcmpic(action->name, "+block"))
+ {
+ register_block_reason_for_statistics(value);
+ }
+#endif
/* FIXME: should validate option string here */
freez (cur_action->string[action->index]);
cur_action->string[action->index] = strdup(value);
#ifdef FEATURE_EXTENDED_STATISTICS
+/*********************************************************************
+ *
+ * Function : get_block_reason_statistics_table
+ *
+ * Description : Produces the block reason statistic table content.
+ *
+ * Parameters :
+ * 1 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : Pointer to the HTML statistic table content or
+ * NULL on out of memory
+ *
+ *********************************************************************/
+static char *get_block_reason_statistics_table(const struct client_state *csp)
+{
+ char buf[BUFFER_SIZE];
+ char *statistics;
+ int i;
+ struct file_list *fl;
+ jb_err err = JB_ERR_OK;
+
+ statistics = strdup_or_die("");
+
+ /* Run through all action files. */
+ for (i = 0; i < MAX_AF_FILES; i++)
+ {
+ struct url_actions *b;
+ struct action_spec *last_action = NULL;
+
+ if (((fl = csp->actions_list[i]) == NULL) || ((b = fl->f) == NULL))
+ {
+ /* Skip empty files */
+ continue;
+ }
+
+ /* Go through all the actions. */
+ for (b = b->next; NULL != b; b = b->next)
+ {
+ if (last_action == b->action)
+ {
+ continue;
+ }
+ if ((b->action->add & ACTION_BLOCK))
+ {
+ unsigned long long count;
+ const char *block_reason = b->action->string[ACTION_STRING_BLOCK];
+ const char *encoded_block_reason = html_encode(block_reason);
+
+ if (encoded_block_reason == NULL)
+ {
+ freez(statistics);
+ return NULL;
+ }
+ get_block_reason_count(block_reason, &count);
+ snprintf(buf, sizeof(buf),
+ "<tr><td>%s</td><td style=\"text-align: right\">%llu</td>",
+ encoded_block_reason, count);
+ freez(encoded_block_reason);
+
+ if (!err) err = string_append(&statistics, buf);
+ }
+ last_action = b->action;
+ }
+ }
+
+ return statistics;
+
+}
+
+
/*********************************************************************
*
* Function : get_filter_statistics_table
return statistics;
}
-#endif
+#endif /* def FEATURE_EXTENDED_STATISTICS */
/*********************************************************************
#endif /* ndef FEATURE_STATISTICS */
#ifdef FEATURE_EXTENDED_STATISTICS
+ {
+ char *block_reason_statistics = get_block_reason_statistics_table(csp);
+ if (block_reason_statistics != NULL)
+ {
+ if (!err) err = map(exports, "block-reason-statistics", 1, block_reason_statistics, 0);
+ }
+ else
+ {
+ if (!err) err = map_block_killer(exports, "extended-statistics");
+ }
+ }
{
char *filter_statistics = get_filter_statistics_table(csp);
if (filter_statistics != NULL)
#endif
struct url_actions *b);
+#ifdef FEATURE_EXTENDED_STATISTICS
+static void increment_block_reason_counter(const char *block_reason);
+#endif
+
#ifdef FEATURE_ACL
#ifdef HAVE_RFC2553
/*********************************************************************
return cgi_error_memory();
}
+#ifdef FEATURE_EXTENDED_STATISTICS
+ if (csp->action->string[ACTION_STRING_BLOCK] != NULL)
+ {
+ increment_block_reason_counter(csp->action->string[ACTION_STRING_BLOCK]);
+ }
+#endif
+
/*
* If it's an image-url, send back an image or redirect
* as specified by the relevant +image action
}
+
+struct block_statistics_entry
+{
+ char *block_reason;
+ unsigned long long count;
+
+ struct block_statistics_entry *next;
+};
+
+static struct block_statistics_entry *block_statistics = NULL;
+
+/*********************************************************************
+ *
+ * Function : register_block_reason_for_statistics
+ *
+ * Description : Registers a block reason so we can gather statistics
+ * for it unless the block reason has already been
+ * registered before.
+ *
+ * Parameters :
+ * 1 : block_reason = Block reason to register
+ *
+ * Returns : void
+ *
+ *********************************************************************/
+void register_block_reason_for_statistics(const char *block_reason)
+{
+ struct block_statistics_entry *entry;
+
+ privoxy_mutex_lock(&block_statistics_mutex);
+
+ if (block_statistics == NULL)
+ {
+ block_statistics = zalloc_or_die(sizeof(struct block_statistics_entry));
+ entry = block_statistics;
+ entry->block_reason = strdup_or_die(block_reason);
+ privoxy_mutex_unlock(&block_statistics_mutex);
+ return;
+ }
+ entry = block_statistics;
+ while (entry != NULL)
+ {
+ if (!strcmp(entry->block_reason, block_reason))
+ {
+ /* Already registered, nothing to do. */
+ break;
+ }
+ if (entry->next == NULL)
+ {
+ entry->next = zalloc_or_die(sizeof(struct block_statistics_entry));
+ entry->next->block_reason = strdup_or_die(block_reason);
+ break;
+ }
+ entry = entry->next;
+ }
+
+ privoxy_mutex_unlock(&block_statistics_mutex);
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : increment_block_reason_counter
+ *
+ * Description : Updates the counter for a block reason.
+ *
+ * Parameters :
+ * 1 : block_reason = Block reason to count
+ *
+ * Returns : void
+ *
+ *********************************************************************/
+static void increment_block_reason_counter(const char *block_reason)
+{
+ struct block_statistics_entry *entry;
+
+ privoxy_mutex_lock(&block_statistics_mutex);
+
+ entry = block_statistics;
+ while (entry != NULL)
+ {
+ if (!strcmp(entry->block_reason, block_reason))
+ {
+ entry->count++;
+ break;
+ }
+ entry = entry->next;
+ }
+
+ privoxy_mutex_unlock(&block_statistics_mutex);
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : get_block_reason_count
+ *
+ * Description : Gets number of times a block reason was used.
+ *
+ * Parameters :
+ * 1 : block_reason = Block reason to get statistics for.
+ * 2 : count = Storage for the number of times the block
+ * reason was used.
+ *
+ * Returns : void
+ *
+ *********************************************************************/
+void get_block_reason_count(const char *block_reason, unsigned long long *count)
+{
+ struct block_statistics_entry *entry;
+
+ privoxy_mutex_lock(&block_statistics_mutex);
+
+ entry = block_statistics;
+ while (entry != NULL)
+ {
+ if (!strcmp(entry->block_reason, block_reason))
+ {
+ *count = entry->count;
+ break;
+ }
+ entry = entry->next;
+ }
+
+ privoxy_mutex_unlock(&block_statistics_mutex);
+
+}
+
#endif /* def FEATURE_EXTENDED_STATISTICS */
/*
unsigned long long *executions,
unsigned long long *pages_modified,
unsigned long long *hits);
+
+extern void register_block_reason_for_statistics(const char *block_reason);
+extern void get_block_reason_count(const char *block_reason,
+ unsigned long long *count);
#endif
#endif /* ndef FILTERS_H_INCLUDED */
#endif
#ifdef FEATURE_EXTENDED_STATISTICS
privoxy_mutex_t filter_statistics_mutex;
+privoxy_mutex_t block_statistics_mutex;
#endif
#if !defined(HAVE_GETHOSTBYADDR_R) || !defined(HAVE_GETHOSTBYNAME_R)
#endif
#ifdef FEATURE_EXTENDED_STATISTICS
privoxy_mutex_init(&filter_statistics_mutex);
+ privoxy_mutex_init(&block_statistics_mutex);
#endif
/*
#ifdef FEATURE_EXTENDED_STATISTICS
extern privoxy_mutex_t filter_statistics_mutex;
+extern privoxy_mutex_t block_statistics_mutex;
#endif
#ifndef HAVE_GMTIME_R
# There haven't any statistics been collected yet
# extended-statistics:
# Privoxy was compiled with extended statistiscs support.
-# In this case the following symbol is available:
+# In this case the following symbols are available:
+# block-reason-statistics:
+# Table content of block reasons and how often they were used.
# filter-statistics:
# Table content of content filter statistics.
# pcrs-support:
<!-- if-statistics-end@ -->
<!-- @if-extended-statistics-start -->
+ <tr>
+ <td class="box">
+ <h2>Block Reason Statistics:</h2>
+ <table summary="Statistics for block reasons" border="1">
+ <tr><th>Block reason</th><th>Count</th></tr>
+@block-reason-statistics@ </table>
+ </td>
+ </tr>
<tr>
<td class="box">
<h2>Content Filter Statistics:</h2>