From a8924b84378f0d743c9ab1aa2fd2d00aa29f58f7 Mon Sep 17 00:00:00 2001 From: Jordan Bancino Date: Sat, 18 May 2024 10:55:15 -0400 Subject: [PATCH 1/4] Update Cytoplasm to v0.4.1. --- Cytoplasm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cytoplasm b/Cytoplasm index 5d87da3..346b912 160000 --- a/Cytoplasm +++ b/Cytoplasm @@ -1 +1 @@ -Subproject commit 5d87da31cda74e6808eebca72e9475aabde86532 +Subproject commit 346b912a0633cceac10780b8a103f6c89b5ba89f From ac9372a30a32c4cf67514ab2520e47762bc185b9 Mon Sep 17 00:00:00 2001 From: lda Date: Sun, 18 Aug 2024 19:31:14 -0400 Subject: [PATCH 2/4] User Directory Patch #70 (#28) Reviewed-on: https://git.telodendria.io/Telodendria/Telodendria/pulls/28 Co-authored-by: lda Co-committed-by: lda --- Schema/UserDirectoryRequest.json | 13 ++ src/Routes.c | 1 + src/Routes/RouteUserDirectory.c | 198 +++++++++++++++++++++++++++++++ src/include/Routes.h | 1 + 4 files changed, 213 insertions(+) create mode 100644 Schema/UserDirectoryRequest.json create mode 100644 src/Routes/RouteUserDirectory.c diff --git a/Schema/UserDirectoryRequest.json b/Schema/UserDirectoryRequest.json new file mode 100644 index 0000000..7e27c03 --- /dev/null +++ b/Schema/UserDirectoryRequest.json @@ -0,0 +1,13 @@ +{ + "header": "Schema\/UserDirectoryRequest.h", + "types": { + "UserDirectoryRequest": { + "fields": { + "search_term": { "type": "string" }, + "limit": { "type": "integer" } + }, + "type": "struct" + } + }, + "guard": "TELODENDRIA_SCHEMA_USERDIRECTORYREQUEST_H" +} diff --git a/src/Routes.c b/src/Routes.c index 2562e78..b52eb09 100644 --- a/src/Routes.c +++ b/src/Routes.c @@ -72,6 +72,7 @@ RouterBuild(void) R("/_matrix/client/v3/profile/(.*)", RouteUserProfile); R("/_matrix/client/v3/profile/(.*)/(avatar_url|displayname)", RouteUserProfile); + R("/_matrix/client/v3/user_directory/search", RouteUserDirectory); R("/_matrix/client/v3/user/(.*)/filter", RouteFilter); R("/_matrix/client/v3/user/(.*)/filter/(.*)", RouteFilter); diff --git a/src/Routes/RouteUserDirectory.c b/src/Routes/RouteUserDirectory.c new file mode 100644 index 0000000..2c091f3 --- /dev/null +++ b/src/Routes/RouteUserDirectory.c @@ -0,0 +1,198 @@ +/* + * Copyright (C) 2022-2023 Jordan Bancino <@jordan:bancino.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without dirRequest.limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include + +ROUTE_IMPL(RouteUserDirectory, path, argp) +{ + RouteArgs *args = argp; + HashMap *response = NULL; + HashMap *request = NULL; + + Array *users = NULL; + Array *results = NULL; + + Db *db = args->matrixArgs->db; + + Config *config = NULL; + + User *user = NULL; + + char *token = NULL; + char *requesterName = NULL; + char *msg = NULL; + + UserDirectoryRequest dirRequest; + + size_t i, included; + + (void) path; + + dirRequest.search_term = NULL; + dirRequest.limit = Int64Create(0, 10); + + + if (HttpRequestMethodGet(args->context) != HTTP_POST) + { + msg = "Request supports only POST."; + HttpResponseStatus(args->context, HTTP_BAD_REQUEST); + response = MatrixErrorCreate(M_UNRECOGNIZED, msg); + goto finish; + } + + request = JsonDecode(HttpServerStream(args->context)); + if (!request) + { + HttpResponseStatus(args->context, HTTP_BAD_REQUEST); + response = MatrixErrorCreate(M_NOT_JSON, NULL); + goto finish; + } + if (!UserDirectoryRequestFromJson(request, &dirRequest, &msg)) + { + HttpResponseStatus(args->context, HTTP_BAD_REQUEST); + response = MatrixErrorCreate(M_BAD_JSON, msg); + goto finish; + } + if (!dirRequest.search_term) + { + msg = "Field 'search_term' not set."; + HttpResponseStatus(args->context, HTTP_BAD_REQUEST); + response = MatrixErrorCreate(M_BAD_JSON, msg); + goto finish; + + } + + response = MatrixGetAccessToken(args->context, &token); + if (response) + { + return response; + } + + /* TODO: Actually use information related to the user. */ + user = UserAuthenticate(db, token); + if (!user) + { + HttpResponseStatus(args->context, HTTP_BAD_REQUEST); + response = MatrixErrorCreate(M_UNKNOWN_TOKEN, NULL); + goto finish; + } + requesterName = UserGetName(user); + + response = HashMapCreate(); + results = ArrayCreate(); + + /* TODO: Check for users matching search term and users outside our + * local server. */ + users = DbList(db, 1, "users"); + + config = ConfigLock(db); + if (!config) + { + Log(LOG_ERR, "Directory endpoint failed to lock configuration."); + HttpResponseStatus(args->context, HTTP_INTERNAL_SERVER_ERROR); + response = MatrixErrorCreate(M_UNKNOWN, NULL); + + goto finish; + } + +#define IncludedLtLimit (Int64Lt(Int64Create(0, included), dirRequest.limit)) + for (i = 0, included = 0; i < ArraySize(users) && IncludedLtLimit; i++) +#undef IncludedLtLimit + { + HashMap *obj; + User *currentUser; + char *name = ArrayGet(users, i); + char *displayName; + char *lowerDisplayName; + char *avatarUrl; + + if (!StrEquals(name, requesterName)) + { + currentUser = UserLock(db, name); + } + else + { + currentUser = user; + } + + displayName = UserGetProfile(currentUser, "displayname"); + lowerDisplayName = StrLower(displayName); + avatarUrl = UserGetProfile(currentUser, "avatar_url"); + + /* Check for the user ID and display name. */ + if (strstr(name, dirRequest.search_term) || + (lowerDisplayName && + strstr(lowerDisplayName, dirRequest.search_term))) + { + included++; + + obj = HashMapCreate(); + if (displayName) + { + JsonSet(obj, JsonValueString(displayName), 1, "display_name"); + } + if (avatarUrl) + { + JsonSet(obj, JsonValueString(displayName), 1, "avatar_url"); + } + if (name) + { + char *uID = StrConcat(4, "@", name, ":", config->serverName); + JsonSet(obj, JsonValueString(uID), 1, "user_id"); + Free(uID); + } + ArrayAdd(results, JsonValueObject(obj)); + } + if (lowerDisplayName) + { + Free(lowerDisplayName); + } + if (!StrEquals(name, requesterName)) + { + UserUnlock(currentUser); + } + } + JsonSet(response, JsonValueArray(results), 1, "results"); + JsonSet(response, JsonValueBoolean( + Int64Eq(Int64Create(0, included), dirRequest.limit)), 1, + "limited"); + +finish: + UserUnlock(user); + JsonFree(request); + DbListFree(users); + ConfigUnlock(config); + UserDirectoryRequestFree(&dirRequest); + return response; +} diff --git a/src/include/Routes.h b/src/include/Routes.h index 76de377..72516a0 100644 --- a/src/include/Routes.h +++ b/src/include/Routes.h @@ -86,6 +86,7 @@ ROUTE(RouteChangePwd); ROUTE(RouteDeactivate); ROUTE(RouteTokenValid); ROUTE(RouteUserProfile); +ROUTE(RouteUserDirectory); ROUTE(RouteRequestToken); ROUTE(RouteUiaFallback); From e263eca5dca108c571b5247211c4d056697cdafe Mon Sep 17 00:00:00 2001 From: lda Date: Wed, 21 Aug 2024 14:32:42 -0400 Subject: [PATCH 3/4] Fix build issues with #28 (#55) Just here to fix old code issues with #28. (we really need CI back, don't we?) --- Please review the developer certificate of origin: 1. The contribution was created in whole or in part by me, and I have the right to submit it under the open source licenses of the Telodendria project; or 1. The contribution is based upon a previous work that, to the best of my knowledge, is covered under an appropriate open source license and I have the right under that license to submit that work with modifications, whether created in whole or in part by me, under the Telodendria project license; or 1. The contribution was provided directly to me by some other person who certified (1), (2), or (3), and I have not modified it. 1. I understand and agree that this project and the contribution are made public and that a record of the contribution—including all personal information I submit with it—is maintained indefinitely and may be redistributed consistent with this project or the open source licenses involved. - [x] I have read the Telodendria Project development certificate of origin, and I certify that I have permission to submit this patch under the conditions specified in it. Co-authored-by: LDA Reviewed-on: https://git.telodendria.io/Telodendria/Telodendria/pulls/55 Co-authored-by: lda Co-committed-by: lda --- src/Routes/RouteUserDirectory.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/Routes/RouteUserDirectory.c b/src/Routes/RouteUserDirectory.c index 2c091f3..c38441a 100644 --- a/src/Routes/RouteUserDirectory.c +++ b/src/Routes/RouteUserDirectory.c @@ -45,7 +45,7 @@ ROUTE_IMPL(RouteUserDirectory, path, argp) Db *db = args->matrixArgs->db; - Config *config = NULL; + Config config = { .ok = 0 }; User *user = NULL; @@ -60,7 +60,7 @@ ROUTE_IMPL(RouteUserDirectory, path, argp) (void) path; dirRequest.search_term = NULL; - dirRequest.limit = Int64Create(0, 10); + dirRequest.limit = 10; if (HttpRequestMethodGet(args->context) != HTTP_POST) @@ -116,17 +116,17 @@ ROUTE_IMPL(RouteUserDirectory, path, argp) * local server. */ users = DbList(db, 1, "users"); - config = ConfigLock(db); - if (!config) + ConfigLock(db, &config); + if (!config.ok) { Log(LOG_ERR, "Directory endpoint failed to lock configuration."); HttpResponseStatus(args->context, HTTP_INTERNAL_SERVER_ERROR); - response = MatrixErrorCreate(M_UNKNOWN, NULL); + response = MatrixErrorCreate(M_UNKNOWN, config.err); goto finish; } -#define IncludedLtLimit (Int64Lt(Int64Create(0, included), dirRequest.limit)) +#define IncludedLtLimit ((int64_t) included < dirRequest.limit) for (i = 0, included = 0; i < ArraySize(users) && IncludedLtLimit; i++) #undef IncludedLtLimit { @@ -168,7 +168,7 @@ ROUTE_IMPL(RouteUserDirectory, path, argp) } if (name) { - char *uID = StrConcat(4, "@", name, ":", config->serverName); + char *uID = StrConcat(4, "@", name, ":", config.serverName); JsonSet(obj, JsonValueString(uID), 1, "user_id"); Free(uID); } @@ -184,15 +184,16 @@ ROUTE_IMPL(RouteUserDirectory, path, argp) } } JsonSet(response, JsonValueArray(results), 1, "results"); - JsonSet(response, JsonValueBoolean( - Int64Eq(Int64Create(0, included), dirRequest.limit)), 1, - "limited"); + JsonSet(response, + JsonValueBoolean((int64_t) included == dirRequest.limit), + 1, "limited" + ); finish: UserUnlock(user); JsonFree(request); DbListFree(users); - ConfigUnlock(config); + ConfigUnlock(&config); UserDirectoryRequestFree(&dirRequest); return response; } From 6dd4440125f75ccae5e7fd3af1fa987f9df8cdaf Mon Sep 17 00:00:00 2001 From: "LevitatingBusinessMan (Rein Fernhout)" Date: Fri, 23 Aug 2024 16:16:33 -0400 Subject: [PATCH 4/4] remove use of install in Makefile (#56) The current make `install` target uses `install -D` to create leading components when install into a directory. This doesn't work on some variants of `install(1)`. Also see https://git.telodendria.io/Telodendria/Cytoplasm/issues/45 and https://git.telodendria.io/Telodendria/Cytoplasm/issues/13 and https://git.telodendria.io/Telodendria/Cytoplasm/commit/08166dd3a77609b7a87e618f42099bbfd346204c. --- Please review the developer certificate of origin: 1. The contribution was created in whole or in part by me, and I have the right to submit it under the open source licenses of the Telodendria project; or 1. The contribution is based upon a previous work that, to the best of my knowledge, is covered under an appropriate open source license and I have the right under that license to submit that work with modifications, whether created in whole or in part by me, under the Telodendria project license; or 1. The contribution was provided directly to me by some other person who certified (1), (2), or (3), and I have not modified it. 1. I understand and agree that this project and the contribution are made public and that a record of the contribution—including all personal information I submit with it—is maintained indefinitely and may be redistributed consistent with this project or the open source licenses involved. - [x] I have read the Telodendria Project development certificate of origin, and I certify that I have permission to submit this patch under the conditions specified in it. Reviewed-on: https://git.telodendria.io/Telodendria/Telodendria/pulls/56 Co-authored-by: LevitatingBusinessMan (Rein Fernhout) Co-committed-by: LevitatingBusinessMan (Rein Fernhout) --- configure | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/configure b/configure index 1da5858..17bacfa 100755 --- a/configure +++ b/configure @@ -231,15 +231,19 @@ compile_schema() { install_out() { src="$1" out="$2" + dir=$(dirname "$out") - echo "${TAB}install -D \"$src\" \"$out\"" + echo "${TAB}mkdir -p \"$dir\"" + echo "${TAB}cp \"$src\" \"$out\"" } install_man() { src="${OUT}/man/man3/${BIN_NAME}-$(basename $1 .h).3" out="$2" + dir=$(dirname "$out") - echo "${TAB}install -D \"$src\" \"$out\"" + echo "${TAB}mkdir -p \"$dir\"" + echo "${TAB}cp \"$src\" \"$out\"" } uninstall_out() { @@ -287,7 +291,8 @@ ${TAB}done ${BIN_NAME}: ${OUT}/bin/${BIN_NAME} install: ${BIN_NAME} -${TAB}install -D ${OUT}/bin/${BIN_NAME} \$(PREFIX)/bin/${BIN_NAME} +${TAB}mkdir -p \$(PREFIX)/bin +${TAB}cp ${OUT}/bin/${BIN_NAME} \$(PREFIX)/bin/${BIN_NAME} uninstall: ${TAB}rm \$(PREFIX)/bin/${BIN_NAME}