Make Telodendria compatible with latest Cytoplasm.

This also brings Telodendria to C99 compliance.
This commit is contained in:
Jordan Bancino 2024-01-13 20:02:07 -05:00
parent f2a4a64b27
commit e62389aa14
13 changed files with 175 additions and 207 deletions

View file

@ -30,7 +30,6 @@
#include <Cytoplasm/Str.h> #include <Cytoplasm/Str.h>
#include <Cytoplasm/Db.h> #include <Cytoplasm/Db.h>
#include <Cytoplasm/Log.h> #include <Cytoplasm/Log.h>
#include <Cytoplasm/Int64.h>
#include <Cytoplasm/Util.h> #include <Cytoplasm/Util.h>
#include <sys/types.h> #include <sys/types.h>
@ -59,7 +58,7 @@ ConfigParse(HashMap * config, Config *tConfig)
memset(tConfig, 0, sizeof(Config)); memset(tConfig, 0, sizeof(Config));
tConfig->maxCache = Int64Create(0, 0); tConfig->maxCache = 0;
if (!ConfigFromJson(config, tConfig, &tConfig->err)) if (!ConfigFromJson(config, tConfig, &tConfig->err))
{ {
@ -85,17 +84,17 @@ ConfigParse(HashMap * config, Config *tConfig)
for (i = 0; i < ArraySize(tConfig->listen); i++) for (i = 0; i < ArraySize(tConfig->listen); i++)
{ {
ConfigListener *listener = ArrayGet(tConfig->listen, i); ConfigListener *listener = ArrayGet(tConfig->listen, i);
if (Int64Eq(listener->maxConnections, Int64Create(0, 0))) if (!listener->maxConnections)
{ {
listener->maxConnections = Int64Create(0, 32); listener->maxConnections = 32;
} }
if (Int64Eq(listener->threads, Int64Create(0, 0))) if (!listener->threads)
{ {
listener->threads = Int64Create(0, 4); listener->threads = 4;
} }
if (Int64Eq(listener->port, Int64Create(0, 0))) if (!listener->port)
{ {
listener->port = Int64Create(0, 8008); listener->port = 8008;
} }
} }
tConfig->ok = 1; tConfig->ok = 1;
@ -148,9 +147,9 @@ ConfigCreateDefault(Db * db)
/* Add simple listener without TLS. */ /* Add simple listener without TLS. */
config.listen = ArrayCreate(); config.listen = ArrayCreate();
listener = Malloc(sizeof(ConfigListener)); listener = Malloc(sizeof(ConfigListener));
listener->maxConnections = Int64Create(0, 32); listener->maxConnections = 32;
listener->port = Int64Create(0, 8008); listener->port = 8008;
listener->threads = Int64Create(0, 4); listener->threads = 4;
ArrayAdd(config.listen, listener); ArrayAdd(config.listen, listener);

View file

@ -36,14 +36,12 @@
#include <Cytoplasm/Args.h> #include <Cytoplasm/Args.h>
#include <Cytoplasm/Memory.h> #include <Cytoplasm/Memory.h>
#include <Config.h>
#include <Cytoplasm/Log.h> #include <Cytoplasm/Log.h>
#include <Cytoplasm/HashMap.h> #include <Cytoplasm/HashMap.h>
#include <Cytoplasm/Json.h> #include <Cytoplasm/Json.h>
#include <Cytoplasm/HttpServer.h> #include <Cytoplasm/HttpServer.h>
#include <Cytoplasm/Db.h> #include <Cytoplasm/Db.h>
#include <Cytoplasm/Cron.h> #include <Cytoplasm/Cron.h>
#include <Uia.h>
#include <Cytoplasm/Util.h> #include <Cytoplasm/Util.h>
#include <Cytoplasm/Str.h> #include <Cytoplasm/Str.h>
@ -52,6 +50,9 @@
#include <User.h> #include <User.h>
#include <RegToken.h> #include <RegToken.h>
#include <Routes.h> #include <Routes.h>
#include <Uia.h>
#include <Config.h>
static Array *httpServers; static Array *httpServers;
static volatile int restart; static volatile int restart;
@ -248,7 +249,7 @@ start:
} }
token = StrRandom(32); token = StrRandom(32);
info = RegTokenCreate(matrixArgs.db, token, NULL, UInt64Create(0, 0), Int64Create(0, 1), USER_ALL); info = RegTokenCreate(matrixArgs.db, token, NULL, /* expires */ 0, /* uses */ 1, USER_ALL);
if (!info) if (!info)
{ {
Free(token); Free(token);
@ -396,14 +397,14 @@ start:
if (args.flags & HTTP_FLAG_TLS) if (args.flags & HTTP_FLAG_TLS)
{ {
if (UInt64Eq(UtilLastModified(serverCfg->tls.cert), UInt64Create(0, 0))) if (!UtilLastModified(serverCfg->tls.cert))
{ {
Log(LOG_ERR, "%s: %s", strerror(errno), serverCfg->tls.cert); Log(LOG_ERR, "%s: %s", strerror(errno), serverCfg->tls.cert);
exit = EXIT_FAILURE; exit = EXIT_FAILURE;
goto finish; goto finish;
} }
if (UInt64Eq(UtilLastModified(serverCfg->tls.key), UInt64Create(0, 0))) if (UtilLastModified(serverCfg->tls.key))
{ {
Log(LOG_ERR, "%s: %s", strerror(errno), serverCfg->tls.key); Log(LOG_ERR, "%s: %s", strerror(errno), serverCfg->tls.key);
exit = EXIT_FAILURE; exit = EXIT_FAILURE;

View file

@ -27,7 +27,6 @@
#include <Cytoplasm/Memory.h> #include <Cytoplasm/Memory.h>
#include <Cytoplasm/Str.h> #include <Cytoplasm/Str.h>
#include <Cytoplasm/Int.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
@ -38,7 +37,7 @@
#define Iterate(s) (*(*s)++) #define Iterate(s) (*(*s)++)
/* Parse an extended localpart */ /* Parse an extended localpart */
static int static bool
ParseUserLocalpart(char **str, char **out) ParseUserLocalpart(char **str, char **out)
{ {
char c; char c;
@ -47,7 +46,7 @@ ParseUserLocalpart(char **str, char **out)
if (!str || !out) if (!str || !out)
{ {
return 0; return false;
} }
/* An extended localpart contains every ASCII printable character, /* An extended localpart contains every ASCII printable character,
* except an ':'. */ * except an ':'. */
@ -60,7 +59,7 @@ ParseUserLocalpart(char **str, char **out)
if (length < 1) if (length < 1)
{ {
*str = start; *str = start;
return 0; return false;
} }
if (c == ':') if (c == ':')
{ {
@ -71,8 +70,9 @@ ParseUserLocalpart(char **str, char **out)
memcpy(*out, start, length); memcpy(*out, start, length);
(*out)[length] = '\0'; (*out)[length] = '\0';
return 1; return true;
} }
/* Parses an IPv4 address. */ /* Parses an IPv4 address. */
static int static int
ParseIPv4(char **str, char **out) ParseIPv4(char **str, char **out)
@ -102,14 +102,14 @@ ParseIPv4(char **str, char **out)
{ {
/* Current digit is too long for the spec! */ /* Current digit is too long for the spec! */
*str = start; *str = start;
return 0; return false;
} }
memcpy(buffer, *str - digit - 1, digit); memcpy(buffer, *str - digit - 1, digit);
if (atoi(buffer) > 255) if (atoi(buffer) > 255)
{ {
/* Current digit is too large for the spec! */ /* Current digit is too large for the spec! */
*str = start; *str = start;
return 0; return false;
} }
memset(buffer, 0, sizeof(buffer)); memset(buffer, 0, sizeof(buffer));
digit = 0; digit = 0;
@ -118,20 +118,22 @@ ParseIPv4(char **str, char **out)
if (c == '.' || digits != 3) if (c == '.' || digits != 3)
{ {
*str = start; *str = start;
return 0; return false;
} }
length = (size_t) (*str - start) - 1; length = (size_t) (*str - start) - 1;
*out = Malloc(length + 1); *out = Malloc(length + 1);
memcpy(*out, start, length); memcpy(*out, start, length);
(*str)--; (*str)--;
return 1; return true;
} }
static int
static bool
IsIPv6Char(char c) IsIPv6Char(char c)
{ {
return isxdigit(c) || c == ':' || c == '.'; return (isxdigit(c) || c == ':' || c == '.');
} }
static int
static bool
ParseIPv6(char **str, char **out) ParseIPv6(char **str, char **out)
{ {
char *start; char *start;
@ -174,7 +176,7 @@ ParseIPv6(char **str, char **out)
/* RFC3513 says the following: /* RFC3513 says the following:
* > 'The "::" can only appear once in an address.' */ * > 'The "::" can only appear once in an address.' */
*str = start; *str = start;
return 0; return false;
} }
if (digit < 1 || digit > 4) if (digit < 1 || digit > 4)
{ {
@ -217,12 +219,13 @@ end:
memset(*out, '\0', length + 1); memset(*out, '\0', length + 1);
memcpy(*out, start, length); memcpy(*out, start, length);
return 1; return true;
fail: fail:
*str = start; *str = start;
return 0; return false;
} }
static int
static bool
ParseHostname(char **str, char **out) ParseHostname(char **str, char **out)
{ {
char *start; char *start;
@ -239,16 +242,16 @@ ParseHostname(char **str, char **out)
if (length < 1 || length > 255) if (length < 1 || length > 255)
{ {
*str = start; *str = start;
return 0; return false;
} }
length = (size_t) (*str - start) - 1; length = (size_t) (*str - start) - 1;
*out = Malloc(length + 1); *out = Malloc(length + 1);
memcpy(*out, start, length); memcpy(*out, start, length);
(*str)--; (*str)--;
return 1; return true;
} }
static int static bool
ParseServerName(char **str, ServerPart *out) ParseServerName(char **str, ServerPart *out)
{ {
char c; char c;
@ -261,7 +264,7 @@ ParseServerName(char **str, ServerPart *out)
if (!str || !out) if (!str || !out)
{ {
return 0; return false;
} }
start = *str; start = *str;
@ -284,7 +287,7 @@ ParseServerName(char **str, ServerPart *out)
if (!host) if (!host)
{ {
/* Can't parse a valid server name. */ /* Can't parse a valid server name. */
return 0; return false;
} }
/* Now, there's only 2 options: a ':', or the end(everything else.) */ /* Now, there's only 2 options: a ':', or the end(everything else.) */
if (**str != ':') if (**str != ':')
@ -292,7 +295,7 @@ ParseServerName(char **str, ServerPart *out)
/* We're done. */ /* We're done. */
out->hostname = host; out->hostname = host;
out->port = NULL; out->port = NULL;
return 1; return true;
} }
/* TODO: Separate this out */ /* TODO: Separate this out */
startPort = ++(*str); startPort = ++(*str);
@ -305,7 +308,7 @@ ParseServerName(char **str, ServerPart *out)
*str = start; *str = start;
Free(host); Free(host);
host = NULL; host = NULL;
return 0; return false;
} }
port = Malloc(chars + 1); port = Malloc(chars + 1);
@ -316,24 +319,26 @@ ParseServerName(char **str, ServerPart *out)
Free(port); Free(port);
Free(host); Free(host);
*str = start; *str = start;
return 0; return false;
} }
out->hostname = host; out->hostname = host;
out->port = port; out->port = port;
return 1; return true;
} }
int
bool
ParseServerPart(char *str, ServerPart *part) ParseServerPart(char *str, ServerPart *part)
{ {
/* This is a wrapper behind the internal ParseServerName. */ /* This is a wrapper behind the internal ParseServerName. */
if (!str || !part) if (!str || !part)
{ {
return 0; return false;
} }
return ParseServerName(&str, part); return ParseServerName(&str, part);
} }
void void
ServerPartFree(ServerPart part) ServerPartFree(ServerPart part)
{ {
@ -347,20 +352,20 @@ ServerPartFree(ServerPart part)
} }
} }
int bool
ParseCommonID(char *str, CommonID *id) ParseCommonID(char *str, CommonID *id)
{ {
char sigil; char sigil;
if (!str || !id) if (!str || !id)
{ {
return 0; return false;
} }
/* There must at least be 2 chararacters: the sigil and a string.*/ /* There must at least be 2 chararacters: the sigil and a string.*/
if (strlen(str) < 2) if (strlen(str) < 2)
{ {
return 0; return false;
} }
sigil = *str++; sigil = *str++;
@ -369,7 +374,7 @@ ParseCommonID(char *str, CommonID *id)
*/ */
if ((sigil == '#' || sigil == '@') && strlen(str) > 255) if ((sigil == '#' || sigil == '@') && strlen(str) > 255)
{ {
return 0; return false;
} }
id->sigil = sigil; id->sigil = sigil;
id->local = NULL; id->local = NULL;
@ -383,7 +388,7 @@ ParseCommonID(char *str, CommonID *id)
* accepting it all. */ * accepting it all. */
if (!ParseUserLocalpart(&str, &id->local)) if (!ParseUserLocalpart(&str, &id->local))
{ {
return 0; return false;
} }
if (*str == ':') if (*str == ':')
{ {
@ -392,9 +397,9 @@ ParseCommonID(char *str, CommonID *id)
{ {
Free(id->local); Free(id->local);
id->local = NULL; id->local = NULL;
return 0; return false;
} }
return 1; return true;
} }
break; break;
case '!': case '!':
@ -403,23 +408,23 @@ ParseCommonID(char *str, CommonID *id)
case '@': case '@':
if (!ParseUserLocalpart(&str, &id->local)) if (!ParseUserLocalpart(&str, &id->local))
{ {
return 0; return false;
} }
if (*str++ != ':') if (*str++ != ':')
{ {
Free(id->local); Free(id->local);
id->local = NULL; id->local = NULL;
return 0; return false;
} }
if (!ParseServerName(&str, &id->server)) if (!ParseServerName(&str, &id->server))
{ {
Free(id->local); Free(id->local);
id->local = NULL; id->local = NULL;
return 0; return false;
} }
break; break;
} }
return 1; return true;
} }
void void
@ -431,15 +436,18 @@ CommonIDFree(CommonID id)
} }
ServerPartFree(id.server); ServerPartFree(id.server);
} }
int
bool
ValidCommonID(char *str, char sigil) ValidCommonID(char *str, char sigil)
{ {
CommonID id; CommonID id;
int ret; bool ret;
memset(&id, 0, sizeof(CommonID)); memset(&id, 0, sizeof(CommonID));
if (!str) if (!str)
{ {
return 0; return false;
} }
ret = ParseCommonID(str, &id) && id.sigil == sigil; ret = ParseCommonID(str, &id) && id.sigil == sigil;
@ -447,6 +455,7 @@ ValidCommonID(char *str, char sigil)
CommonIDFree(id); CommonIDFree(id);
return ret; return ret;
} }
char * char *
ParserRecomposeServerPart(ServerPart serverPart) ParserRecomposeServerPart(ServerPart serverPart)
{ {
@ -460,6 +469,7 @@ ParserRecomposeServerPart(ServerPart serverPart)
} }
return NULL; return NULL;
} }
char * char *
ParserRecomposeCommonID(CommonID id) ParserRecomposeCommonID(CommonID id)
{ {
@ -485,15 +495,18 @@ ParserRecomposeCommonID(CommonID id)
} }
return ret; return ret;
} }
int
bool
ParserServerNameEquals(ServerPart serverPart, char *str) ParserServerNameEquals(ServerPart serverPart, char *str)
{ {
char *idServer; char *idServer;
int ret; bool ret;
if (!str) if (!str)
{ {
return 0; return false;
} }
idServer = ParserRecomposeServerPart(serverPart); idServer = ParserRecomposeServerPart(serverPart);
ret = StrEquals(idServer, str); ret = StrEquals(idServer, str);

View file

@ -31,7 +31,6 @@
#include <Cytoplasm/Json.h> #include <Cytoplasm/Json.h>
#include <Cytoplasm/Util.h> #include <Cytoplasm/Util.h>
#include <Cytoplasm/Str.h> #include <Cytoplasm/Str.h>
#include <Cytoplasm/Int64.h>
#include <Cytoplasm/Log.h> #include <Cytoplasm/Log.h>
#include <User.h> #include <User.h>
@ -40,9 +39,9 @@ int
RegTokenValid(RegTokenInfo * token) RegTokenValid(RegTokenInfo * token)
{ {
HashMap *tokenJson; HashMap *tokenJson;
Int64 uses, used; int64_t uses, used;
UInt64 expiration; uint64_t expiration;
if (!token || !RegTokenExists(token->db, token->name)) if (!token || !RegTokenExists(token->db, token->name))
{ {
@ -54,9 +53,7 @@ RegTokenValid(RegTokenInfo * token)
used = JsonValueAsInteger(HashMapGet(tokenJson, "used")); used = JsonValueAsInteger(HashMapGet(tokenJson, "used"));
expiration = JsonValueAsInteger(HashMapGet(tokenJson, "expires_on")); expiration = JsonValueAsInteger(HashMapGet(tokenJson, "expires_on"));
return (UInt64Eq(expiration, UInt64Create(0, 0)) || return (!expiration || (UtilTsMillis() < expiration)) && (uses == -1 || used < uses);
UInt64Geq(UtilServerTs(), expiration)) &&
(Int64Eq(uses, Int64Neg(Int64Create(0, 1))) || Int64Lt(used, uses));
} }
void void
RegTokenUse(RegTokenInfo * token) RegTokenUse(RegTokenInfo * token)
@ -68,13 +65,12 @@ RegTokenUse(RegTokenInfo * token)
return; return;
} }
if (Int64Geq(token->uses, Int64Create(0, 0)) && if (token->uses >= 0 && token->used >= token->uses)
Int64Geq(token->used, token->uses))
{ {
return; return;
} }
token->used = Int64Add(token->used, Int64Create(0, 1)); token->used++;
/* Write the information to the hashmap */ /* Write the information to the hashmap */
tokenJson = DbJson(token->ref); tokenJson = DbJson(token->ref);
@ -199,11 +195,11 @@ RegTokenVerify(char *token)
} }
RegTokenInfo * RegTokenInfo *
RegTokenCreate(Db * db, char *name, char *owner, UInt64 expires, Int64 uses, int privileges) RegTokenCreate(Db * db, char *name, char *owner, uint64_t expires, int64_t uses, int privileges)
{ {
RegTokenInfo *ret; RegTokenInfo *ret;
UInt64 timestamp = UtilServerTs(); uint64_t timestamp = UtilTsMillis();
if (!db || !name) if (!db || !name)
{ {
@ -213,13 +209,13 @@ RegTokenCreate(Db * db, char *name, char *owner, UInt64 expires, Int64 uses, int
/* -1 indicates infinite uses; zero and all positive values are a /* -1 indicates infinite uses; zero and all positive values are a
* valid number of uses; althought zero would be rather useless. * valid number of uses; althought zero would be rather useless.
* Anything less than -1 doesn't make sense. */ * Anything less than -1 doesn't make sense. */
if (Int64Lt(uses, Int64Neg(Int64Create(0, 1)))) if (uses < -1)
{ {
return NULL; return NULL;
} }
/* Verify the token */ /* Verify the token */
if (!RegTokenVerify(name) || (UInt64Gt(expires, UInt64Create(0, 0)) && UInt64Lt(expires, timestamp))) if (!RegTokenVerify(name) || ((expires > 0) && (expires < timestamp)))
{ {
return NULL; return NULL;
} }
@ -235,7 +231,7 @@ RegTokenCreate(Db * db, char *name, char *owner, UInt64 expires, Int64 uses, int
} }
ret->name = StrDuplicate(name); ret->name = StrDuplicate(name);
ret->created_by = StrDuplicate(owner); ret->created_by = StrDuplicate(owner);
ret->used = Int64Create(0, 0); ret->used = 0;
ret->uses = uses; ret->uses = uses;
ret->created_on = timestamp; ret->created_on = timestamp;
ret->expires_on = expires; ret->expires_on = expires;

View file

@ -24,7 +24,6 @@
*/ */
#include <Routes.h> #include <Routes.h>
#include <Cytoplasm/Int64.h>
#include <User.h> #include <User.h>
#include <Cytoplasm/Memory.h> #include <Cytoplasm/Memory.h>
#include <Cytoplasm/Str.h> #include <Cytoplasm/Str.h>
@ -86,24 +85,11 @@ ROUTE_IMPL(RouteProcControl, path, argp)
if (StrEquals(op, "stats")) if (StrEquals(op, "stats"))
{ {
size_t allocated = MemoryAllocated(); size_t allocated = MemoryAllocated();
Int64 a;
response = HashMapCreate(); response = HashMapCreate();
if (sizeof(size_t) == sizeof(Int64))
{
UInt32 high = (UInt32) (allocated >> 32);
UInt32 low = (UInt32) (allocated);
a = Int64Create(high, low);
}
else
{
a = Int64Create(0, allocated);
}
HashMapSet(response, "version", JsonValueString(TELODENDRIA_VERSION)); HashMapSet(response, "version", JsonValueString(TELODENDRIA_VERSION));
HashMapSet(response, "memory_allocated", JsonValueInteger(a)); HashMapSet(response, "memory_allocated", JsonValueInteger(allocated));
goto finish; goto finish;
} }

View file

@ -40,8 +40,6 @@ ROUTE_IMPL(RouteRequestToken, path, argp)
RequestToken reqTok; RequestToken reqTok;
Int64 minusOne = Int64Neg(Int64Create(0, 1));
reqTok.client_secret = NULL; reqTok.client_secret = NULL;
reqTok.next_link = NULL; reqTok.next_link = NULL;
reqTok.id_access_token = NULL; reqTok.id_access_token = NULL;
@ -51,7 +49,7 @@ ROUTE_IMPL(RouteRequestToken, path, argp)
reqTok.country = NULL; reqTok.country = NULL;
reqTok.phone_number = NULL; reqTok.phone_number = NULL;
reqTok.send_attempt = minusOne; reqTok.send_attempt = -1;
if (HttpRequestMethodGet(args->context) != HTTP_POST) if (HttpRequestMethodGet(args->context) != HTTP_POST)
{ {
@ -90,7 +88,7 @@ ROUTE_IMPL(RouteRequestToken, path, argp)
goto finish; goto finish;
} }
if (Int64Eq(reqTok.send_attempt, minusOne)) if (reqTok.send_attempt == -1)
{ {
msg = "Invalid or inexistent 'send_attempt'"; msg = "Invalid or inexistent 'send_attempt'";
HttpResponseStatus(args->context, HTTP_BAD_REQUEST); HttpResponseStatus(args->context, HTTP_BAD_REQUEST);

View file

@ -133,7 +133,7 @@ TelodendriaPrintHeader(void)
Log(LOG_INFO, "%s", TelodendriaHeader[i]); Log(LOG_INFO, "%s", TelodendriaHeader[i]);
} }
Log(LOG_INFO, "Telodendria v" TELODENDRIA_VERSION " (%s v%s)", CytoplasmGetName(), CytoplasmGetVersion()); Log(LOG_INFO, "Telodendria v" TELODENDRIA_VERSION " (Cytoplasm v%s)", CytoplasmGetVersionStr());
Log(LOG_INFO, ""); Log(LOG_INFO, "");
Log(LOG_INFO, Log(LOG_INFO,
"Copyright (C) 2024 Jordan Bancino <@jordan:bancino.net>"); "Copyright (C) 2024 Jordan Bancino <@jordan:bancino.net>");

View file

@ -135,7 +135,7 @@ BuildResponse(Array * flows, Db * db, HashMap ** response, char *session, DbRef
json = DbJson(ref); json = DbJson(ref);
HashMapSet(json, "completed", JsonValueArray(ArrayCreate())); HashMapSet(json, "completed", JsonValueArray(ArrayCreate()));
HashMapSet(json, "last_access", JsonValueInteger(UtilServerTs())); HashMapSet(json, "last_access", JsonValueInteger(UtilTsMillis()));
DbUnlock(db, ref); DbUnlock(db, ref);
HashMapSet(*response, "completed", JsonValueArray(ArrayCreate())); HashMapSet(*response, "completed", JsonValueArray(ArrayCreate()));
@ -452,7 +452,7 @@ UiaComplete(Array * flows, HttpServerContext * context, Db * db,
finish: finish:
ArrayFree(possibleNext); ArrayFree(possibleNext);
JsonValueFree(HashMapSet(dbJson, "last_access", JsonValueInteger(UtilServerTs()))); JsonValueFree(HashMapSet(dbJson, "last_access", JsonValueInteger(UtilTsMillis())));
DbUnlock(db, dbRef); DbUnlock(db, dbRef);
return ret; return ret;
} }
@ -498,7 +498,7 @@ UiaCleanup(MatrixHttpHandlerArgs * args)
char *session = ArrayGet(sessions, i); char *session = ArrayGet(sessions, i);
DbRef *ref = DbLock(args->db, 2, "user_interactive", session); DbRef *ref = DbLock(args->db, 2, "user_interactive", session);
UInt64 lastAccess; uint64_t lastAccess;
if (!ref) if (!ref)
{ {
@ -513,7 +513,7 @@ UiaCleanup(MatrixHttpHandlerArgs * args)
/* If last access was greater than 15 minutes ago, remove this /* If last access was greater than 15 minutes ago, remove this
* session */ * session */
if (UInt64Gt(UInt64Sub(UtilServerTs(), lastAccess), UInt64Create(0, 1000 * 60 * 15))) if ((UtilTsMillis() - lastAccess) > (1000 * 60 * 15))
{ {
DbDelete(args->db, 2, "user_interactive", session); DbDelete(args->db, 2, "user_interactive", session);
Log(LOG_DEBUG, "Deleted session %s", session); Log(LOG_DEBUG, "Deleted session %s", session);

View file

@ -28,8 +28,6 @@
#include <Cytoplasm/Str.h> #include <Cytoplasm/Str.h>
#include <Cytoplasm/Sha.h> #include <Cytoplasm/Sha.h>
#include <Cytoplasm/Json.h> #include <Cytoplasm/Json.h>
#include <Cytoplasm/Int64.h>
#include <Cytoplasm/UInt64.h>
#include <Parser.h> #include <Parser.h>
@ -44,7 +42,7 @@ struct User
char *deviceId; char *deviceId;
}; };
int bool
UserValidate(char *localpart, char *domain) UserValidate(char *localpart, char *domain)
{ {
size_t maxLen = 255 - strlen(domain) - 1; size_t maxLen = 255 - strlen(domain) - 1;
@ -56,23 +54,23 @@ UserValidate(char *localpart, char *domain)
if (i > maxLen) if (i > maxLen)
{ {
return 0; return false;
} }
if (!((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || if (!((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') ||
(c == '.') || (c == '_') || (c == '=') || (c == '-') || (c == '.') || (c == '_') || (c == '=') || (c == '-') ||
(c == '/'))) (c == '/')))
{ {
return 0; return false;
} }
i++; i++;
} }
return 1; return true;
} }
int bool
UserHistoricalValidate(char *localpart, char *domain) UserHistoricalValidate(char *localpart, char *domain)
{ {
size_t maxLen = 255 - strlen(domain) - 1; size_t maxLen = 255 - strlen(domain) - 1;
@ -84,21 +82,21 @@ UserHistoricalValidate(char *localpart, char *domain)
if (i > maxLen) if (i > maxLen)
{ {
return 0; return false;
} }
if (!((c >= 0x21 && c <= 0x39) || (c >= 0x3B && c <= 0x7E))) if (!((c >= 0x21 && c <= 0x39) || (c >= 0x3B && c <= 0x7E)))
{ {
return 0; return false;
} }
i++; i++;
} }
return 1; return true;
} }
int bool
UserExists(Db * db, char *name) UserExists(Db * db, char *name)
{ {
return DbExists(db, 2, "users", name); return DbExists(db, 2, "users", name);
@ -133,7 +131,7 @@ UserAuthenticate(Db * db, char *accessToken)
char *userName; char *userName;
char *deviceId; char *deviceId;
UInt64 expires; uint64_t expires;
if (!db || !accessToken) if (!db || !accessToken)
{ {
@ -157,8 +155,7 @@ UserAuthenticate(Db * db, char *accessToken)
return NULL; return NULL;
} }
if (UInt64Neq(expires, UInt64Create(0, 0)) && if (expires && UtilTsMillis() >= expires)
UInt64Geq(UtilServerTs(), expires))
{ {
UserUnlock(user); UserUnlock(user);
DbUnlock(db, atRef); DbUnlock(db, atRef);
@ -171,14 +168,14 @@ UserAuthenticate(Db * db, char *accessToken)
return user; return user;
} }
int bool
UserUnlock(User * user) UserUnlock(User * user)
{ {
int ret; bool ret;
if (!user) if (!user)
{ {
return 0; return false;
} }
Free(user->name); Free(user->name);
@ -196,7 +193,7 @@ UserCreate(Db * db, char *name, char *password)
User *user = NULL; User *user = NULL;
HashMap *json = NULL; HashMap *json = NULL;
UInt64 ts = UtilServerTs(); uint64_t ts = UtilTsMillis();
/* TODO: Put some sort of password policy(like for example at least /* TODO: Put some sort of password policy(like for example at least
* 8 chars, or maybe check it's entropy)? */ * 8 chars, or maybe check it's entropy)? */
@ -233,7 +230,7 @@ UserCreate(Db * db, char *name, char *password)
json = DbJson(user->ref); json = DbJson(user->ref);
HashMapSet(json, "createdOn", JsonValueInteger(ts)); HashMapSet(json, "createdOn", JsonValueInteger(ts));
HashMapSet(json, "deactivated", JsonValueBoolean(0)); HashMapSet(json, "deactivated", JsonValueBoolean(false));
return user; return user;
} }
@ -356,7 +353,7 @@ UserGetDeviceId(User * user)
return user ? user->deviceId : NULL; return user ? user->deviceId : NULL;
} }
int bool
UserCheckPassword(User * user, char *password) UserCheckPassword(User * user, char *password)
{ {
HashMap *json; HashMap *json;
@ -368,11 +365,11 @@ UserCheckPassword(User * user, char *password)
char *hashedPwd; char *hashedPwd;
char *tmp; char *tmp;
int result; bool result;
if (!user || !password) if (!user || !password)
{ {
return 0; return false;
} }
json = DbJson(user->ref); json = DbJson(user->ref);
@ -382,7 +379,7 @@ UserCheckPassword(User * user, char *password)
if (!storedHash || !salt) if (!storedHash || !salt)
{ {
return 0; return false;
} }
tmp = StrConcat(2, password, salt); tmp = StrConcat(2, password, salt);
@ -398,7 +395,7 @@ UserCheckPassword(User * user, char *password)
return result; return result;
} }
int bool
UserSetPassword(User * user, char *password) UserSetPassword(User * user, char *password)
{ {
HashMap *json; HashMap *json;
@ -410,7 +407,7 @@ UserSetPassword(User * user, char *password)
if (!user || !password) if (!user || !password)
{ {
return 0; return false;
} }
json = DbJson(user->ref); json = DbJson(user->ref);
@ -428,10 +425,10 @@ UserSetPassword(User * user, char *password)
Free(hashBytes); Free(hashBytes);
Free(tmpstr); Free(tmpstr);
return 1; return true;
} }
int bool
UserDeactivate(User * user, char * from, char * reason) UserDeactivate(User * user, char * from, char * reason)
{ {
HashMap *json; HashMap *json;
@ -439,7 +436,7 @@ UserDeactivate(User * user, char * from, char * reason)
if (!user) if (!user)
{ {
return 0; return false;
} }
/* By default, it's the target's username */ /* By default, it's the target's username */
@ -450,7 +447,7 @@ UserDeactivate(User * user, char * from, char * reason)
json = DbJson(user->ref); json = DbJson(user->ref);
JsonValueFree(HashMapSet(json, "deactivated", JsonValueBoolean(1))); JsonValueFree(HashMapSet(json, "deactivated", JsonValueBoolean(true)));
val = JsonValueString(from); val = JsonValueString(from);
JsonValueFree(JsonSet(json, val, 2, "deactivate", "by")); JsonValueFree(JsonSet(json, val, 2, "deactivate", "by"));
@ -460,38 +457,38 @@ UserDeactivate(User * user, char * from, char * reason)
JsonValueFree(JsonSet(json, val, 2, "deactivate", "reason")); JsonValueFree(JsonSet(json, val, 2, "deactivate", "reason"));
} }
return 1; return true;
} }
int bool
UserReactivate(User * user) UserReactivate(User * user)
{ {
HashMap *json; HashMap *json;
if (!user) if (!user)
{ {
return 0; return false;
} }
json = DbJson(user->ref); json = DbJson(user->ref);
JsonValueFree(HashMapSet(json, "deactivated", JsonValueBoolean(0))); JsonValueFree(HashMapSet(json, "deactivated", JsonValueBoolean(false)));
JsonValueFree(HashMapDelete(json, "deactivate")); JsonValueFree(HashMapDelete(json, "deactivate"));
return 1; return true;
} }
int bool
UserDeactivated(User * user) UserDeactivated(User * user)
{ {
HashMap *json; HashMap *json;
if (!user) if (!user)
{ {
return 1; return true;
} }
json = DbJson(user->ref); json = DbJson(user->ref);
@ -537,17 +534,17 @@ UserAccessTokenGenerate(User * user, char *deviceId, int withRefresh)
if (withRefresh) if (withRefresh)
{ {
token->lifetime = Int64Create(0, 1000 * 60 * 60 * 24 * 7); /* 1 Week */ token->lifetime = 1000 * 60 * 60 * 24 * 7; /* 1 Week */
} }
else else
{ {
token->lifetime = Int64Create(0, 0); token->lifetime = 0;
} }
return token; return token;
} }
int bool
UserAccessTokenSave(Db * db, UserAccessToken * token) UserAccessTokenSave(Db * db, UserAccessToken * token)
{ {
DbRef *ref; DbRef *ref;
@ -555,14 +552,14 @@ UserAccessTokenSave(Db * db, UserAccessToken * token)
if (!token) if (!token)
{ {
return 0; return false;
} }
ref = DbCreate(db, 3, "tokens", "access", token->string); ref = DbCreate(db, 3, "tokens", "access", token->string);
if (!ref) if (!ref)
{ {
return 0; return false;
} }
json = DbJson(ref); json = DbJson(ref);
@ -570,9 +567,9 @@ UserAccessTokenSave(Db * db, UserAccessToken * token)
HashMapSet(json, "user", JsonValueString(token->user)); HashMapSet(json, "user", JsonValueString(token->user));
HashMapSet(json, "device", JsonValueString(token->deviceId)); HashMapSet(json, "device", JsonValueString(token->deviceId));
if (Int64Neq(token->lifetime, Int64Create(0, 0))) if (token->lifetime)
{ {
HashMapSet(json, "expires", JsonValueInteger(UInt64Add(UtilServerTs(), token->lifetime))); HashMapSet(json, "expires", JsonValueInteger(UtilTsMillis() + token->lifetime));
} }
return DbUnlock(db, ref); return DbUnlock(db, ref);
@ -592,7 +589,7 @@ UserAccessTokenFree(UserAccessToken * token)
Free(token); Free(token);
} }
int bool
UserDeleteToken(User * user, char *token) UserDeleteToken(User * user, char *token)
{ {
char *username; char *username;
@ -610,14 +607,14 @@ UserDeleteToken(User * user, char *token)
if (!user || !token) if (!user || !token)
{ {
return 0; return false;
} }
db = user->db; db = user->db;
/* First check if the token even exists */ /* First check if the token even exists */
if (!DbExists(db, 3, "tokens", "access", token)) if (!DbExists(db, 3, "tokens", "access", token))
{ {
return 0; return false;
} }
/* If it does, get it's username. */ /* If it does, get it's username. */
@ -625,7 +622,7 @@ UserDeleteToken(User * user, char *token)
if (!tokenRef) if (!tokenRef)
{ {
return 0; return false;
} }
tokenJson = DbJson(tokenRef); tokenJson = DbJson(tokenRef);
username = JsonValueAsString(HashMapGet(tokenJson, "user")); username = JsonValueAsString(HashMapGet(tokenJson, "user"));
@ -635,7 +632,7 @@ UserDeleteToken(User * user, char *token)
{ {
/* Token does not match user, do not delete it */ /* Token does not match user, do not delete it */
DbUnlock(db, tokenRef); DbUnlock(db, tokenRef);
return 0; return false;
} }
userJson = DbJson(user->ref); userJson = DbJson(user->ref);
@ -643,7 +640,7 @@ UserDeleteToken(User * user, char *token)
if (!deviceObj) if (!deviceObj)
{ {
return 0; return false;
} }
/* Delete refresh token, if present */ /* Delete refresh token, if present */
@ -657,17 +654,17 @@ UserDeleteToken(User * user, char *token)
deletedVal = HashMapDelete(deviceObj, deviceId); deletedVal = HashMapDelete(deviceObj, deviceId);
if (!deletedVal) if (!deletedVal)
{ {
return 0; return false;
} }
JsonValueFree(deletedVal); JsonValueFree(deletedVal);
/* Delete the access token. */ /* Delete the access token. */
if (!DbUnlock(db, tokenRef) || !DbDelete(db, 3, "tokens", "access", token)) if (!DbUnlock(db, tokenRef) || !DbDelete(db, 3, "tokens", "access", token))
{ {
return 0; return false;
} }
return 1; return true;
} }
char * char *
@ -699,7 +696,7 @@ UserSetProfile(User * user, char *name, char *val)
JsonValueFree(JsonSet(json, JsonValueString(val), 2, "profile", name)); JsonValueFree(JsonSet(json, JsonValueString(val), 2, "profile", name));
} }
int bool
UserDeleteTokens(User * user, char *exempt) UserDeleteTokens(User * user, char *exempt)
{ {
HashMap *devices; HashMap *devices;
@ -708,13 +705,13 @@ UserDeleteTokens(User * user, char *exempt)
if (!user) if (!user)
{ {
return 0; return false;
} }
devices = JsonValueAsObject(HashMapGet(DbJson(user->ref), "devices")); devices = JsonValueAsObject(HashMapGet(DbJson(user->ref), "devices"));
if (!devices) if (!devices)
{ {
return 0; return false;
} }
while (HashMapIterate(devices, &deviceId, (void **) &deviceObj)) while (HashMapIterate(devices, &deviceId, (void **) &deviceObj))
@ -741,7 +738,7 @@ UserDeleteTokens(User * user, char *exempt)
JsonValueFree(HashMapDelete(devices, deviceId)); JsonValueFree(HashMapDelete(devices, deviceId));
} }
return 1; return true;
} }
int int
@ -755,30 +752,30 @@ UserGetPrivileges(User * user)
return UserDecodePrivileges(JsonValueAsArray(HashMapGet(DbJson(user->ref), "privileges"))); return UserDecodePrivileges(JsonValueAsArray(HashMapGet(DbJson(user->ref), "privileges")));
} }
int bool
UserSetPrivileges(User * user, int privileges) UserSetPrivileges(User * user, int privileges)
{ {
JsonValue *val; JsonValue *val;
if (!user) if (!user)
{ {
return 0; return false;
} }
if (!privileges) if (!privileges)
{ {
JsonValueFree(HashMapDelete(DbJson(user->ref), "privileges")); JsonValueFree(HashMapDelete(DbJson(user->ref), "privileges"));
return 1; return true;
} }
val = JsonValueArray(UserEncodePrivileges(privileges)); val = JsonValueArray(UserEncodePrivileges(privileges));
if (!val) if (!val)
{ {
return 0; return false;
} }
JsonValueFree(HashMapSet(DbJson(user->ref), "privileges", val)); JsonValueFree(HashMapSet(DbJson(user->ref), "privileges", val));
return 1; return true;
} }
int int

