diff --git a/src/User.c b/src/User.c index 9e36239..2777d79 100644 --- a/src/User.c +++ b/src/User.c @@ -31,6 +31,10 @@ #include #include +#include + +#include + #include struct User @@ -882,51 +886,88 @@ finish: return arr; } +static int +UserIdParseLocal(Parser *p, char **ret) +{ + int c; + if (!p || !ret) + { + return 0; + } + + ParserStartCopy(p); + /* Always assume the general case here: every ASCII char, + * minus ':'. */ + while (isascii((c = ParserGetc(p))) && c != ':') + { + /* Do nothing. */ + } + if (c != EOF) + { + ParserUndo(p); + } + *ret = ParserEndCopy(p); + return 1; +} +static int +UserIdParseServer(Parser *p, char **ret) +{ + int c; + if (!p || !ret) + { + return 0; + } + + ParserStartCopy(p); + /* Allow *every* ASCII character. */ + while (isascii((c = ParserGetc(p)))) + { + /* Do nothing. */ + } + if (c != EOF) + { + ParserUndo(p); + } + *ret = ParserEndCopy(p); + return 1; +} + UserId * UserIdParse(char *id, char *defaultServer) { UserId *userId; + Parser *p; if (!id) { return NULL; } - id = StrDuplicate(id); - if (!id) - { - return NULL; - } - + p = ParserCreate(id); userId = Malloc(sizeof(UserId)); + userId->localpart = NULL; + userId->server = NULL; + if (!userId) { goto finish; } - /* Fully-qualified user ID */ - if (*id == '@') + /* Fully-qualified user ID. + * TODO: Generalise this for parsing namespaced IDs, + * like room aliases and IDs. */ + if (ParserExcept(p, '@')) { - char *localStart = id + 1; - char *serverStart = localStart; - - while (*serverStart != ':' && *serverStart != '\0') - { - serverStart++; - } - - if (*serverStart == '\0') + if (!UserIdParseLocal(p, &userId->localpart) || + !ParserExcept(p, ':') || + !UserIdParseServer(p, &userId->server)) { + if (userId->localpart) + { + Free(userId->localpart); + } Free(userId); - userId = NULL; - goto finish; } - - *serverStart = '\0'; - serverStart++; - - userId->localpart = StrDuplicate(localStart); - userId->server = StrDuplicate(serverStart); } else { @@ -942,7 +983,7 @@ UserIdParse(char *id, char *defaultServer) } finish: - Free(id); + ParserEnd(p); return userId; }