diff --git a/src/Parsee/Config.c b/src/Parsee/Config.c index 8f6bb3d..442c2c0 100644 --- a/src/Parsee/Config.c +++ b/src/Parsee/Config.c @@ -2,10 +2,114 @@ #include #include +#include #include +#include + +#include +#include static ParseeConfig *config = NULL; +static char * +GetLine(void) +{ + Stream *input = StreamStdin(); + char *out = NULL; + size_t length; + UtilGetLine(&out, &length, input); + + if (out) + { + char *line = strchr(out, '\n'); + if (line) + { + *line = '\0'; + } + } + + return out; +} + +#include +static char * +PromptString(const char *expression, const char *def, ...) +{ + Stream *output = StreamStdout(); + char *out = NULL; + va_list ap; + + while (!out) + { + va_start(ap, def); + + StreamVprintf(output, expression, ap); + if (def) + { + StreamPrintf(output, " [%s]", def); + } + StreamPrintf(output, ": "); + StreamFlush(output); + + va_end(ap); + + out = GetLine(); + if (!*out) + { + Free(out); + out = NULL; + if (def) + { + return StrDuplicate(def); + } + } + Log(LOG_INFO, "R=%s", out); + } + + return out; +} +static int +PromptInteger(const char *expression, int def, ...) +{ + Stream *output = StreamStdout(); + char *out; + long l; + va_list ap; + + va_start(ap, def); + + StreamVprintf(output, expression, ap); + if (def >= 0) + { + StreamPrintf(output, " [%d]", def); + } + StreamPrintf(output, ": "); + StreamFlush(output); + + va_end(ap); + while (true) + { + char *inval; + out = GetLine(); + l = strtol(out, &inval, 10); + Free(out); + + /* Not a use-after-free, as we reference only the addresses. */ + if (l != 0 || inval != out) + { + break; + } + + if (def >= 0) + { + return def; + } + } + + return l; +} + +/* TODO: Memleaks, galore! */ void ParseeConfigInit(void) { @@ -15,17 +119,72 @@ ParseeConfigInit(void) { return; } + + /* TODO: Give the user an achievement at the end, just because they're + * cool. */ + Log(LOG_NOTICE, "It seems like it is the first time you have configured "); + Log(LOG_NOTICE, "Parsee."); + Log(LOG_NOTICE, "As such, I need to ask you a couple of questions before "); + Log(LOG_NOTICE, "being able to use it."); + Log(LOG_NOTICE, "(don't worry; it won't take too long.)"); + Log(LOG_NOTICE, ""); + Log(LOG_NOTICE, ""); + config = Malloc(sizeof(*config)); config->as_token = StrRandom(32); config->hs_token = StrRandom(32); - config->sender_localpart = StrDuplicate("_parsee_bridge"); - config->namespace_base = StrDuplicate("_parsee_j"); - config->listen_as = StrDuplicate("localhost"); - config->port = 7642; /* proposed by Saint */ - config->component_port = 0; - config->component_host = NULL; - config->shared_comp_secret = NULL; + /* TODO: This is NOT user friendly, and I know it! */ + config->sender_localpart = PromptString( + "Name of the bridge bot, used for commands and bridged rooms", + "_parsee_bridge" + ); + config->namespace_base = PromptString( + "Base namespace for Parsee (so foo@bar.com => @[NS]_foo=40bar.com)", + "_jabber" + ); + + config->listen_as = StrDuplicate("localhost"); + config->port = PromptInteger( + "Matrix port for the AS service to use", + 7642 /* proposed by Saint */ + ); + + + config->component_host = PromptString( + "XMPP component to be used for the configuration", + NULL + ); + config->component_port = PromptInteger( + "XMPP port for to use for '%s'", + 5347, config->component_host + ); + config->shared_comp_secret = PromptString( + "%s's shared secret", + NULL, config->component_host + ); + + config->homeserver_host = PromptString( + "Delegated homeserver to be used for the configuration", + NULL + ); + config->homeserver_port = PromptInteger( + "HTTP port for to use for '%s'", + 443, config->homeserver_host + ); + + config->db_path = PromptString( + "Base directory for Parsee data", + NULL + ); + config->media_base = PromptString( + "Base media URL for bridged media", + NULL + ); + Log(LOG_NOTICE, "Done! Please look over to the parsee.yaml file, "); + Log(LOG_NOTICE, "and follow the instructions listed in it. Then, "); + Log(LOG_NOTICE, "restart Parsee. "); + Log(LOG_NOTICE, "------------------------------------------------"); stream = StreamOpen("parsee.json", "w"); json = HashMapCreate(); @@ -37,8 +196,16 @@ ParseeConfigInit(void) HashMapSet(json, "listen_as", JsonValueString(config->listen_as)); HashMapSet(json, "port", JsonValueInteger(config->port)); + HashMapSet(json, "hs_host", JsonValueString(config->homeserver_host)); + HashMapSet(json, "hs_port", JsonValueInteger(config->homeserver_port)); + + HashMapSet(json, "component_host", JsonValueString(config->component_host)); + HashMapSet(json, "component_port", JsonValueInteger(config->component_port)); + HashMapSet(json, "shared_comp_secret", JsonValueString(config->shared_comp_secret)); + HashMapSet(json, "db", JsonValueString(config->db_path)); + JsonEncode(json, stream, JSON_PRETTY); - HashMapFree(json); + JsonFree(json); StreamClose(stream); } void @@ -51,6 +218,10 @@ ParseeConfigLoad(char *conf) return; } stream = StreamOpen("parsee.json", "r"); + if (!stream) + { + return; + } json = JsonDecode(stream); config = Malloc(sizeof(*config)); diff --git a/src/XMPPThread.c b/src/XMPPThread.c index 64a4b32..ed7ba51 100644 --- a/src/XMPPThread.c +++ b/src/XMPPThread.c @@ -1150,6 +1150,8 @@ PresenceStanza(ParseeData *args, XMLElement *stanza) } else if (StrEquals(affiliation, "member")) { + /* TODO: Reconsider setting the PL if a member, as there's no + * clear reason to do this in some cases. */ power_level = 0; } else if (StrEquals(affiliation, "outcast")) @@ -1157,7 +1159,9 @@ PresenceStanza(ParseeData *args, XMLElement *stanza) power_level = -1; } - /* Set the user's PL */ + /* Set the user's PL + * TODO: Do NOT change the PL of *real* people nilly-willy. + * In some scenarios, this is really bad behaviour. */ if (room) { HashMap *powers = ASGetPL(args->config, room);