View file

@ -25,6 +25,8 @@
#ifndef TELODENDRIA_PARSER_H #ifndef TELODENDRIA_PARSER_H
#define TELODENDRIA_PARSER_H #define TELODENDRIA_PARSER_H
#include <stdbool.h>
/*** /***
* @Nm Parser * @Nm Parser
* @Nd Functions for dealing with grammars found in Matrix * @Nd Functions for dealing with grammars found in Matrix
@ -58,17 +60,17 @@ typedef struct CommonID {
* Parses a common identifier, as per the Common Identifier Format as defined * Parses a common identifier, as per the Common Identifier Format as defined
* by the [matrix] specification. * by the [matrix] specification.
*/ */
extern int ParseCommonID(char *, CommonID *); extern bool ParseCommonID(char *, CommonID *);
/** /**
* Parses the server part in a common identifier. * Parses the server part in a common identifier.
*/ */
extern int ParseServerPart(char *, ServerPart *); extern bool ParseServerPart(char *, ServerPart *);
/** /**
* Checks whenever the string is a valid common ID with the correct sigil. * Checks whenever the string is a valid common ID with the correct sigil.
*/ */
extern int ValidCommonID(char *, char); extern bool ValidCommonID(char *, char);
/** /**
* Frees a CommonID's values. Note that it doesn't free the CommonID itself. * Frees a CommonID's values. Note that it doesn't free the CommonID itself.
@ -100,7 +102,7 @@ extern char * ParserRecomposeServerPart(ServerPart);
/** /**
* Compares whenever a ServerName is equivalent to a server name string. * Compares whenever a ServerName is equivalent to a server name string.
*/ */
extern int ParserServerNameEquals(ServerPart, char *); extern bool ParserServerNameEquals(ServerPart, char *);
#endif /* TELODENDRIA_PARSER_H */ #endif /* TELODENDRIA_PARSER_H */

