forked from Telodendria/Telodendria
Make Telodendria compatible with latest Cytoplasm.
This also brings Telodendria to C99 compliance.
This commit is contained in:
parent
f2a4a64b27
commit
e62389aa14
13 changed files with 175 additions and 207 deletions
21
src/Config.c
21
src/Config.c
|
@ -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);
|
||||||
|
|
||||||
|
|
11
src/Main.c
11
src/Main.c
|
@ -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;
|
||||||
|
|
101
src/Parser.c
101
src/Parser.c
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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>");
|
||||||
|
|
|
@ -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);
|
||||||
|
|
119
src/User.c
119
src/User.c
|
@ -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
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue