diff --git a/src/api/list.c b/src/api/list.c index 8845c5d6..60d36842 100644 --- a/src/api/list.c +++ b/src/api/list.c @@ -72,7 +72,7 @@ static int api_list_read(struct ftl_conn *api, { if(row.ip != NULL) { - JSON_OBJ_COPY_STR(item, "ip", row.ip); + JSON_OBJ_COPY_STR(item, "client", row.ip); char *name = getNameFromIP(row.ip); if(name != NULL) { @@ -100,6 +100,7 @@ static int api_list_read(struct ftl_conn *api, { 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); } else { @@ -130,11 +131,10 @@ static int api_list_read(struct ftl_conn *api, if(listtype != GRAVITY_CLIENTS) JSON_OBJ_ADD_BOOL(item, "enabled", row.enabled); - cJSON *database = JSON_NEW_OBJ(); - JSON_OBJ_ADD_NUMBER(database, "id", row.id); - JSON_OBJ_ADD_NUMBER(database, "date_added", row.date_added); - JSON_OBJ_ADD_NUMBER(database, "date_modified", row.date_modified); - JSON_OBJ_ADD_ITEM(item, "database", database); + // 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_ARRAY_ADD_ITEM(items, item); } @@ -188,14 +188,6 @@ static int api_list_write(struct ftl_conn *api, // Set argument row.argument = argument; - // Check argument is not empty - if (api->method == HTTP_PUT && strlen(argument) < 1) { - return send_json_error(api, 400, - "bad_request", - "Missing argument, check URI", - NULL); - } - // Check if valid JSON payload is available if (api->payload.json == NULL) { return send_json_error(api, 400, @@ -240,13 +232,19 @@ static int api_list_write(struct ftl_conn *api, else row.oldtype = NULL; // Default value + cJSON *json_oldkind = cJSON_GetObjectItemCaseSensitive(api->payload.json, "oldkind"); + if(cJSON_IsString(json_oldkind) && strlen(json_oldkind->valuestring) > 0) + row.oldkind = json_oldkind->valuestring; + else + row.oldkind = NULL; // 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(argument, ®ex, ®ex_msg); + okay = compile_regex(row.argument, ®ex, ®ex_msg); } // Try to add item to table @@ -292,18 +290,22 @@ static int api_list_write(struct ftl_conn *api, } // Add regex error (may not be available) + const char *errortype = "database_error"; + const char *errormsg = "Could not add to gravity database"; if (regex_msg != NULL) { JSON_OBJ_COPY_STR(json, "regex_msg", regex_msg); free(regex_msg); regex_msg = NULL; + errortype = "regex_error"; + errormsg = "Regex validation failed"; } else { JSON_OBJ_ADD_NULL(json, "regex_msg"); } // Send error reply return send_json_error(api, 400, // 400 Bad Request - "database_error", - "Could not add to gravity database", + errortype, + errormsg, json); } // else: everything is okay @@ -450,7 +452,7 @@ int api_list(struct ftl_conn *api) } JSON_OBJ_REF_STR(uri, "item", argument); return send_json_error(api, 400, - "bad_request", + "uri_error", "Invalid request: Specify item in URI", uri); } @@ -473,7 +475,7 @@ int api_list(struct ftl_conn *api) } JSON_OBJ_REF_STR(uri, "item", argument); return send_json_error(api, 400, - "bad_request", + "uri_error", "Invalid request: Specify item in payload, not as URI parameter", uri); } @@ -498,12 +500,10 @@ int api_list(struct ftl_conn *api) JSON_OBJ_ADD_NULL(uri, "path"); } JSON_OBJ_REF_STR(uri, "item", argument); - cJSON *data = JSON_NEW_OBJ(); - JSON_OBJ_ADD_ITEM(data, "uri", uri); return send_json_error(api, 400, - "bad_request", + "uri_error", "Invalid request: Specify list to modify more precisely", - data); + uri); } else { diff --git a/src/database/gravity-db.c b/src/database/gravity-db.c index c7ee2c4c..23afcc70 100644 --- a/src/database/gravity-db.c +++ b/src/database/gravity-db.c @@ -1458,8 +1458,8 @@ bool gravityDB_addToTable(const enum gravity_list_type listtype, tablerow *row, 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));"; + "(SELECT id FROM domainlist WHERE domain = :argument AND type = :oldtype)," + "(SELECT date_added FROM domainlist WHERE domain = :argument AND type = :oldtype));"; } int rc = sqlite3_prepare_v2(gravity_db, querystr, -1, &stmt, NULL); @@ -1499,38 +1499,63 @@ bool gravityDB_addToTable(const enum gravity_list_type listtype, tablerow *row, idx = sqlite3_bind_parameter_index(stmt, ":oldtype"); if(idx > 0) { - if(row->oldtype == NULL) + int oldtype = -1; + if(row->oldtype == NULL && row->oldkind == NULL) { - *message = "Field oldtype missing from request."; + // User didn't specify oldtype/oldkind, just replace without moving + oldtype = type; + } + 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); sqlite3_reset(stmt); sqlite3_finalize(stmt); return false; } - int oldtype = -1; - if(strcasecmp("allow/exact", row->oldtype) == 0) - oldtype = 0; - else if(strcasecmp("deny/exact", row->oldtype) == 0) - oldtype = 1; - else if(strcasecmp("allow/regex", row->oldtype) == 0) - oldtype = 2; - else if(strcasecmp("deny/regex", row->oldtype) == 0) - oldtype = 3; - else + else if(row->oldkind == NULL) { - *message = "Cannot interpret oldtype field."; - logg("gravityDB_addToTable(%d, %s): Failed to identify oldtype \"%s\"", - type, row->domain, row->oldtype); + // Error, one is not meaningful without the other + *message = "Field oldkind missing from request"; + logg("gravityDB_addToTable(%d, %s): Oldkind missing", + type, row->domain); sqlite3_reset(stmt); sqlite3_finalize(stmt); return false; } + else + { + if(strcasecmp("allow", row->oldtype) == 0 && + strcasecmp("exact", row->oldkind) == 0) + oldtype = 0; + else if(strcasecmp("deny", row->oldtype) == 0 && + strcasecmp("exact", row->oldkind) == 0) + oldtype = 1; + else if(strcasecmp("allow", row->oldtype) == 0 && + strcasecmp("regex", row->oldkind) == 0) + oldtype = 2; + else if(strcasecmp("deny", row->oldtype) == 0 && + strcasecmp("regex", row->oldkind) == 0) + oldtype = 3; + else + { + *message = "Cannot interpret oldtype/oldkind"; + logg("gravityDB_addToTable(%d, %s): Failed to identify oldtype=\"%s\", oldkind=\"%s\"", + type, row->domain, row->oldtype, row->oldkind); + sqlite3_reset(stmt); + sqlite3_finalize(stmt); + return false; + } + } + + // Bind oldtype to database statement if((rc = sqlite3_bind_int(stmt, idx, oldtype)) != SQLITE_OK) { *message = sqlite3_errmsg(gravity_db); logg("gravityDB_addToTable(%d, %s): Failed to bind oldtype (error %d) - %s", - type, row->domain, rc, *message); + type, row->domain, rc, *message); sqlite3_reset(stmt); sqlite3_finalize(stmt); return false; diff --git a/src/database/gravity-db.h b/src/database/gravity-db.h index 9ad0adb5..d5222e4d 100644 --- a/src/database/gravity-db.h +++ b/src/database/gravity-db.h @@ -25,11 +25,13 @@ typedef struct { const char *domain; const char *address; const char *type; + const char *oldtype; + const char *kind; + const char *oldkind; const char *comment; const char *group_ids; const char *description; const char *argument; - const char *oldtype; const char *ip; long id; time_t date_added;