/**
* part of Hydrilla
* Routines that perform queries on in-memory scriptbase and return results in
* the form of JSON strings.
*
* Copyright (C) 2021 Wojtek Kosior
* Redistribution terms are gathered in the `copyright' file.
*/
#include <errno.h>
#include "scriptbase.h"
#define ADD_COMPONENT(object, key, construct, adder) \
new = cJSON_Create##construct; \
if (!new) \
goto free_json; \
adder(object, key, new)
#define ADD_TO_OBJECT(object, key, construct) \
ADD_COMPONENT(object, key, construct, cJSON_AddItemToObject)
#define ADD_KEY(key, construct) ADD_TO_OBJECT(json, key, construct)
#define ARRAY_ADDER(object, key, var) cJSON_AddItemToArray(object, var)
#define ADD_TO_ARRAY(object, construct) \
ADD_COMPONENT(object, dummy, construct, ARRAY_ADDER)
char *get_script_json(const char *name, struct scriptbase *base)
{
const struct script *script;
cJSON *json, *new;
char *printed = NULL;
script = get_script(name, base);
if (!script || !script->filled)
return NULL;
json = cJSON_CreateObject();
if (!json)
goto free_json;
ADD_KEY("name", String(script->name));
ADD_KEY("location", String(script->location));
ADD_KEY("sha256", String(script->sha256));
printed = cJSON_Print(json);
free_json:
cJSON_Delete(json);
if (!printed)
errno = ENOMEM;
return printed;
}
char *get_bag_json(const char *name, struct scriptbase *base)
{
const struct bag *bag;
cJSON *json, *new, *components, *current_component;
struct component_ref *ref;
char type_prefix[] = "\0";
char *printed = NULL;
bag = get_bag(name, base);
if (!bag || !bag->filled)
return NULL;
json = cJSON_CreateObject();
if (!json)
goto free_json;
ADD_KEY("name", String(bag->name));
ADD_KEY("components", Array());
components = new;
for (ref = bag->components; ref; ref = ref->next) {
ADD_TO_ARRAY(components, Array());
current_component = new;
type_prefix[0] = ref->component_type[0];
ADD_TO_ARRAY(current_component, String(type_prefix));
/* name is at the same offset in struct bag and struct script */
ADD_TO_ARRAY(current_component,
String(ref->component.bag->name));
}
printed = cJSON_Print(json);
free_json:
cJSON_Delete(json);
if (!printed)
errno = ENOMEM;
return printed;
}
cJSON *page_to_cJSON(const struct page *page)
{
cJSON *json, *new, *payload;
char type_prefix[] = "\0";
json = cJSON_CreateObject();
if (!json)
goto free_json;
ADD_KEY("pattern", String(page->pattern));
if (!page->payload.any)
goto skip_payload;
ADD_KEY("payload", Array());
payload = new;
type_prefix[0] = page->payload_type[0];
ADD_TO_ARRAY(payload, String(type_prefix));
/* name is at the same offset in struct bag and struct script */
ADD_TO_ARRAY(payload, String(page->payload.bag->name));
skip_payload:
return json;
free_json:
cJSON_Delete(json);
errno = ENOMEM;
return NULL;
}
char *get_pattern_json(const char *pattern, struct scriptbase *base)
{
const struct page *page;
cJSON *json;
char *printed = NULL;
page = get_pattern(pattern, base);
if (!page)
return NULL;
json = page_to_cJSON(page);
if (!json)
return NULL;
printed = cJSON_Print(json);
cJSON_Delete(json);
if (!printed)
errno = ENOMEM;
return printed;
}
struct page_array_building {
cJSON *page_array;
bool OOM_error;
};
int lookup_callback(struct page *page, void *data)
{
struct page_array_building *building = data;
cJSON *page_json;
page_json = page_to_cJSON(page);
if (!page_json) {
building->OOM_error = true;
return -1;
}
cJSON_AddItemToArray(building->page_array, page_json);
return 0;
}
#include <stdio.h>
char *get_page_query_json(const char *url, struct scriptbase *base)
{
struct page_array_building building = {NULL, false};
char *printed = NULL;
int result = -2;
building.page_array = cJSON_CreateArray();
if (!building.page_array)
goto free_json;
result = lookup_url(url, base, lookup_callback, &building);
printf("lookup returned value is %d\n", result);
if (building.OOM_error)
result = -2;
if (result < 0)
goto free_json;
printed = cJSON_Print(building.page_array);
if (!printed)
result = -2;
free_json:
cJSON_Delete(building.page_array);
switch (result) {
case 0:
break;
case -1:
case -3:
errno = EINVAL;
break;
case -2:
errno = ENOMEM;
}
return printed;
}