Improve error reporting for missing/incorrect sets of payload/URI arguments

Signed-off-by: DL6ER <dl6er@dl6er.de>
This commit is contained in:
DL6ER
2021-01-25 20:55:52 +01:00
parent 54cd12e895
commit 73b3d680ca
6 changed files with 254 additions and 191 deletions
+172 -104
View File
@@ -20,15 +20,15 @@
static int api_list_read(struct ftl_conn *api,
const int code,
const enum gravity_list_type listtype,
const char *argument)
const char *item)
{
const char *sql_msg = NULL;
if(!gravityDB_readTable(listtype, argument, &sql_msg))
if(!gravityDB_readTable(listtype, item, &sql_msg))
{
cJSON *json = JSON_NEW_OBJ();
// Add argument (may be NULL = not available)
JSON_OBJ_REF_STR(json, "argument", argument);
// Add item (may be NULL = not available)
JSON_OBJ_REF_STR(json, "item", item);
// Add SQL message (may be NULL = not available)
if (sql_msg != NULL) {
@@ -43,100 +43,100 @@ static int api_list_read(struct ftl_conn *api,
json);
}
tablerow row;
cJSON *items = JSON_NEW_ARRAY();
while(gravityDB_readTableGetRow(&row, &sql_msg))
tablerow table;
cJSON *rows = JSON_NEW_ARRAY();
while(gravityDB_readTableGetRow(&table, &sql_msg))
{
cJSON *item = JSON_NEW_OBJ();
cJSON *row = JSON_NEW_OBJ();
// Special fields
if(listtype == GRAVITY_GROUPS)
{
JSON_OBJ_COPY_STR(item, "name", row.name);
if(row.description != NULL) {
JSON_OBJ_COPY_STR(item, "description", row.description);
JSON_OBJ_COPY_STR(row, "name", table.name);
if(table.comment != NULL) {
JSON_OBJ_COPY_STR(row, "comment", table.comment);
} else {
JSON_OBJ_ADD_NULL(item, "description");
JSON_OBJ_ADD_NULL(row, "comment");
}
}
else if(listtype == GRAVITY_ADLISTS)
{
JSON_OBJ_COPY_STR(item, "address", row.address);
if(row.comment != NULL) {
JSON_OBJ_COPY_STR(item, "comment", row.comment);
JSON_OBJ_COPY_STR(row, "address", table.address);
if(table.comment != NULL) {
JSON_OBJ_COPY_STR(row, "comment", table.comment);
} else {
JSON_OBJ_ADD_NULL(item, "comment");
JSON_OBJ_ADD_NULL(row, "comment");
}
}
else if(listtype == GRAVITY_CLIENTS)
{
if(row.ip != NULL)
if(table.client != NULL)
{
JSON_OBJ_COPY_STR(item, "client", row.ip);
char *name = getNameFromIP(row.ip);
JSON_OBJ_COPY_STR(row, "client", table.client);
char *name = getNameFromIP(table.client);
if(name != NULL)
{
JSON_OBJ_COPY_STR(item, "name", name);
JSON_OBJ_COPY_STR(row, "name", name);
free(name);
}
else
{
JSON_OBJ_ADD_NULL(item, "name");
JSON_OBJ_ADD_NULL(row, "name");
}
}
else
{
JSON_OBJ_ADD_NULL(item, "ip");
JSON_OBJ_ADD_NULL(item, "name");
JSON_OBJ_ADD_NULL(row, "ip");
JSON_OBJ_ADD_NULL(row, "name");
}
if(row.comment != NULL) {
JSON_OBJ_COPY_STR(item, "comment", row.comment);
if(table.comment != NULL) {
JSON_OBJ_COPY_STR(row, "comment", table.comment);
} else {
JSON_OBJ_ADD_NULL(item, "comment");
JSON_OBJ_ADD_NULL(row, "comment");
}
}
else // domainlists
{
JSON_OBJ_COPY_STR(item, "domain", row.domain);
JSON_OBJ_REF_STR(item, "type", row.type);
JSON_OBJ_REF_STR(item, "kind", row.kind);
if(row.comment != NULL) {
JSON_OBJ_COPY_STR(item, "comment", row.comment);
JSON_OBJ_COPY_STR(row, "domain", table.domain);
JSON_OBJ_REF_STR(row, "type", table.type);
JSON_OBJ_REF_STR(row, "kind", table.kind);
if(table.comment != NULL) {
JSON_OBJ_COPY_STR(row, "comment", table.comment);
} else {
JSON_OBJ_ADD_NULL(item, "comment");
JSON_OBJ_ADD_NULL(row, "comment");
}
}
if(row.group_ids != NULL) {
if(table.group_ids != NULL) {
// Black magic at work here: We build a JSON array from
// the group_concat result delivered from the database,
// parse it as valid array and append it as item to the
// parse it as valid array and append it as row to the
// data
logg("row.group_ids = %p \"%s\"", row.group_ids, row.group_ids);
char group_ids_str[strlen(row.group_ids)+3u];
logg("table.group_ids = %p \"%s\"", table.group_ids, table.group_ids);
char group_ids_str[strlen(table.group_ids)+3u];
group_ids_str[0] = '[';
strcpy(group_ids_str+1u , row.group_ids);
strcpy(group_ids_str+1u , table.group_ids);
group_ids_str[sizeof(group_ids_str)-2u] = ']';
group_ids_str[sizeof(group_ids_str)-1u] = '\0';
cJSON * group_ids = cJSON_Parse(group_ids_str);
JSON_OBJ_ADD_ITEM(item, "groups", group_ids);
JSON_OBJ_ADD_ITEM(row, "groups", group_ids);
} else {
// Empty group set
cJSON *group_ids = JSON_NEW_ARRAY();
JSON_OBJ_ADD_ITEM(item, "groups", group_ids);
JSON_OBJ_ADD_ITEM(row, "groups", group_ids);
}
// Clients don't have the enabled property
if(listtype != GRAVITY_CLIENTS)
JSON_OBJ_ADD_BOOL(item, "enabled", row.enabled);
JSON_OBJ_ADD_BOOL(row, "enabled", table.enabled);
// Add read-only database parameters
JSON_OBJ_ADD_NUMBER(item, "id", row.id);
JSON_OBJ_ADD_NUMBER(item, "date_added", row.date_added);
JSON_OBJ_ADD_NUMBER(item, "date_modified", row.date_modified);
JSON_OBJ_ADD_NUMBER(row, "id", table.id);
JSON_OBJ_ADD_NUMBER(row, "date_added", table.date_added);
JSON_OBJ_ADD_NUMBER(row, "date_modified", table.date_modified);
JSON_ARRAY_ADD_ITEM(items, item);
JSON_ARRAY_ADD_ITEM(rows, row);
}
gravityDB_readTableFinalize();
@@ -153,16 +153,16 @@ static int api_list_read(struct ftl_conn *api,
objname = "clients";
else // domainlists
objname = "domains";
JSON_OBJ_ADD_ITEM(json, objname, items);
JSON_OBJ_ADD_ITEM(json, objname, rows);
JSON_SEND_OBJECT_CODE(json, code);
}
else
{
JSON_DELETE(items);
JSON_DELETE(rows);
cJSON *json = JSON_NEW_OBJ();
// Add argument (may be NULL = not available)
JSON_OBJ_REF_STR(json, "argument", argument);
// Add item (may be NULL = not available)
JSON_OBJ_REF_STR(json, "item", item);
// Add SQL message (may be NULL = not available)
if (sql_msg != NULL) {
@@ -180,14 +180,11 @@ static int api_list_read(struct ftl_conn *api,
static int api_list_write(struct ftl_conn *api,
const enum gravity_list_type listtype,
const char *argument,
const char *item,
char payload[MAX_PAYLOAD_BYTES])
{
tablerow row = { 0 };
// Set argument
row.argument = argument;
// Check if valid JSON payload is available
if (api->payload.json == NULL) {
return send_json_error(api, 400,
@@ -196,23 +193,97 @@ static int api_list_write(struct ftl_conn *api,
NULL);
}
// Clients don't have the enabled property
cJSON *json_enabled = cJSON_GetObjectItemCaseSensitive(api->payload.json, "enabled");
if (cJSON_IsBool(json_enabled))
row.enabled = cJSON_IsTrue(json_enabled);
else
row.enabled = true; // Default value
cJSON *json_item = cJSON_GetObjectItemCaseSensitive(api->payload.json, "item");
if(cJSON_IsString(json_item) && strlen(json_item->valuestring) > 0)
row.argument = json_item->valuestring;
else if (api->method != HTTP_PUT) // PUT uses the URI argument
if(api->method == HTTP_POST)
{
return send_json_error(api, 400,
"bad_request",
"No \"item\" string in body data",
NULL);
// Extract domain/name/client/address from payload whe using POST, all
// others specify it as URI-component
cJSON *json_domain, *json_name, *json_address, *json_client;
switch(listtype)
{
case GRAVITY_DOMAINLIST_ALLOW_EXACT:
case GRAVITY_DOMAINLIST_ALLOW_REGEX:
case GRAVITY_DOMAINLIST_DENY_EXACT:
case GRAVITY_DOMAINLIST_DENY_REGEX:
json_domain = cJSON_GetObjectItemCaseSensitive(api->payload.json, "domain");
if(cJSON_IsString(json_domain) && strlen(json_domain->valuestring) > 0)
{
row.item = json_domain->valuestring;
}
else
{
cJSON *uri = JSON_NEW_OBJ();
JSON_OBJ_REF_STR(uri, "path", api->action_path);
JSON_OBJ_REF_STR(uri, "item", item);
return send_json_error(api, 400,
"uri_error",
"Invalid request: No item \"domain\" in payload",
uri);
}
break;
case GRAVITY_GROUPS:
json_name = cJSON_GetObjectItemCaseSensitive(api->payload.json, "name");
if(cJSON_IsString(json_name) && strlen(json_name->valuestring) > 0)
row.item = json_name->valuestring;
else
{
cJSON *uri = JSON_NEW_OBJ();
JSON_OBJ_REF_STR(uri, "path", api->action_path);
JSON_OBJ_REF_STR(uri, "item", item);
return send_json_error(api, 400,
"uri_error",
"Invalid request: No item \"name\" in payload",
uri);
}
break;
case GRAVITY_CLIENTS:
json_client = cJSON_GetObjectItemCaseSensitive(api->payload.json, "client");
if(cJSON_IsString(json_client) && strlen(json_client->valuestring) > 0)
row.item = json_client->valuestring;
else
{
cJSON *uri = JSON_NEW_OBJ();
JSON_OBJ_REF_STR(uri, "path", api->action_path);
JSON_OBJ_REF_STR(uri, "item", item);
return send_json_error(api, 400,
"uri_error",
"Invalid request: No item \"client\" in payload",
uri);
}
break;
case GRAVITY_ADLISTS:
json_address = cJSON_GetObjectItemCaseSensitive(api->payload.json, "address");
if(cJSON_IsString(json_address) && strlen(json_address->valuestring) > 0)
row.item = json_address->valuestring;
else
{
cJSON *uri = JSON_NEW_OBJ();
JSON_OBJ_REF_STR(uri, "path", api->action_path);
JSON_OBJ_REF_STR(uri, "item", item);
return send_json_error(api, 400,
"uri_error",
"Invalid request: No item \"address\" in payload",
uri);
}
break;
// Aggregate types are not handled by this routine
case GRAVITY_DOMAINLIST_ALL_ALL:
case GRAVITY_DOMAINLIST_ALL_EXACT:
case GRAVITY_DOMAINLIST_ALL_REGEX:
case GRAVITY_DOMAINLIST_ALLOW_ALL:
case GRAVITY_DOMAINLIST_DENY_ALL:
return 500;
}
}
else
{
// PUT = Use URI item
row.item = item;
}
cJSON *json_comment = cJSON_GetObjectItemCaseSensitive(api->payload.json, "comment");
if(cJSON_IsString(json_comment) && strlen(json_comment->valuestring) > 0)
@@ -220,12 +291,6 @@ static int api_list_write(struct ftl_conn *api,
else
row.comment = NULL; // Default value
cJSON *json_description = cJSON_GetObjectItemCaseSensitive(api->payload.json, "description");
if(cJSON_IsString(json_description) && strlen(json_description->valuestring) > 0)
row.description = json_description->valuestring;
else
row.description = NULL; // Default value
cJSON *json_oldtype = cJSON_GetObjectItemCaseSensitive(api->payload.json, "oldtype");
if(cJSON_IsString(json_oldtype) && strlen(json_oldtype->valuestring) > 0)
row.oldtype = json_oldtype->valuestring;
@@ -238,13 +303,19 @@ static int api_list_write(struct ftl_conn *api,
else
row.oldkind = NULL; // Default value
cJSON *json_enabled = cJSON_GetObjectItemCaseSensitive(api->payload.json, "enabled");
if (cJSON_IsBool(json_enabled))
row.enabled = cJSON_IsTrue(json_enabled);
else
row.enabled = true; // Default value
bool okay = true;
char *regex_msg = NULL;
if(listtype == GRAVITY_DOMAINLIST_ALLOW_REGEX || listtype == GRAVITY_DOMAINLIST_DENY_REGEX)
{
// Test validity of this regex
regexData regex = { 0 };
okay = compile_regex(row.argument, &regex, &regex_msg);
okay = compile_regex(row.domain, &regex, &regex_msg);
}
// Try to add item to table
@@ -271,12 +342,10 @@ static int api_list_write(struct ftl_conn *api,
{
// Error adding item, prepare error object
cJSON *json = JSON_NEW_OBJ();
JSON_OBJ_REF_STR(json, "item", row.argument);
JSON_OBJ_REF_STR(json, "item", item);
JSON_OBJ_ADD_BOOL(json, "enabled", row.enabled);
if(row.comment != NULL)
JSON_OBJ_REF_STR(json, "comment", row.comment);
if(row.description != NULL)
JSON_OBJ_REF_STR(json, "description", row.description);
if(row.name != NULL)
JSON_OBJ_REF_STR(json, "name", row.name);
if(row.oldtype != NULL)
@@ -317,16 +386,16 @@ static int api_list_write(struct ftl_conn *api,
if(api->method == HTTP_PUT)
response_code = 200; // 200 - OK
// Send GET style reply
return api_list_read(api, response_code, listtype, row.argument);
return api_list_read(api, response_code, listtype, row.item);
}
static int api_list_remove(struct ftl_conn *api,
const enum gravity_list_type listtype,
const char *argument)
const char *item)
{
cJSON *json = JSON_NEW_OBJ();
const char *sql_msg = NULL;
if(gravityDB_delFromTable(listtype, argument, &sql_msg))
if(gravityDB_delFromTable(listtype, item, &sql_msg))
{
// Inform the resolver that it needs to reload the domainlists
set_event(RELOAD_GRAVITY);
@@ -336,8 +405,8 @@ static int api_list_remove(struct ftl_conn *api,
}
else
{
// Add argument
JSON_OBJ_REF_STR(json, "argument", argument);
// Add item
JSON_OBJ_REF_STR(json, "item", item);
// Add SQL message (may be NULL = not available)
if (sql_msg != NULL) {
@@ -365,59 +434,58 @@ int api_list(struct ftl_conn *api)
enum gravity_list_type listtype;
bool can_modify = false;
const char *argument = NULL;
if((argument = startsWith("/api/groups", api)) != NULL)
if((api->item = startsWith("/api/groups", api)) != NULL)
{
listtype = GRAVITY_GROUPS;
can_modify = true;
}
else if((argument = startsWith("/api/lists", api)) != NULL)
else if((api->item = startsWith("/api/lists", api)) != NULL)
{
listtype = GRAVITY_ADLISTS;
can_modify = true;
}
else if((argument = startsWith("/api/clients", api)) != NULL)
else if((api->item = startsWith("/api/clients", api)) != NULL)
{
listtype = GRAVITY_CLIENTS;
can_modify = true;
}
else if((argument = startsWith("/api/domains/allow/exact", api)) != NULL)
else if((api->item = startsWith("/api/domains/allow/exact", api)) != NULL)
{
listtype = GRAVITY_DOMAINLIST_ALLOW_EXACT;
can_modify = true;
}
else if((argument = startsWith("/api/domains/allow/regex", api)) != NULL)
else if((api->item = startsWith("/api/domains/allow/regex", api)) != NULL)
{
listtype = GRAVITY_DOMAINLIST_ALLOW_REGEX;
can_modify = true;
}
else if((argument = startsWith("/api/domains/allow", api)) != NULL)
else if((api->item = startsWith("/api/domains/allow", api)) != NULL)
{
listtype = GRAVITY_DOMAINLIST_ALLOW_ALL;
}
else if((argument = startsWith("/api/domains/deny/exact", api)) != NULL)
else if((api->item = startsWith("/api/domains/deny/exact", api)) != NULL)
{
listtype = GRAVITY_DOMAINLIST_DENY_EXACT;
can_modify = true;
}
else if((argument = startsWith("/api/domains/deny/regex", api)) != NULL)
else if((api->item = startsWith("/api/domains/deny/regex", api)) != NULL)
{
listtype = GRAVITY_DOMAINLIST_DENY_REGEX;
can_modify = true;
}
else if((argument = startsWith("/api/domains/deny", api)) != NULL)
else if((api->item = startsWith("/api/domains/deny", api)) != NULL)
{
listtype = GRAVITY_DOMAINLIST_DENY_ALL;
}
else if((argument = startsWith("/api/domains/exact", api)) != NULL)
else if((api->item = startsWith("/api/domains/exact", api)) != NULL)
{
listtype = GRAVITY_DOMAINLIST_ALL_EXACT;
}
else if((argument = startsWith("/api/domains/regex", api)) != NULL)
else if((api->item = startsWith("/api/domains/regex", api)) != NULL)
{
listtype = GRAVITY_DOMAINLIST_ALL_REGEX;
}
else if((argument = startsWith("/api/domains", api)) != NULL)
else if((api->item = startsWith("/api/domains", api)) != NULL)
{
listtype = GRAVITY_DOMAINLIST_ALL_ALL;
}
@@ -434,12 +502,12 @@ int api_list(struct ftl_conn *api)
if(api->method == HTTP_GET)
{
// Read list item identified by URI (or read them all)
return api_list_read(api, 200, listtype, argument);
return api_list_read(api, 200, listtype, api->item);
}
else if(can_modify && api->method == HTTP_PUT)
{
// Add/update item identified by URI
if(strlen(argument) == 0)
if(api->item != NULL && strlen(api->item) == 0)
{
cJSON *uri = JSON_NEW_OBJ();
if(api->action_path != NULL)
@@ -450,19 +518,19 @@ int api_list(struct ftl_conn *api)
{
JSON_OBJ_ADD_NULL(uri, "path");
}
JSON_OBJ_REF_STR(uri, "item", argument);
JSON_OBJ_REF_STR(uri, "item", api->item);
return send_json_error(api, 400,
"uri_error",
"Invalid request: Specify item in URI",
uri);
}
else
return api_list_write(api, listtype, argument, payload);
return api_list_write(api, listtype, api->item, payload);
}
else if(can_modify && api->method == HTTP_POST)
{
// Add item to list identified by payload
if(strlen(argument) != 0)
if(api->item != NULL && strlen(api->item) != 0)
{
cJSON *uri = JSON_NEW_OBJ();
if(api->action_path != NULL)
@@ -473,19 +541,19 @@ int api_list(struct ftl_conn *api)
{
JSON_OBJ_ADD_NULL(uri, "path");
}
JSON_OBJ_REF_STR(uri, "item", argument);
JSON_OBJ_REF_STR(uri, "item", api->item);
return send_json_error(api, 400,
"uri_error",
"Invalid request: Specify item in payload, not as URI parameter",
uri);
}
else
return api_list_write(api, listtype, argument, payload);
return api_list_write(api, listtype, api->item, payload);
}
else if(can_modify && api->method == HTTP_DELETE)
{
// Delete item from list
return api_list_remove(api, listtype, argument);
return api_list_remove(api, listtype, api->item);
}
else if(!can_modify)
{
@@ -499,7 +567,7 @@ int api_list(struct ftl_conn *api)
{
JSON_OBJ_ADD_NULL(uri, "path");
}
JSON_OBJ_REF_STR(uri, "item", argument);
JSON_OBJ_REF_STR(uri, "item", api->item);
return send_json_error(api, 400,
"uri_error",
"Invalid request: Specify list to modify more precisely",
+1
View File
@@ -30,6 +30,7 @@ int api_handler(struct mg_connection *conn, void *ignored)
mg_get_request_info(conn),
http_method(conn),
NULL,
NULL,
{ 0 }
};
read_and_parse_payload(&api);
+74 -84
View File
@@ -1388,53 +1388,58 @@ bool gravityDB_addToTable(const enum gravity_list_type listtype, tablerow *row,
return false;
}
int type = -1;
switch (listtype)
{
case GRAVITY_DOMAINLIST_ALLOW_EXACT:
type = 0;
row->type_int = 0;
break;
case GRAVITY_DOMAINLIST_DENY_EXACT:
type = 1;
row->type_int = 1;
break;
case GRAVITY_DOMAINLIST_ALLOW_REGEX:
type = 2;
row->type_int = 2;
break;
case GRAVITY_DOMAINLIST_DENY_REGEX:
type = 3;
row->type_int = 3;
break;
// Nothing to be done for these tables
case GRAVITY_GROUPS:
case GRAVITY_ADLISTS:
case GRAVITY_CLIENTS:
// No type required for these tables
break;
// Aggregate types cannot be handled by this routine
// Aggregate types are not handled by this routine
case GRAVITY_DOMAINLIST_ALLOW_ALL:
case GRAVITY_DOMAINLIST_DENY_ALL:
case GRAVITY_DOMAINLIST_ALL_EXACT:
case GRAVITY_DOMAINLIST_ALL_REGEX:
case GRAVITY_DOMAINLIST_ALL_ALL:
default:
return false;
}
row->type_int = type;
// Prepare SQLite statement
sqlite3_stmt* stmt = NULL;
const char *querystr;
if(method == HTTP_POST) // Create NEW entry, error if existing
{
// The item is the argument for all POST requests
// The item is the item for all POST requests
if(listtype == GRAVITY_GROUPS)
querystr = "INSERT INTO \"group\" (name,enabled,description) VALUES (:argument,:enabled,:description);";
{
querystr = "INSERT INTO \"group\" (name,enabled,description) VALUES (:item,:enabled,:description);";
}
else if(listtype == GRAVITY_ADLISTS)
querystr = "INSERT INTO adlist (address,enabled,comment) VALUES (:argument,:enabled,:comment);";
{
querystr = "INSERT INTO adlist (address,enabled,comment) VALUES (:item,:enabled,:comment);";
}
else if(listtype == GRAVITY_CLIENTS)
querystr = "INSERT INTO client (ip,comment) VALUES (:argument,:comment);";
else // domainlist
querystr = "INSERT INTO domainlist (domain,type,enabled,comment) VALUES (:argument,:type,:enabled,:comment);";
{
querystr = "INSERT INTO client (ip,comment) VALUES (:item,:comment);";
}
else // domainlis
{
querystr = "INSERT INTO domainlist (domain,type,enabled,comment) VALUES (:item,:type,:enabled,:comment);";
}
}
else
{ // Create new or replace existing entry, no error if existing
@@ -1442,24 +1447,24 @@ bool gravityDB_addToTable(const enum gravity_list_type listtype, tablerow *row,
// contraints (REPLACE recreates (= new ID) entries instead of updating them)
if(listtype == GRAVITY_GROUPS)
querystr = "REPLACE INTO \"group\" (name,enabled,description,id,date_added) "
"VALUES (:argument,:enabled,:description,"
"(SELECT id FROM \"group\" WHERE name = :argument),"
"(SELECT date_added FROM \"group\" WHERE name = :argument));";
"VALUES (:item,:enabled,:description,"
"(SELECT id FROM \"group\" WHERE name = :item),"
"(SELECT date_added FROM \"group\" WHERE name = :item));";
else if(listtype == GRAVITY_ADLISTS)
querystr = "REPLACE INTO adlist (address,enabled,comment,id,date_added) "
"VALUES (:argument,:enabled,:comment,"
"(SELECT id FROM adlist WHERE address = :argument),"
"(SELECT date_added FROM adlist WHERE address = :argument));";
"VALUES (:item,:enabled,:comment,"
"(SELECT id FROM adlist WHERE address = :item),"
"(SELECT date_added FROM adlist WHERE address = :item));";
else if(listtype == GRAVITY_CLIENTS)
querystr = "REPLACE INTO client (ip,comment,id,date_added) "
"VALUES (:argument,:comment,"
"(SELECT id FROM client WHERE ip = :argument),"
"(SELECT date_added FROM client WHERE ip = :argument));";
"VALUES (:item,:comment,"
"(SELECT id FROM client WHERE ip = :item),"
"(SELECT date_added FROM client WHERE ip = :item));";
else // domainlist
querystr = "REPLACE INTO domainlist (domain,type,enabled,comment,id,date_added) "
"VALUES (:argument,:type,:enabled,:comment,"
"(SELECT id FROM domainlist WHERE domain = :argument AND type = :oldtype),"
"(SELECT date_added FROM domainlist WHERE domain = :argument AND type = :oldtype));";
"VALUES (:item,:type,:enabled,:comment,"
"(SELECT id FROM domainlist WHERE domain = :item AND type = :oldtype),"
"(SELECT date_added FROM domainlist WHERE domain = :item AND type = :oldtype));";
}
int rc = sqlite3_prepare_v2(gravity_db, querystr, -1, &stmt, NULL);
@@ -1467,17 +1472,17 @@ bool gravityDB_addToTable(const enum gravity_list_type listtype, tablerow *row,
{
*message = sqlite3_errmsg(gravity_db);
logg("gravityDB_addToTable(%d, %s) - SQL error prepare (%i): %s",
type, row->domain, rc, *message);
row->type_int, row->domain, rc, *message);
return false;
}
// Bind argument to prepared statement (if requested)
int idx = sqlite3_bind_parameter_index(stmt, ":argument");
if(idx > 0 && (rc = sqlite3_bind_text(stmt, idx, row->argument, -1, SQLITE_STATIC)) != SQLITE_OK)
// Bind item to prepared statement (if requested)
int idx = sqlite3_bind_parameter_index(stmt, ":item");
if(idx > 0 && (rc = sqlite3_bind_text(stmt, idx, row->item, -1, SQLITE_STATIC)) != SQLITE_OK)
{
*message = sqlite3_errmsg(gravity_db);
logg("gravityDB_addToTable(%d, %s): Failed to bind argument (error %d) - %s",
type, row->argument, rc, *message);
logg("gravityDB_addToTable(%d, %s): Failed to bind item (error %d) - %s",
row->type_int, row->item, rc, *message);
sqlite3_reset(stmt);
sqlite3_finalize(stmt);
return false;
@@ -1485,11 +1490,11 @@ bool gravityDB_addToTable(const enum gravity_list_type listtype, tablerow *row,
// Bind type to prepared statement (if requested)
idx = sqlite3_bind_parameter_index(stmt, ":type");
if(idx > 0 && (rc = sqlite3_bind_int(stmt, idx, type)) != SQLITE_OK)
if(idx > 0 && (rc = sqlite3_bind_int(stmt, idx, row->type_int)) != SQLITE_OK)
{
*message = sqlite3_errmsg(gravity_db);
logg("gravityDB_addToTable(%d, %s): Failed to bind type (error %d) - %s",
type, row->domain, rc, *message);
row->type_int, row->domain, rc, *message);
sqlite3_reset(stmt);
sqlite3_finalize(stmt);
return false;
@@ -1503,14 +1508,14 @@ bool gravityDB_addToTable(const enum gravity_list_type listtype, tablerow *row,
if(row->oldtype == NULL && row->oldkind == NULL)
{
// User didn't specify oldtype/oldkind, just replace without moving
oldtype = type;
oldtype = row->type_int;
}
else if(row->oldtype == NULL)
{
// Error, one is not meaningful without the other
*message = "Field oldtype missing from request";
logg("gravityDB_addToTable(%d, %s): Oldtype missing",
type, row->domain);
row->type_int, row->domain);
sqlite3_reset(stmt);
sqlite3_finalize(stmt);
return false;
@@ -1520,7 +1525,7 @@ bool gravityDB_addToTable(const enum gravity_list_type listtype, tablerow *row,
// Error, one is not meaningful without the other
*message = "Field oldkind missing from request";
logg("gravityDB_addToTable(%d, %s): Oldkind missing",
type, row->domain);
row->type_int, row->domain);
sqlite3_reset(stmt);
sqlite3_finalize(stmt);
return false;
@@ -1543,7 +1548,7 @@ bool gravityDB_addToTable(const enum gravity_list_type listtype, tablerow *row,
{
*message = "Cannot interpret oldtype/oldkind";
logg("gravityDB_addToTable(%d, %s): Failed to identify oldtype=\"%s\", oldkind=\"%s\"",
type, row->domain, row->oldtype, row->oldkind);
row->type_int, row->domain, row->oldtype, row->oldkind);
sqlite3_reset(stmt);
sqlite3_finalize(stmt);
return false;
@@ -1555,7 +1560,7 @@ bool gravityDB_addToTable(const enum gravity_list_type listtype, tablerow *row,
{
*message = sqlite3_errmsg(gravity_db);
logg("gravityDB_addToTable(%d, %s): Failed to bind oldtype (error %d) - %s",
type, row->domain, rc, *message);
row->type_int, row->domain, rc, *message);
sqlite3_reset(stmt);
sqlite3_finalize(stmt);
return false;
@@ -1568,7 +1573,7 @@ bool gravityDB_addToTable(const enum gravity_list_type listtype, tablerow *row,
{
*message = sqlite3_errmsg(gravity_db);
logg("gravityDB_addToTable(%d, %s): Failed to bind enabled (error %d) - %s",
type, row->domain, rc, *message);
row->type_int, row->domain, rc, *message);
sqlite3_reset(stmt);
sqlite3_finalize(stmt);
return false;
@@ -1580,19 +1585,7 @@ bool gravityDB_addToTable(const enum gravity_list_type listtype, tablerow *row,
{
*message = sqlite3_errmsg(gravity_db);
logg("gravityDB_addToTable(%d, %s): Failed to bind comment (error %d) - %s",
type, row->domain, rc, *message);
sqlite3_reset(stmt);
sqlite3_finalize(stmt);
return false;
}
// Bind description string to prepared statement (if requested)
idx = sqlite3_bind_parameter_index(stmt, ":description");
if(idx > 0 && (rc = sqlite3_bind_text(stmt, idx, row->description, -1, SQLITE_STATIC)) != SQLITE_OK)
{
*message = sqlite3_errmsg(gravity_db);
logg("gravityDB_addToTable(%d, %s): Failed to bind description (error %d) - %s",
type, row->domain, rc, *message);
row->type_int, row->domain, rc, *message);
sqlite3_reset(stmt);
sqlite3_finalize(stmt);
return false;
@@ -1799,7 +1792,7 @@ bool gravityDB_delFromTable(const enum gravity_list_type listtype, const char* a
}
static sqlite3_stmt* read_stmt = NULL;
bool gravityDB_readTable(const enum gravity_list_type listtype, const char *argument, const char **message)
bool gravityDB_readTable(const enum gravity_list_type listtype, const char *item, const char **message)
{
if(gravity_db == NULL)
{
@@ -1852,30 +1845,30 @@ bool gravityDB_readTable(const enum gravity_list_type listtype, const char *argu
const char *extra = "";
if(listtype == GRAVITY_GROUPS)
{
if(argument != NULL && argument[0] != '\0')
extra = " WHERE name = :argument;";
sprintf(querystr, "SELECT id,name,enabled,date_added,date_modified,description FROM \"group\"%s;", extra);
if(item != NULL && item[0] != '\0')
extra = " WHERE name = :item;";
sprintf(querystr, "SELECT id,name,enabled,date_added,date_modified,description AS comment FROM \"group\"%s;", extra);
}
else if(listtype == GRAVITY_ADLISTS)
{
if(argument != NULL && argument[0] != '\0')
extra = " WHERE address = :argument;";
if(item != NULL && item[0] != '\0')
extra = " WHERE address = :item;";
sprintf(querystr, "SELECT id,address,enabled,date_added,date_modified,comment,"
"(SELECT GROUP_CONCAT(group_id) FROM adlist_by_group g WHERE g.adlist_id = a.id) AS group_ids "
"FROM adlist a%s;", extra);
}
else if(listtype == GRAVITY_CLIENTS)
{
if(argument != NULL && argument[0] != '\0')
extra = " WHERE ip = :argument;";
sprintf(querystr, "SELECT id,ip,date_added,date_modified,comment,"
if(item != NULL && item[0] != '\0')
extra = " WHERE ip = :item;";
sprintf(querystr, "SELECT id,ip AS client,date_added,date_modified,comment,"
"(SELECT GROUP_CONCAT(group_id) FROM client_by_group g WHERE g.client_id = c.id) AS group_ids "
"FROM client c%s;", extra);
}
else // domainlist
{
if(argument != NULL && argument[0] != '\0')
extra = " AND domain = :argument;";
if(item != NULL && item[0] != '\0')
extra = " AND domain = :item;";
sprintf(querystr, "SELECT id,type,domain,enabled,date_added,date_modified,comment,"
"(SELECT GROUP_CONCAT(group_id) FROM domainlist_by_group g WHERE g.domainlist_id = d.id) AS group_ids "
"FROM domainlist d WHERE d.type IN (%s)%s;", type, extra);
@@ -1890,13 +1883,13 @@ bool gravityDB_readTable(const enum gravity_list_type listtype, const char *argu
return false;
}
// Bind argument to prepared statement (if requested)
int idx = sqlite3_bind_parameter_index(read_stmt, ":argument");
if(idx > 0 && (rc = sqlite3_bind_text(read_stmt, idx, argument, -1, SQLITE_STATIC)) != SQLITE_OK)
// Bind item to prepared statement (if requested)
int idx = sqlite3_bind_parameter_index(read_stmt, ":item");
if(idx > 0 && (rc = sqlite3_bind_text(read_stmt, idx, item, -1, SQLITE_STATIC)) != SQLITE_OK)
{
*message = sqlite3_errmsg(gravity_db);
logg("gravityDB_readTable(%d => (%s), %s): Failed to bind argument (error %d) - %s",
listtype, type, argument, rc, *message);
logg("gravityDB_readTable(%d => (%s), %s): Failed to bind item (error %d) - %s",
listtype, type, item, rc, *message);
sqlite3_reset(read_stmt);
sqlite3_finalize(read_stmt);
return false;
@@ -1906,7 +1899,7 @@ bool gravityDB_readTable(const enum gravity_list_type listtype, const char *argu
if(config.debug & DEBUG_API)
{
logg("SQL: %s", querystr);
logg(" :argument = \"%s\"", argument);
logg(" :item = \"%s\"", item);
}
return true;
@@ -1976,11 +1969,8 @@ bool gravityDB_readTableGetRow(tablerow *row, const char **message)
else if(strcasecmp(cname, "name") == 0)
row->name = (char*)sqlite3_column_text(read_stmt, c);
else if(strcasecmp(cname, "description") == 0)
row->description = (char*)sqlite3_column_text(read_stmt, c);
else if(strcasecmp(cname, "ip") == 0)
row->ip = (char*)sqlite3_column_text(read_stmt, c);
else if(strcasecmp(cname, "client") == 0)
row->client = (char*)sqlite3_column_text(read_stmt, c);
else
logg("Internal API error: Encountered unknown column %s", cname);
@@ -2025,19 +2015,19 @@ bool gravityDB_edit_groups(const enum gravity_list_type listtype, cJSON *groups,
return false;
else if(listtype == GRAVITY_CLIENTS)
{
get_querystr = "SELECT id FROM client WHERE ip = :argument";
get_querystr = "SELECT id FROM client WHERE ip = :item";
del_querystr = "DELETE FROM client_by_group WHERE client_id = :id;";
add_querystr = "INSERT INTO client_by_group (client_id,group_id) VALUES (:id,:gid);";
}
else if(listtype == GRAVITY_ADLISTS)
{
get_querystr = "SELECT id FROM adlist WHERE address = :argument";
get_querystr = "SELECT id FROM adlist WHERE address = :item";
del_querystr = "DELETE FROM adlist_by_group WHERE adlist_id = :id;";
add_querystr = "INSERT INTO adlist_by_group (adlist_id,group_id) VALUES (:id,:gid);";
}
else // domainlist
{
get_querystr = "SELECT id FROM domainlist WHERE domain = :argument AND type = :type";
get_querystr = "SELECT id FROM domainlist WHERE domain = :item AND type = :type";
del_querystr = "DELETE FROM domainlist_by_group WHERE domainlist_id = :id;";
add_querystr = "INSERT INTO domainlist_by_group (domainlist_id,group_id) VALUES (:id,:gid);";
}
@@ -2053,12 +2043,12 @@ bool gravityDB_edit_groups(const enum gravity_list_type listtype, cJSON *groups,
return false;
}
// Bind argument string to prepared statement (if requested)
int idx = sqlite3_bind_parameter_index(stmt, ":argument");
if(idx > 0 && (rc = sqlite3_bind_text(stmt, idx, row->argument, -1, SQLITE_STATIC)) != SQLITE_OK)
// Bind item string to prepared statement (if requested)
int idx = sqlite3_bind_parameter_index(stmt, ":item");
if(idx > 0 && (rc = sqlite3_bind_text(stmt, idx, row->item, -1, SQLITE_STATIC)) != SQLITE_OK)
{
*message = sqlite3_errmsg(gravity_db);
logg("gravityDB_edit_groups(%d): Failed to bind argument SELECT (error %d) - %s",
logg("gravityDB_edit_groups(%d): Failed to bind item SELECT (error %d) - %s",
listtype, rc, *message);
sqlite3_reset(stmt);
sqlite3_finalize(stmt);
@@ -2095,7 +2085,7 @@ bool gravityDB_edit_groups(const enum gravity_list_type listtype, cJSON *groups,
if(config.debug & DEBUG_API)
{
logg("SQL: %s", get_querystr);
logg(" :argument = \"%s\"", row->argument);
logg(" :item = \"%s\"", row->item);
logg(" :type = \"%d\"", row->type_int);
}
+2 -3
View File
@@ -30,9 +30,8 @@ typedef struct {
const char *oldkind;
const char *comment;
const char *group_ids;
const char *description;
const char *argument;
const char *ip;
const char *client;
const char *item;
long id;
time_t date_added;
time_t date_modified;
+4
View File
@@ -146,6 +146,8 @@ const char* __attribute__((pure)) startsWith(const char *path, struct ftl_conn *
if(api->request->local_uri[strlen(path)] == '/')
{
// Path match with argument after ".../"
if(api->action_path != NULL)
free(api->action_path);
api->action_path = strdup(api->request->local_uri);
api->action_path[strlen(path)] = '\0';
return api->request->local_uri + strlen(path) + 1u;
@@ -153,6 +155,8 @@ const char* __attribute__((pure)) startsWith(const char *path, struct ftl_conn *
else if(strlen(path) == strlen(api->request->local_uri))
{
// Path match directly, no argument
if(api->action_path != NULL)
free(api->action_path);
api->action_path = strdup(api->request->local_uri);
return "";
}
+1
View File
@@ -25,6 +25,7 @@ struct ftl_conn {
const struct mg_request_info *request;
const enum http_method method;
char *action_path;
const char *item;
struct {
bool avail :1;
char raw[MAX_PAYLOAD_BYTES];