View file

@ -41,7 +41,6 @@
*/ */
#include <Cytoplasm/Db.h> #include <Cytoplasm/Db.h>
#include <Cytoplasm/Int64.h>
#include <Schema/RegToken.h> #include <Schema/RegToken.h>
@ -78,7 +77,7 @@ extern RegTokenInfo * RegTokenGetInfo(Db *, char *);
* structure will be returned. Otherwise, NULL will be returned. * structure will be returned. Otherwise, NULL will be returned.
*/ */
extern RegTokenInfo * extern RegTokenInfo *
RegTokenCreate(Db *, char *, char *, UInt64, Int64, int); RegTokenCreate(Db *, char *, char *, uint64_t, int64_t, int);
/** /**
* Free the memory associated with the registration token. This should * Free the memory associated with the registration token. This should

View file

@ -39,12 +39,13 @@
* users, among many other tasks. * users, among many other tasks.
*/ */
#include <Cytoplasm/Int64.h>
#include <Cytoplasm/Db.h> #include <Cytoplasm/Db.h>
#include <Cytoplasm/Json.h> #include <Cytoplasm/Json.h>
#include <Parser.h> #include <Parser.h>
#include <stdbool.h>
/** /**
* Many functions here operate on an opaque user structure. * Many functions here operate on an opaque user structure.
*/ */
@ -77,7 +78,7 @@ typedef struct UserAccessToken
char *user; char *user;
char *string; char *string;
char *deviceId; char *deviceId;
Int64 lifetime; uint64_t lifetime;
} UserAccessToken; } UserAccessToken;
/** /**
@ -98,7 +99,7 @@ typedef struct UserLoginInfo
* the local part is allowed to be. This function is used to ensure * the local part is allowed to be. This function is used to ensure
* that client-provided Matrix IDs are valid on this server. * that client-provided Matrix IDs are valid on this server.
*/ */
extern int UserValidate(char *, char *); extern bool UserValidate(char *, char *);
/** /**
* This function behaves just like * This function behaves just like
@ -109,13 +110,13 @@ extern int UserValidate(char *, char *);
* spec compliant but remain in use since before the new restrictions * spec compliant but remain in use since before the new restrictions
* were put in place. * were put in place.
*/ */
extern int UserHistoricalValidate(char *, char *); extern bool UserHistoricalValidate(char *, char *);
/** /**
* Determine whether the user identified by the specified localpart * Determine whether the user identified by the specified localpart
* exists in the database. * exists in the database.
*/ */
extern int UserExists(Db *, char *); extern bool UserExists(Db *, char *);
/** /**
* Create a new user with the specified localpart and password, in * Create a new user with the specified localpart and password, in
@ -146,7 +147,7 @@ extern User * UserAuthenticate(Db *, char *);
* .Fn DbUnlock * .Fn DbUnlock
* under the hood. * under the hood.
*/ */
extern int UserUnlock(User *); extern bool UserUnlock(User *);
/** /**
* Log in a user. This function takes the user's password, desired * Log in a user. This function takes the user's password, desired
@ -179,13 +180,13 @@ extern char * UserGetDeviceId(User *);
* does not store passwords in plain text, so this function hashes the * does not store passwords in plain text, so this function hashes the
* password and checks it against what is stored in the database. * password and checks it against what is stored in the database.
*/ */
extern int UserCheckPassword(User *, char *); extern bool UserCheckPassword(User *, char *);
/** /**
* Reset the given user's password by hashing a plain text password and * Reset the given user's password by hashing a plain text password and
* storing it in the database. * storing it in the database.
*/ */
extern int UserSetPassword(User *, char *); extern bool UserSetPassword(User *, char *);
/** /**
* Immediately deactivate the given user account such that it can no * Immediately deactivate the given user account such that it can no
@ -198,21 +199,21 @@ extern int UserSetPassword(User *, char *);
* responsible for deactivating the target user is NULL, then it is * responsible for deactivating the target user is NULL, then it is
* set to the target's own name. * set to the target's own name.
*/ */
extern int UserDeactivate(User *, char *, char *); extern bool UserDeactivate(User *, char *, char *);
/** /**
* Reactivates the given user account if it has been deactvated with * Reactivates the given user account if it has been deactvated with
* .Fn UserDeactivate , * .Fn UserDeactivate ,
* otherwise, it simply doesn't do anything. * otherwise, it simply doesn't do anything.
*/ */
extern int UserReactivate(User *); extern bool UserReactivate(User *);
/** /**
* Return a boolean value indicating whether or not the user was * Return a boolean value indicating whether or not the user was
* deactivated using * deactivated using
* .Fn UserDeactivate . * .Fn UserDeactivate .
*/ */
extern int UserDeactivated(User *); extern bool UserDeactivated(User *);
/** /**
* Fetches the devices that belong to the user, in JSON format, * Fetches the devices that belong to the user, in JSON format,
@ -233,7 +234,7 @@ extern UserAccessToken * UserAccessTokenGenerate(User *, char *, int);
* Write the specified access token to the database, returning a * Write the specified access token to the database, returning a
* boolean value indicating success. * boolean value indicating success.
*/ */
extern int UserAccessTokenSave(Db *, UserAccessToken *); extern bool UserAccessTokenSave(Db *, UserAccessToken *);
/** /**
* Free the memory associated with the given access token. * Free the memory associated with the given access token.
@ -243,7 +244,7 @@ extern void UserAccessTokenFree(UserAccessToken *);
/** /**
* Delete a specific access token by name. * Delete a specific access token by name.
*/ */
extern int UserDeleteToken(User *, char *); extern bool UserDeleteToken(User *, char *);
/** /**
* Get a string property from the user's profile given the specified * Get a string property from the user's profile given the specified
@ -262,7 +263,7 @@ extern void UserSetProfile(User *, char *, char *);
* except for the one provided by name, unless NULL is provided for * except for the one provided by name, unless NULL is provided for
* the name. * the name.
*/ */
extern int UserDeleteTokens(User *, char *); extern bool UserDeleteTokens(User *, char *);
/** /**
* Get the current privileges of the user as a packed bit field. Use * Get the current privileges of the user as a packed bit field. Use
@ -274,7 +275,7 @@ extern int UserGetPrivileges(User *);
/** /**
* Set the privileges of the user. * Set the privileges of the user.
*/ */
extern int UserSetPrivileges(User *, int); extern bool UserSetPrivileges(User *, int);
/** /**
* Decode the JSON that represents the user privileges into a packed * Decode the JSON that represents the user privileges into a packed

View file

@ -70,41 +70,17 @@ query(char *select, HashMap * json, int canonical)
{ {
if (StrEquals(keyName + 1, "length")) if (StrEquals(keyName + 1, "length"))
{ {
UInt64 len; uint64_t len;
switch (JsonValueType(val)) switch (JsonValueType(val))
{ {
case JSON_ARRAY: case JSON_ARRAY:
if (sizeof(size_t) == sizeof(UInt64)) len = ArraySize(JsonValueAsArray(val));
{
size_t slen = ArraySize(JsonValueAsArray(val));
UInt32 high = slen >> 32;
UInt32 low = slen;
len = UInt64Create(high, low);
}
else
{
len = UInt64Create(0, ArraySize(JsonValueAsArray(val)));
}
val = JsonValueInteger(len); val = JsonValueInteger(len);
ArrayAdd(cleanUp, val); ArrayAdd(cleanUp, val);
break; break;
case JSON_STRING: case JSON_STRING:
if (sizeof(size_t) == sizeof(UInt64)) len = strlen(JsonValueAsString(val));
{
size_t slen = strlen(JsonValueAsString(val));
UInt32 high = slen >> 32;
UInt32 low = slen;
len = UInt64Create(high, low);
}
else
{
len = UInt64Create(0, strlen(JsonValueAsString(val)));
}
val = JsonValueInteger(len); val = JsonValueInteger(len);
ArrayAdd(cleanUp, val); ArrayAdd(cleanUp, val);
break; break;