[ADD/WIP] Filtering some event fields(somewhat)
Some checks failed
Compile Telodendria / Compile Telodendria (x86, alpine-v3.19) (push) Has been cancelled
Compile Telodendria / Compile Telodendria (x86, debian-v12.4) (push) Has been cancelled
Compile Telodendria / Compile Telodendria (x86, freebsd-v14.0) (push) Has been cancelled
Compile Telodendria / Compile Telodendria (x86, netbsd-v9.3) (push) Has been cancelled
Compile Telodendria / Compile Telodendria (x86_64, alpine-v3.19) (push) Has been cancelled
Compile Telodendria / Compile Telodendria (x86_64, debian-v12.4) (push) Has been cancelled
Compile Telodendria / Compile Telodendria (x86_64, freebsd-v14.0) (push) Has been cancelled
Compile Telodendria / Compile Telodendria (x86_64, netbsd-v9.3) (push) Has been cancelled
Compile Telodendria / Compile Telodendria (x86_64, openbsd-v7.4) (push) Has been cancelled

This commit is contained in:
LDA 2024-07-24 13:17:53 +02:00
parent 123aa0b23a
commit 3e5d9dbe62
5 changed files with 156 additions and 8 deletions

View file

@ -32,6 +32,8 @@
#include <Schema/Filter.h>
#include <Matrix.h>
/* Verifies whenever an item passes through a set of blacklisted and
* whitelisted groups(e.g "not_rooms"/"rooms"), and makes the calling
* function return true/false if it is explicitely in a filtered list,
@ -120,6 +122,52 @@ IsRoomFiltered(Filter *filter, char *roomID)
return false;
}
static HashMap *
IncludeFields(Array * fields, HashMap * event)
{
HashMap *cpy;
size_t i, len;
if (!event)
{
return NULL;
}
if (!fields)
{
return JsonDuplicate(event);
}
cpy = HashMapCreate();
/* NOTE: We intentionally add some fields due to some requirements
* around certain schemas. The specification does find such behavior
* compliant:
* > "[...] A server may include more fields than were requested." */
#define CopyField(field) \
HashMapSet(cpy, field, JsonValueDuplicate(HashMapGet(event, field)))
CopyField("event_id");
CopyField("origin_server_ts");
CopyField("sender");
CopyField("type");
len = ArraySize(fields);
for (i = 0; i < len; i++)
{
char *field = ArrayGet(fields, i);
JsonValue *val = JsonValueDuplicate(MatrixGetJSON(event, field));
JsonValueFree(MatrixSetJSON(cpy, field, val));
}
/* Only copy it if not already present. */
if (!HashMapGet(cpy, "content"))
{
CopyField("content");
}
#undef CopyField
return cpy;
}
/* TODO: MORE FILTERS! */
HashMap *
FilterApply(Filter * filter, HashMap * event)
@ -144,26 +192,31 @@ FilterApply(Filter * filter, HashMap * event)
{
return NULL;
}
copy = JsonDuplicate(event);
copy = IncludeFields(filter->event_fields, event);
return copy;
}
Filter *
FilterDecode(Db *db, char *user, char *filterStr)
FilterDecode(Db *db, char *user, char *filterStr, char **errp)
{
Filter *ret;
DbRef *filterRef;
HashMap *filterObj;
if (!db || !user || !filterStr)
{
if (errp)
{
*errp =
"Internal error: Field required for FilterDecode is missing.";
}
return NULL;
}
if (*filterStr != '{')
{
char *err; /* TODO: use error status somewhere... */
char *err;
filterRef = DbLock(db, 3, "filters", user, filterStr);
filterObj = DbJson(filterRef);
@ -172,17 +225,24 @@ FilterDecode(Db *db, char *user, char *filterStr)
if (!FilterFromJson(filterObj, ret, &err))
{
if (errp)
{
*errp = err;
}
DbUnlock(db, filterRef);
Free(ret);
return NULL;
}
DbUnlock(db, filterRef);
(void) err;
return ret;
}
/* TODO: Decode JSON here... */
if (errp)
{
*errp = "Unimplemented feature: decoding from a raw JSON object";
}
return NULL;
}

View file

@ -428,3 +428,84 @@ MatrixGetJSON(HashMap *json, char *string)
}
return retVal;
}
JsonValue *
MatrixSetJSON(HashMap *json, char *string, JsonValue *new)
{
JsonValue *retVal;
HashMap *currentObj;
char *field, *fieldTemp;
size_t i, length;
if (!json || !string || !new)
{
return NULL;
}
currentObj = json;
retVal = NULL;
length = strlen(string);
field = NULL;
#define Append(ch) do \
{ \
char chb[2] = { ch, 0 }; \
fieldTemp = field; \
field = StrConcat(2, field, chb); \
Free(fieldTemp); \
} while (0)
/* We include the 0-terminator as a valid separator. */
for (i = 0; i < length + 1; i++)
{
char currentChar = string[i];
char escape;
if (currentChar == '\\' && (escape = string[i+1]))
{
if (escape != '.' && escape != '\\')
{
Append('\\');
}
Append(escape);
i++;
continue;
}
else if (currentChar == '.' || currentChar == '\0')
{
if (!field || !currentObj)
{
Free(field);
return NULL;
}
if (currentChar == '.')
{
retVal = HashMapGet(currentObj, field);
if (!retVal)
{
retVal = JsonValueObject(HashMapCreate());
HashMapSet(currentObj, field, retVal);
}
currentObj = JsonValueAsObject(retVal);
Free(field);
field = NULL;
continue;
}
retVal = HashMapSet(currentObj, field, new);
Free(field);
field = NULL;
continue;
}
Append(currentChar);
}
#undef Append
if (field)
{
/* This is weird. */
Free(field);
}
return retVal;
}

View file

@ -121,9 +121,8 @@ ROUTE_IMPL(RouteSync, path, argp)
if (filter)
{
char *userName = UserGetName(user);
if (!(filterData = FilterDecode(db, userName, filter)))
if (!(filterData = FilterDecode(db, userName, filter, &err)))
{
err = "Couldn't decode filter given in";
HttpResponseStatus(args->context, HTTP_BAD_REQUEST);
response = MatrixErrorCreate(M_BAD_JSON, err);
}

View file

@ -55,9 +55,10 @@ extern bool IsRoomFiltered(Filter *, char *);
/**
* Decodes a filter from a JSON stream to decode or an ID that was
* registered using the filter API.
* registered using the filter API, and may return an optional error
* string, if not set to NULL.
*/
extern Filter * FilterDecode(Db *, char *, char *);
extern Filter * FilterDecode(Db *, char *, char *, char **);
/**
* Frees all memory created by

View file

@ -163,4 +163,11 @@ extern HashMap * MatrixClientWellKnown(char *, char *);
*/
extern JsonValue * MatrixGetJSON(HashMap *, char *);
/**
* Sets a value given a dot-separated path (see
* .Fn MatrixGetJSON
* for more information).
*/
extern JsonValue * MatrixSetJSON(HashMap *, char *, JsonValue *);
#endif