mirror of
https://github.com/pi-hole/FTL.git
synced 2024-10-26 16:52:18 +02:00
Reduce code duplication by factoring out filter regex compilation
Signed-off-by: DL6ER <dl6er@dl6er.de>
This commit is contained in:
@@ -15,6 +15,8 @@
|
||||
// type cJSON
|
||||
#include "webserver/cJSON/cJSON.h"
|
||||
#include "webserver/http-common.h"
|
||||
// regex_t
|
||||
#include "regex_r.h"
|
||||
|
||||
// Common definitions
|
||||
#define LOCALHOSTv4 "127.0.0.1"
|
||||
@@ -43,6 +45,7 @@ int api_history_database_clients(struct ftl_conn *api);
|
||||
// Query methods
|
||||
int api_queries(struct ftl_conn *api);
|
||||
int api_queries_suggestions(struct ftl_conn *api);
|
||||
bool compile_filter_regex(struct ftl_conn *api, const char *path, cJSON *json, regex_t **regex, unsigned int *N_regex);
|
||||
|
||||
// Statistics methods (database)
|
||||
int api_stats_database_top_items(struct ftl_conn *api);
|
||||
|
||||
+68
-98
@@ -19,7 +19,6 @@
|
||||
#include "database/aliasclients.h"
|
||||
// get_memdb()
|
||||
#include "database/query-table.h"
|
||||
#include "regex.h"
|
||||
// dbopen(false, ), dbclose()
|
||||
#include "database/common.h"
|
||||
|
||||
@@ -444,103 +443,19 @@ int api_queries(struct ftl_conn *api)
|
||||
bool filtering = false;
|
||||
|
||||
// Regex filtering?
|
||||
const int N_regex_domains = cJSON_GetArraySize(config.webserver.api.excludeDomains.v.json);
|
||||
regex_t *regex_domains = NULL;
|
||||
if(N_regex_domains > 0)
|
||||
{
|
||||
// Allocate memory for regex array
|
||||
regex_domains = calloc(N_regex_domains, sizeof(regex_t));
|
||||
if(regex_domains == NULL)
|
||||
{
|
||||
return send_json_error(api, 500,
|
||||
"internal_error",
|
||||
"Internal server error, failed to allocate memory for domain regex array",
|
||||
NULL);
|
||||
}
|
||||
|
||||
// Compile regexes
|
||||
unsigned int i = 0;
|
||||
cJSON *filter = NULL;
|
||||
cJSON_ArrayForEach(filter, config.webserver.api.excludeDomains.v.json)
|
||||
{
|
||||
// Skip non-string, invalid and empty values
|
||||
if(!cJSON_IsString(filter) || filter->valuestring == NULL || strlen(filter->valuestring) == 0)
|
||||
{
|
||||
log_warn("Skipping invalid regex at webserver.api.excludeDomains.%u", i);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Compile regex
|
||||
int rc = regcomp(®ex_domains[i], filter->valuestring, REG_EXTENDED);
|
||||
if(rc != 0)
|
||||
{
|
||||
// Failed to compile regex
|
||||
char errbuf[1024] = { 0 };
|
||||
regerror(rc, ®ex_domains[i], errbuf, sizeof(errbuf));
|
||||
log_err("Failed to compile domain regex \"%s\": %s",
|
||||
filter->valuestring, errbuf);
|
||||
return send_json_error(api, 400,
|
||||
"bad_request",
|
||||
"Failed to compile domain regex",
|
||||
filter->valuestring);
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
// We are filtering, so we have to continue to step over the
|
||||
// remaining rows to get the correct number of total records
|
||||
unsigned int N_regex_domains = 0;
|
||||
if(compile_filter_regex(api, "webserver.api.excludeDomains",
|
||||
config.webserver.api.excludeDomains.v.json,
|
||||
®ex_domains, &N_regex_domains))
|
||||
filtering = true;
|
||||
}
|
||||
|
||||
const int N_regex_clients = cJSON_GetArraySize(config.webserver.api.excludeClients.v.json);
|
||||
regex_t *regex_clients = NULL;
|
||||
if(N_regex_clients > 0)
|
||||
{
|
||||
// Allocate memory for regex array
|
||||
regex_clients = calloc(N_regex_clients, sizeof(regex_t));
|
||||
if(regex_clients == NULL)
|
||||
{
|
||||
return send_json_error(api, 500,
|
||||
"internal_error",
|
||||
"Internal server error, failed to allocate memory for client regex array",
|
||||
NULL);
|
||||
}
|
||||
|
||||
// Compile regexes
|
||||
unsigned int i = 0;
|
||||
cJSON *filter = NULL;
|
||||
cJSON_ArrayForEach(filter, config.webserver.api.excludeClients.v.json)
|
||||
{
|
||||
// Skip non-string, invalid and empty values
|
||||
if(!cJSON_IsString(filter) || filter->valuestring == NULL || strlen(filter->valuestring) == 0)
|
||||
{
|
||||
log_warn("Skipping invalid regex at webserver.api.excludeClients.%u", i);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Compile regex
|
||||
int rc = regcomp(®ex_clients[i], filter->valuestring, REG_EXTENDED);
|
||||
if(rc != 0)
|
||||
{
|
||||
// Failed to compile regex
|
||||
char errbuf[1024] = { 0 };
|
||||
regerror(rc, ®ex_clients[i], errbuf, sizeof(errbuf));
|
||||
log_err("Failed to compile client regex \"%s\": %s",
|
||||
filter->valuestring, errbuf);
|
||||
return send_json_error(api, 400,
|
||||
"bad_request",
|
||||
"Failed to compile client regex",
|
||||
filter->valuestring);
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
// We are filtering, so we have to continue to step over the
|
||||
// remaining rows to get the correct number of total records
|
||||
unsigned int N_regex_clients = 0;
|
||||
if(compile_filter_regex(api, "webserver.api.excludeClients",
|
||||
config.webserver.api.excludeClients.v.json,
|
||||
®ex_clients, &N_regex_clients))
|
||||
filtering = true;
|
||||
}
|
||||
|
||||
// Finish preparing query string
|
||||
querystr_finish(querystr, sort_col, sort_dir);
|
||||
@@ -824,7 +739,7 @@ int api_queries(struct ftl_conn *api)
|
||||
{
|
||||
bool match = false;
|
||||
// Iterate over all regex filters
|
||||
for(int i = 0; i < N_regex_domains; i++)
|
||||
for(unsigned int i = 0; i < N_regex_domains; i++)
|
||||
{
|
||||
// Check if the domain matches the regex
|
||||
if(regexec(®ex_domains[i], domain, 0, NULL, 0) == 0)
|
||||
@@ -853,7 +768,7 @@ int api_queries(struct ftl_conn *api)
|
||||
{
|
||||
bool match = false;
|
||||
// Iterate over all regex filters
|
||||
for(int i = 0; i < N_regex_clients; i++)
|
||||
for(unsigned int i = 0; i < N_regex_clients; i++)
|
||||
{
|
||||
// Check if the domain matches the regex
|
||||
if(regexec(®ex_clients[i], client_ip, 0, NULL, 0) == 0)
|
||||
@@ -1049,7 +964,7 @@ int api_queries(struct ftl_conn *api)
|
||||
if(N_regex_domains > 0)
|
||||
{
|
||||
// Free individual regexes
|
||||
for(int i = 0; i < N_regex_domains; i++)
|
||||
for(unsigned int i = 0; i < N_regex_domains; i++)
|
||||
regfree(®ex_domains[i]);
|
||||
|
||||
// Free array of regex pointers
|
||||
@@ -1058,12 +973,67 @@ int api_queries(struct ftl_conn *api)
|
||||
if(N_regex_clients > 0)
|
||||
{
|
||||
// Free individual regexes
|
||||
for(int i = 0; i < N_regex_clients; i++)
|
||||
for(unsigned int i = 0; i < N_regex_clients; i++)
|
||||
regfree(®ex_clients[i]);
|
||||
|
||||
// Free array of regex pointers
|
||||
// Free array of regex po^inters
|
||||
free(regex_clients);
|
||||
}
|
||||
|
||||
JSON_SEND_OBJECT(json);
|
||||
}
|
||||
|
||||
bool compile_filter_regex(struct ftl_conn *api, const char *path, cJSON *json, regex_t **regex, unsigned int *N_regex)
|
||||
{
|
||||
|
||||
const int N = cJSON_GetArraySize(json);
|
||||
if(N < 1)
|
||||
return false;
|
||||
|
||||
// Set number of regexes (positive = unsigned integer)
|
||||
*N_regex = N;
|
||||
|
||||
// Allocate memory for regex array
|
||||
*regex = calloc(N, sizeof(regex_t));
|
||||
if(*regex == NULL)
|
||||
{
|
||||
return send_json_error(api, 500,
|
||||
"internal_error",
|
||||
"Internal server error, failed to allocate memory for regex array",
|
||||
NULL);
|
||||
}
|
||||
|
||||
// Compile regexes
|
||||
unsigned int i = 0;
|
||||
cJSON *filter = NULL;
|
||||
cJSON_ArrayForEach(filter, json)
|
||||
{
|
||||
// Skip non-string, invalid and empty values
|
||||
if(!cJSON_IsString(filter) || filter->valuestring == NULL || strlen(filter->valuestring) == 0)
|
||||
{
|
||||
log_warn("Skipping invalid regex at %s.%u", path, i);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Compile regex
|
||||
int rc = regcomp(regex[i], filter->valuestring, REG_EXTENDED);
|
||||
if(rc != 0)
|
||||
{
|
||||
// Failed to compile regex
|
||||
char errbuf[1024] = { 0 };
|
||||
regerror(rc, regex[i], errbuf, sizeof(errbuf));
|
||||
log_err("Failed to compile regex \"%s\": %s",
|
||||
filter->valuestring, errbuf);
|
||||
return send_json_error(api, 400,
|
||||
"bad_request",
|
||||
"Failed to compile regex",
|
||||
filter->valuestring);
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
// We are filtering, so we have to continue to step over the
|
||||
// remaining rows to get the correct number of total records
|
||||
return true;
|
||||
}
|
||||
+12
-90
@@ -216,50 +216,11 @@ int api_stats_top_domains(struct ftl_conn *api)
|
||||
clearSetupVarsArray();
|
||||
|
||||
// Get domains which the user doesn't want to see
|
||||
const int N_regex_domains = cJSON_GetArraySize(config.webserver.api.excludeDomains.v.json);
|
||||
regex_t *regex_domains = NULL;
|
||||
if(N_regex_domains > 0)
|
||||
{
|
||||
// Allocate memory for regex array
|
||||
regex_domains = calloc(N_regex_domains, sizeof(regex_t));
|
||||
if(regex_domains == NULL)
|
||||
{
|
||||
return send_json_error(api, 500,
|
||||
"internal_error",
|
||||
"Internal server error, failed to allocate memory for client regex array",
|
||||
NULL);
|
||||
}
|
||||
|
||||
// Compile regexes
|
||||
unsigned int i = 0;
|
||||
cJSON *filter = NULL;
|
||||
cJSON_ArrayForEach(filter, config.webserver.api.excludeDomains.v.json)
|
||||
{
|
||||
// Skip non-string, invalid and empty values
|
||||
if(!cJSON_IsString(filter) || filter->valuestring == NULL || strlen(filter->valuestring) == 0)
|
||||
{
|
||||
log_warn("Skipping invalid regex at webserver.api.excludeDomains.%u", i);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Compile regex
|
||||
int rc = regcomp(®ex_domains[i], filter->valuestring, REG_EXTENDED);
|
||||
if(rc != 0)
|
||||
{
|
||||
// Failed to compile regex
|
||||
char errbuf[1024] = { 0 };
|
||||
regerror(rc, ®ex_domains[i], errbuf, sizeof(errbuf));
|
||||
log_err("Failed to compile domain regex \"%s\": %s",
|
||||
filter->valuestring, errbuf);
|
||||
return send_json_error(api, 400,
|
||||
"bad_request",
|
||||
"Failed to compile domain regex",
|
||||
filter->valuestring);
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
unsigned int N_regex_domains = 0;
|
||||
compile_filter_regex(api, "webserver.api.excludeDomains",
|
||||
config.webserver.api.excludeDomains.v.json,
|
||||
®ex_domains, &N_regex_domains);
|
||||
|
||||
int n = 0;
|
||||
cJSON *top_domains = JSON_NEW_ARRAY();
|
||||
@@ -284,7 +245,7 @@ int api_stats_top_domains(struct ftl_conn *api)
|
||||
if(N_regex_domains > 0)
|
||||
{
|
||||
// Iterate over all regex filters
|
||||
for(int j = 0; j < N_regex_domains; j++)
|
||||
for(unsigned int j = 0; j < N_regex_domains; j++)
|
||||
{
|
||||
// Check if the domain matches the regex
|
||||
if(regexec(®ex_domains[j], domain_name, 0, NULL, 0) == 0)
|
||||
@@ -328,7 +289,7 @@ int api_stats_top_domains(struct ftl_conn *api)
|
||||
if(N_regex_domains > 0)
|
||||
{
|
||||
// Free individual regexes
|
||||
for(int i = 0; i < N_regex_domains; i++)
|
||||
for(unsigned int i = 0; i < N_regex_domains; i++)
|
||||
regfree(®ex_domains[i]);
|
||||
|
||||
// Free array of regex pointers
|
||||
@@ -403,50 +364,11 @@ int api_stats_top_clients(struct ftl_conn *api)
|
||||
qsort(temparray, clients, sizeof(int[2]), cmpdesc);
|
||||
|
||||
// Get clients which the user doesn't want to see
|
||||
const int N_regex_clients = cJSON_GetArraySize(config.webserver.api.excludeClients.v.json);
|
||||
regex_t *regex_clients = NULL;
|
||||
if(N_regex_clients > 0)
|
||||
{
|
||||
// Allocate memory for regex array
|
||||
regex_clients = calloc(N_regex_clients, sizeof(regex_t));
|
||||
if(regex_clients == NULL)
|
||||
{
|
||||
return send_json_error(api, 500,
|
||||
"internal_error",
|
||||
"Internal server error, failed to allocate memory for client regex array",
|
||||
NULL);
|
||||
}
|
||||
|
||||
// Compile regexes
|
||||
unsigned int i = 0;
|
||||
cJSON *filter = NULL;
|
||||
cJSON_ArrayForEach(filter, config.webserver.api.excludeClients.v.json)
|
||||
{
|
||||
// Skip non-string, invalid and empty values
|
||||
if(!cJSON_IsString(filter) || filter->valuestring == NULL || strlen(filter->valuestring) == 0)
|
||||
{
|
||||
log_warn("Skipping invalid regex at webserver.api.excludeClients.%u", i);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Compile regex
|
||||
int rc = regcomp(®ex_clients[i], filter->valuestring, REG_EXTENDED);
|
||||
if(rc != 0)
|
||||
{
|
||||
// Failed to compile regex
|
||||
char errbuf[1024] = { 0 };
|
||||
regerror(rc, ®ex_clients[i], errbuf, sizeof(errbuf));
|
||||
log_err("Failed to compile client regex \"%s\": %s",
|
||||
filter->valuestring, errbuf);
|
||||
return send_json_error(api, 400,
|
||||
"bad_request",
|
||||
"Failed to compile client regex",
|
||||
filter->valuestring);
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
unsigned int N_regex_clients = 0;
|
||||
compile_filter_regex(api, "webserver.api.excludeClients",
|
||||
config.webserver.api.excludeClients.v.json,
|
||||
®ex_clients, &N_regex_clients);
|
||||
|
||||
int n = 0;
|
||||
cJSON *top_clients = JSON_NEW_ARRAY();
|
||||
@@ -473,7 +395,7 @@ int api_stats_top_clients(struct ftl_conn *api)
|
||||
if(N_regex_clients > 0)
|
||||
{
|
||||
// Iterate over all regex filters
|
||||
for(int j = 0; j < N_regex_clients; j++)
|
||||
for(unsigned int j = 0; j < N_regex_clients; j++)
|
||||
{
|
||||
// Check if the domain matches the regex
|
||||
if(regexec(®ex_clients[j], client_ip, 0, NULL, 0) == 0)
|
||||
@@ -516,7 +438,7 @@ int api_stats_top_clients(struct ftl_conn *api)
|
||||
if(N_regex_clients > 0)
|
||||
{
|
||||
// Free individual regexes
|
||||
for(int i = 0; i < N_regex_clients; i++)
|
||||
for(unsigned int i = 0; i < N_regex_clients; i++)
|
||||
regfree(®ex_clients[i]);
|
||||
|
||||
// Free array of regex pointers
|
||||
|
||||
Reference in New Issue
Block a user