mirror of
https://forge.fsky.io/lda/Parsee.git
synced 2026-03-13 13:45:10 +00:00
[FIX/WIP] Plumbing, -Werror, death to hitmen
Suspend killers are now no more. Except the actual killers to be gone eventually. Plumbing is also very basic as of now, but it "works".
This commit is contained in:
parent
1f658ece76
commit
bb836789b2
23 changed files with 310 additions and 165 deletions
4
Makefile
4
Makefile
|
|
@ -19,8 +19,8 @@ SOURCE=src
|
||||||
OBJECT=build
|
OBJECT=build
|
||||||
INCLUDES=src/include
|
INCLUDES=src/include
|
||||||
CC=cc
|
CC=cc
|
||||||
CFLAGS=-I$(INCLUDES) -I$(CYTO_INC) -DNAME="\"$(NAME)\"" -DVERSION="\"$(VERSION)\"" -DREPOSITORY=\"$(REPOSITORY)\" -O3
|
CFLAGS=-I$(INCLUDES) -I$(CYTO_INC) -DNAME="\"$(NAME)\"" -DVERSION="\"$(VERSION)\"" -DREPOSITORY=\"$(REPOSITORY)\" -O3 -g -ggdb -Wall -Werror
|
||||||
LDFLAGS=-L $(CYTO_LIB) -lCytoplasm -Wl,--export-dynamic -O3
|
LDFLAGS=-L $(CYTO_LIB) -lCytoplasm -Wl,--export-dynamic -O3 -g -ggdb
|
||||||
BINARY=parsee
|
BINARY=parsee
|
||||||
# ============================ Compilation =================================
|
# ============================ Compilation =================================
|
||||||
SRC_FILES:=$(shell find $(SOURCE) -name '*.c')
|
SRC_FILES:=$(shell find $(SOURCE) -name '*.c')
|
||||||
|
|
|
||||||
|
|
@ -42,8 +42,11 @@ TODO
|
||||||
- Look at XEPS-TBD.TXT for XEPs to be done
|
- Look at XEPS-TBD.TXT for XEPs to be done
|
||||||
- Achievements
|
- Achievements
|
||||||
### Why?
|
### Why?
|
||||||
> "[...] and it [BoVeX] has an achievement system, because another thing I don't like is when software will not acknowledge that you've reached an obscure error state, essentially outsmarting it."
|
> "[...] and it [BoVeX] has an achievement system, because another thing I don't like is
|
||||||
- Tom Murphy VII
|
> when software will not acknowledge that you've reached an obscure error state, essentially
|
||||||
|
> outsmarting it."
|
||||||
|
|
||||||
|
- [Tom Murphy VII](https://tom7.org)
|
||||||
|
|
||||||
## DONATING/CONTRIBUTING
|
## DONATING/CONTRIBUTING
|
||||||
If you know things about XMPP or Matrix, yet aren't familiar with C99, or just
|
If you know things about XMPP or Matrix, yet aren't familiar with C99, or just
|
||||||
|
|
|
||||||
42
src/AS.c
42
src/AS.c
|
|
@ -222,19 +222,33 @@ ASKick(const ParseeConfig *conf, char *id, char *banned)
|
||||||
HttpClientContextFree(ctx);
|
HttpClientContextFree(ctx);
|
||||||
JsonFree(json);
|
JsonFree(json);
|
||||||
}
|
}
|
||||||
void
|
char *
|
||||||
ASJoin(const ParseeConfig *conf, char *id, char *masquerade)
|
ASJoin(const ParseeConfig *conf, char *id, char *masquerade)
|
||||||
{
|
{
|
||||||
HttpClientContext *ctx = NULL;
|
HttpClientContext *ctx = NULL;
|
||||||
HashMap *json = NULL;
|
HashMap *json = NULL;
|
||||||
char *path;
|
char *path, *ret;
|
||||||
if (!conf || !id || !masquerade)
|
if (!conf || !id)
|
||||||
{
|
{
|
||||||
return;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!masquerade)
|
||||||
|
{
|
||||||
|
char *raw = StrConcat(4,
|
||||||
|
"@", conf->sender_localpart,
|
||||||
|
":", conf->homeserver_host
|
||||||
|
);
|
||||||
|
masquerade = HttpUrlEncode(raw);
|
||||||
|
Free(raw);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
masquerade = HttpUrlEncode(masquerade);
|
||||||
|
}
|
||||||
|
id = HttpUrlEncode(id);
|
||||||
path = StrConcat(5,
|
path = StrConcat(5,
|
||||||
"/_matrix/client/v3/rooms/", id, "/join?",
|
"/_matrix/client/v3/join/", id, "?",
|
||||||
"user_id=", masquerade
|
"user_id=", masquerade
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -246,15 +260,23 @@ ASJoin(const ParseeConfig *conf, char *id, char *masquerade)
|
||||||
json = HashMapCreate();
|
json = HashMapCreate();
|
||||||
ASAuthenticateRequest(conf, ctx);
|
ASAuthenticateRequest(conf, ctx);
|
||||||
ParseeSetRequestJSON(ctx, json);
|
ParseeSetRequestJSON(ctx, json);
|
||||||
|
JsonFree(json);
|
||||||
|
|
||||||
|
json = JsonDecode(HttpClientStream(ctx));
|
||||||
|
ret = StrDuplicate(GrabString(json, 1, "room_id"));
|
||||||
|
JsonFree(json);
|
||||||
|
|
||||||
HttpClientContextFree(ctx);
|
HttpClientContextFree(ctx);
|
||||||
JsonFree(json);
|
Free(masquerade);
|
||||||
|
Free(id);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
void
|
void
|
||||||
ASSetState(const ParseeConfig *conf, char *id, char *type, char *key, char *mask, HashMap *state)
|
ASSetState(const ParseeConfig *conf, char *id, char *type, char *key, char *mask, HashMap *state)
|
||||||
{
|
{
|
||||||
HttpClientContext *ctx = NULL;
|
HttpClientContext *ctx = NULL;
|
||||||
char *path, *params;
|
char *path;
|
||||||
if (!conf || !id || !type || !mask || !state)
|
if (!conf || !id || !type || !mask || !state)
|
||||||
{
|
{
|
||||||
JsonFree(state);
|
JsonFree(state);
|
||||||
|
|
@ -278,7 +300,7 @@ char *
|
||||||
ASSend(const ParseeConfig *conf, char *id, char *user, char *type, HashMap *c)
|
ASSend(const ParseeConfig *conf, char *id, char *user, char *type, HashMap *c)
|
||||||
{
|
{
|
||||||
HttpClientContext *ctx = NULL;
|
HttpClientContext *ctx = NULL;
|
||||||
char *path, *params;
|
char *path;
|
||||||
char *txn, *ret;
|
char *txn, *ret;
|
||||||
HashMap *reply;
|
HashMap *reply;
|
||||||
if (!conf || !id || !type || !user || !c)
|
if (!conf || !id || !type || !user || !c)
|
||||||
|
|
@ -626,7 +648,6 @@ ASReupload(const ParseeConfig *c, char *from, char **mime)
|
||||||
HttpClientContext *ctx;
|
HttpClientContext *ctx;
|
||||||
unsigned short port;
|
unsigned short port;
|
||||||
int size = 0, flags = HTTP_FLAG_NONE;
|
int size = 0, flags = HTTP_FLAG_NONE;
|
||||||
int i;
|
|
||||||
char *ret, *content_len;
|
char *ret, *content_len;
|
||||||
|
|
||||||
if (!c || !from)
|
if (!c || !from)
|
||||||
|
|
@ -685,7 +706,7 @@ ASType(const ParseeConfig *c, char *user, char *room, bool status)
|
||||||
{
|
{
|
||||||
HttpClientContext *ctx = NULL;
|
HttpClientContext *ctx = NULL;
|
||||||
HashMap *json;
|
HashMap *json;
|
||||||
char *path, *full;
|
char *path;
|
||||||
if (!c || !user || !room)
|
if (!c || !user || !room)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
|
@ -760,7 +781,6 @@ ASSetUserConfig(const ParseeConfig *c, char *user, char *key, HashMap *map)
|
||||||
{
|
{
|
||||||
|
|
||||||
HttpClientContext *ctx = NULL;
|
HttpClientContext *ctx = NULL;
|
||||||
HashMap *json;
|
|
||||||
char *path;
|
char *path;
|
||||||
if (!c || !key || !map)
|
if (!c || !key || !map)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
#include <Cytoplasm/Str.h>
|
#include <Cytoplasm/Str.h>
|
||||||
|
|
||||||
#include <Matrix.h>
|
#include <Matrix.h>
|
||||||
|
#include <Bot.h>
|
||||||
#include <AS.h>
|
#include <AS.h>
|
||||||
|
|
||||||
CommandHead(CmdBanUser, cmd, argp)
|
CommandHead(CmdBanUser, cmd, argp)
|
||||||
|
|
@ -13,32 +14,21 @@ CommandHead(CmdBanUser, cmd, argp)
|
||||||
HashMap *event = args->event;
|
HashMap *event = args->event;
|
||||||
char *user = HashMapGet(cmd->arguments, "user");
|
char *user = HashMapGet(cmd->arguments, "user");
|
||||||
char *room = HashMapGet(cmd->arguments, "room");
|
char *room = HashMapGet(cmd->arguments, "room");
|
||||||
char *msg;
|
|
||||||
char *msgtype = GrabString(event, 2, "content", "msgtype");
|
BotInitialise();
|
||||||
char *body = GrabString(event, 2, "content", "body");
|
|
||||||
char *id = GrabString(event, 1, "room_id");
|
|
||||||
char *ev_id = GrabString(event, 1, "event_id");
|
|
||||||
char *sender = GrabString(event, 1, "sender");
|
|
||||||
char *profile = StrConcat(4,
|
|
||||||
"@", data->config->sender_localpart,
|
|
||||||
":", data->config->homeserver_host
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!user || !room)
|
if (!user || !room)
|
||||||
{
|
{
|
||||||
Free(profile);
|
BotDestroy();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ASBan(data->config, room, user);
|
ASBan(data->config, room, user);
|
||||||
|
|
||||||
msg = StrConcat(3, "Banning '", user, "'...");
|
ReplySprintf("Banning %s from '%s'...",
|
||||||
Free(ASSend(
|
user, room
|
||||||
data->config, id, profile,
|
);
|
||||||
"m.room.message",
|
|
||||||
MatrixCreateNotice(msg)
|
BotDestroy();
|
||||||
));
|
|
||||||
Free(msg);
|
|
||||||
Free(profile);
|
|
||||||
}
|
}
|
||||||
CommandHead(CmdNoFlyList, cmd, argp)
|
CommandHead(CmdNoFlyList, cmd, argp)
|
||||||
{
|
{
|
||||||
|
|
@ -46,30 +36,19 @@ CommandHead(CmdNoFlyList, cmd, argp)
|
||||||
ParseeData *data = args->data;
|
ParseeData *data = args->data;
|
||||||
HashMap *event = args->event;
|
HashMap *event = args->event;
|
||||||
char *user = HashMapGet(cmd->arguments, "user");
|
char *user = HashMapGet(cmd->arguments, "user");
|
||||||
char *msg;
|
char *reason = HashMapGet(cmd->arguments, "reason");
|
||||||
char *msgtype = GrabString(event, 2, "content", "msgtype");
|
BotInitialise();
|
||||||
char *body = GrabString(event, 2, "content", "body");
|
|
||||||
char *id = GrabString(event, 1, "room_id");
|
|
||||||
char *ev_id = GrabString(event, 1, "event_id");
|
|
||||||
char *sender = GrabString(event, 1, "sender");
|
|
||||||
char *profile = StrConcat(4,
|
|
||||||
"@", data->config->sender_localpart,
|
|
||||||
":", data->config->homeserver_host
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!user)
|
if (!user)
|
||||||
{
|
{
|
||||||
Free(profile);
|
BotDestroy();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
msg = StrConcat(3, "Banning '", user, "'...");
|
ReplySprintf("Banning %s for '%s'",
|
||||||
Free(ASSend(
|
user, reason ? reason : "[no reason specified]"
|
||||||
data->config, id, profile,
|
);
|
||||||
"m.room.message",
|
ParseeGlobalBan(data, user, reason);
|
||||||
MatrixCreateNotice(msg)
|
|
||||||
));
|
BotDestroy();
|
||||||
Free(msg);
|
|
||||||
ParseeGlobalBan(data, user);
|
|
||||||
Free(profile);
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ CommandHead(CmdHelp, cmd, argp)
|
||||||
{
|
{
|
||||||
ParseeCmdArg *args = argp;
|
ParseeCmdArg *args = argp;
|
||||||
ParseeData *data = args->data;
|
ParseeData *data = args->data;
|
||||||
HashMap *json, *event = args->event;
|
HashMap *event = args->event;
|
||||||
BotInitialise();
|
BotInitialise();
|
||||||
|
|
||||||
ReplyBasic("Commands: ");
|
ReplyBasic("Commands: ");
|
||||||
|
|
|
||||||
89
src/Commands/Plumb.c
Normal file
89
src/Commands/Plumb.c
Normal file
|
|
@ -0,0 +1,89 @@
|
||||||
|
#include <Routes.h>
|
||||||
|
|
||||||
|
#include <Cytoplasm/Memory.h>
|
||||||
|
#include <Cytoplasm/Str.h>
|
||||||
|
|
||||||
|
#include <Matrix.h>
|
||||||
|
#include <Bot.h>
|
||||||
|
#include <AS.h>
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
CommandHead(CmdPlumb, cmd, argp)
|
||||||
|
{
|
||||||
|
ParseeCmdArg *args = argp;
|
||||||
|
ParseeData *data = args->data;
|
||||||
|
HashMap *event = args->event;
|
||||||
|
char *muc = NULL, *room = NULL, *chat_id = NULL;
|
||||||
|
char *room_id = NULL;
|
||||||
|
MUCInfo info = { .exists = false };
|
||||||
|
|
||||||
|
BotInitialise();
|
||||||
|
|
||||||
|
BotRequired(muc);
|
||||||
|
BotRequired(room);
|
||||||
|
|
||||||
|
/* Check MUC viability */
|
||||||
|
Log(LOG_INFO, "BAR1");
|
||||||
|
if (ParseeManageBan(args->data, muc, NULL))
|
||||||
|
{
|
||||||
|
ReplySprintf("MUC '%s' is not allowed on this bridge.", muc);
|
||||||
|
Log(LOG_INFO, "BAR1F");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
Log(LOG_INFO, "BAR2");
|
||||||
|
if (!XMPPQueryMUC(args->data->jabber, muc, &info))
|
||||||
|
{
|
||||||
|
ReplySprintf("MUC '%s' does not exist.", muc);
|
||||||
|
Log(LOG_INFO, "BAR2F");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
Log(LOG_INFO, "BAR3");
|
||||||
|
if ((chat_id = ParseeGetFromMUCID(args->data, muc)))
|
||||||
|
{
|
||||||
|
Free(chat_id);
|
||||||
|
chat_id = NULL;
|
||||||
|
ReplySprintf("MUC '%s' is already mapped.", muc);
|
||||||
|
Log(LOG_INFO, "BAR3F");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
Log(LOG_INFO, "FOO");
|
||||||
|
|
||||||
|
/* Check room viability */
|
||||||
|
room_id = ASJoin(args->data->config, room, NULL);
|
||||||
|
if (!room_id)
|
||||||
|
{
|
||||||
|
ReplySprintf("Room '%s' does not exist.", room);
|
||||||
|
Log(LOG_INFO, "FOO2");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
Log(LOG_INFO, "FOO3");
|
||||||
|
if ((chat_id = ParseeGetFromRoomID(args->data, room_id)))
|
||||||
|
{
|
||||||
|
Free(chat_id);
|
||||||
|
chat_id = NULL;
|
||||||
|
ReplySprintf("Room '%s' is already mapped.", room);
|
||||||
|
Log(LOG_INFO, "FOO4");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
Log(LOG_INFO, "FOO5");
|
||||||
|
chat_id = ParseePushMUC(args->data, room_id, muc);
|
||||||
|
if (chat_id)
|
||||||
|
{
|
||||||
|
char *rev = StrConcat(2, muc, "/parsee");
|
||||||
|
XMPPJoinMUC(args->data->jabber, "parsee", rev);
|
||||||
|
|
||||||
|
Free(rev);
|
||||||
|
}
|
||||||
|
Log(LOG_INFO, "FOO6");
|
||||||
|
|
||||||
|
ReplySprintf("Plumbed '%s'", muc);
|
||||||
|
end:
|
||||||
|
Log(LOG_INFO, "End.");
|
||||||
|
BotDestroy();
|
||||||
|
Free(chat_id);
|
||||||
|
Free(room_id);
|
||||||
|
XMPPFreeMUCInfo(info);
|
||||||
|
}
|
||||||
|
|
@ -12,8 +12,7 @@ CommandHead(CmdStats, cmd, argp)
|
||||||
{
|
{
|
||||||
ParseeCmdArg *args = argp;
|
ParseeCmdArg *args = argp;
|
||||||
ParseeData *data = args->data;
|
ParseeData *data = args->data;
|
||||||
HashMap *json, *event = args->event;
|
HashMap *event = args->event;
|
||||||
char *msg;
|
|
||||||
size_t alloc = MemoryAllocated();
|
size_t alloc = MemoryAllocated();
|
||||||
size_t kb = alloc >> 10;
|
size_t kb = alloc >> 10;
|
||||||
size_t mb = kb >> 10;
|
size_t mb = kb >> 10;
|
||||||
|
|
@ -30,7 +29,7 @@ CommandHead(CmdStats, cmd, argp)
|
||||||
);
|
);
|
||||||
|
|
||||||
ReplySprintf("- Memory used: %d%s (reported by Cytoplasm)",
|
ReplySprintf("- Memory used: %d%s (reported by Cytoplasm)",
|
||||||
min, unit
|
(int) min, unit
|
||||||
);
|
);
|
||||||
ReplySprintf("- Source code and licensing information: %s",
|
ReplySprintf("- Source code and licensing information: %s",
|
||||||
REPOSITORY
|
REPOSITORY
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,6 @@ CommandHead(CmdUnlinkMUC, cmd, argp)
|
||||||
HashMap *json, *event = args->event, *mucs;
|
HashMap *json, *event = args->event, *mucs;
|
||||||
DbRef *ref;
|
DbRef *ref;
|
||||||
char *muc = NULL, *chat_id = NULL, *room = NULL;
|
char *muc = NULL, *chat_id = NULL, *room = NULL;
|
||||||
JsonValue *val;
|
|
||||||
|
|
||||||
BotInitialise();
|
BotInitialise();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,12 +20,10 @@ static HttpServer *server = NULL;
|
||||||
static pthread_t xmpp_thr;
|
static pthread_t xmpp_thr;
|
||||||
static XMPPComponent *jabber = NULL;
|
static XMPPComponent *jabber = NULL;
|
||||||
|
|
||||||
extern int ParseeFindDatastart(char *data);
|
|
||||||
int
|
int
|
||||||
Main(void)
|
Main(void)
|
||||||
{
|
{
|
||||||
HttpServerConfig conf;
|
HttpServerConfig conf;
|
||||||
ParseeData *data = NULL;
|
|
||||||
const ParseeConfig *parsee_conf;
|
const ParseeConfig *parsee_conf;
|
||||||
Stream *yaml;
|
Stream *yaml;
|
||||||
Cron *cron = NULL;
|
Cron *cron = NULL;
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ ParseeMemberHandler(ParseeData *data, HashMap *event)
|
||||||
char *jid;
|
char *jid;
|
||||||
bool direct = GrabBoolean(event, 2, "content", "is_direct");
|
bool direct = GrabBoolean(event, 2, "content", "is_direct");
|
||||||
bool bot = !strncmp(sender + 1, local, strlen(local));
|
bool bot = !strncmp(sender + 1, local, strlen(local));
|
||||||
ASJoin(conf, room_id, state_key);
|
Free(ASJoin(conf, room_id, state_key));
|
||||||
|
|
||||||
jid = ParseeDecodeLocalJID(conf, state_key);
|
jid = ParseeDecodeLocalJID(conf, state_key);
|
||||||
|
|
||||||
|
|
@ -70,7 +70,6 @@ ParseeBotHandler(ParseeData *data, HashMap *event)
|
||||||
char *msgtype = GrabString(event, 2, "content", "msgtype");
|
char *msgtype = GrabString(event, 2, "content", "msgtype");
|
||||||
char *body = GrabString(event, 2, "content", "body");
|
char *body = GrabString(event, 2, "content", "body");
|
||||||
char *id = GrabString(event, 1, "room_id");
|
char *id = GrabString(event, 1, "room_id");
|
||||||
char *ev_id = GrabString(event, 1, "event_id");
|
|
||||||
char *sender = GrabString(event, 1, "sender");
|
char *sender = GrabString(event, 1, "sender");
|
||||||
char *profile = StrConcat(4,
|
char *profile = StrConcat(4,
|
||||||
"@", data->config->sender_localpart,
|
"@", data->config->sender_localpart,
|
||||||
|
|
@ -117,7 +116,7 @@ ParseeBotHandler(ParseeData *data, HashMap *event)
|
||||||
|
|
||||||
RouteCommand(data->handler, cmd, &arg);
|
RouteCommand(data->handler, cmd, &arg);
|
||||||
}
|
}
|
||||||
end:
|
|
||||||
Free(profile);
|
Free(profile);
|
||||||
CommandFree(cmd);
|
CommandFree(cmd);
|
||||||
}
|
}
|
||||||
|
|
@ -128,16 +127,14 @@ ParseeMessageHandler(ParseeData *data, HashMap *event)
|
||||||
DbRef *ref = NULL;
|
DbRef *ref = NULL;
|
||||||
HashMap *json;
|
HashMap *json;
|
||||||
|
|
||||||
char *msgtype = GrabString(event, 2, "content", "msgtype");
|
|
||||||
char *body = GrabString(event, 2, "content", "body");
|
char *body = GrabString(event, 2, "content", "body");
|
||||||
char *id = GrabString(event, 1, "room_id");
|
char *id = GrabString(event, 1, "room_id");
|
||||||
char *ev_id = GrabString(event, 1, "event_id");
|
char *ev_id = GrabString(event, 1, "event_id");
|
||||||
char *m_sender = GrabString(event, 1, "sender");
|
char *m_sender = GrabString(event, 1, "sender");
|
||||||
char *chat_id, *muc_id, *jid;
|
char *chat_id, *muc_id;
|
||||||
char *reply_id = MatrixGetReply(event);
|
char *reply_id = MatrixGetReply(event);
|
||||||
char *xepd = ParseeXMPPify(event);
|
char *xepd = ParseeXMPPify(event);
|
||||||
char *cmd_lp = data->config->sender_localpart;
|
char *type, *user, *xmppified_user = NULL, *to = NULL;
|
||||||
char *type, *user, *xmppified_user = NULL, *to;
|
|
||||||
char *unauth = NULL;
|
char *unauth = NULL;
|
||||||
char *origin_id = NULL, *stanza = NULL;
|
char *origin_id = NULL, *stanza = NULL;
|
||||||
char *sender = NULL;
|
char *sender = NULL;
|
||||||
|
|
@ -189,7 +186,7 @@ ParseeMessageHandler(ParseeData *data, HashMap *event)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
char *name, *rev, *stanza;
|
char *name, *rev;
|
||||||
/* Try to find the chat ID */
|
/* Try to find the chat ID */
|
||||||
muc_id = ParseeGetMUCID(data, chat_id);
|
muc_id = ParseeGetMUCID(data, chat_id);
|
||||||
if (!chat_id)
|
if (!chat_id)
|
||||||
|
|
|
||||||
|
|
@ -369,14 +369,16 @@ XMPPifyElement(HashMap *event, XMLElement *elem, XMPPFlags flags)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return xepd;
|
return xepd;
|
||||||
}
|
}
|
||||||
char *
|
char *
|
||||||
ParseeXMPPify(HashMap *event)
|
ParseeXMPPify(HashMap *event)
|
||||||
{
|
{
|
||||||
char *cntr, *type, *format, *html;
|
char *type, *format, *html;
|
||||||
char *xepd = NULL, *tmp;
|
char *xepd = NULL;
|
||||||
XMLElement *elem;
|
XMLElement *elem;
|
||||||
|
|
||||||
XMPPFlags flags;
|
XMPPFlags flags;
|
||||||
|
|
@ -756,10 +758,10 @@ end:
|
||||||
|
|
||||||
}
|
}
|
||||||
void
|
void
|
||||||
ParseeGlobalBan(ParseeData *data, char *user)
|
ParseeGlobalBan(ParseeData *data, char *user, char *reason)
|
||||||
{
|
{
|
||||||
DbRef *ref;
|
DbRef *ref;
|
||||||
HashMap *j;
|
HashMap *j, *obj;
|
||||||
if (!data || !user)
|
if (!data || !user)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
|
@ -773,7 +775,13 @@ ParseeGlobalBan(ParseeData *data, char *user)
|
||||||
|
|
||||||
j = DbJson(ref);
|
j = DbJson(ref);
|
||||||
|
|
||||||
JsonValueFree(HashMapSet(j, user, JsonValueObject(HashMapCreate())));
|
obj = HashMapCreate();
|
||||||
|
if (reason)
|
||||||
|
{
|
||||||
|
HashMapSet(obj, "reason", JsonValueString(reason));
|
||||||
|
}
|
||||||
|
HashMapSet(obj, "date", JsonValueInteger(UtilTsMillis()));
|
||||||
|
JsonValueFree(HashMapSet(j, user, JsonValueObject(obj)));
|
||||||
|
|
||||||
DbUnlock(data->db, ref);
|
DbUnlock(data->db, ref);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -529,7 +529,7 @@ ParseeSendPresence(ParseeData *data)
|
||||||
DbRef *ref;
|
DbRef *ref;
|
||||||
HashMap *j, *mucs;
|
HashMap *j, *mucs;
|
||||||
JsonValue *val;
|
JsonValue *val;
|
||||||
char *chatid = NULL, *muc;
|
char *muc;
|
||||||
if (!data)
|
if (!data)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -13,8 +13,6 @@ RouteHead(RouteUserAck, arr, argp)
|
||||||
ParseeHttpArg *args = argp;
|
ParseeHttpArg *args = argp;
|
||||||
HashMap *request = NULL;
|
HashMap *request = NULL;
|
||||||
HashMap *response = NULL;
|
HashMap *response = NULL;
|
||||||
Array *events;
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
char *user = ArrayGet(arr, 0);
|
char *user = ArrayGet(arr, 0);
|
||||||
response = ASVerifyRequest(args);
|
response = ASVerifyRequest(args);
|
||||||
|
|
@ -44,8 +42,6 @@ RouteHead(RouteRoomAck, arr, argp)
|
||||||
ParseeHttpArg *args = argp;
|
ParseeHttpArg *args = argp;
|
||||||
HashMap *request = NULL;
|
HashMap *request = NULL;
|
||||||
HashMap *response = NULL;
|
HashMap *response = NULL;
|
||||||
Array *events;
|
|
||||||
size_t i;
|
|
||||||
MUCInfo info = { .exists = false };
|
MUCInfo info = { .exists = false };
|
||||||
|
|
||||||
char *room = ArrayGet(arr, 0), *muc = NULL, *id = NULL;
|
char *room = ArrayGet(arr, 0), *muc = NULL, *id = NULL;
|
||||||
|
|
@ -119,6 +115,16 @@ RouteHead(RouteRoomAck, arr, argp)
|
||||||
/* Creates a mapping */
|
/* Creates a mapping */
|
||||||
chatid = ParseePushMUC(args->data, id, muc);
|
chatid = ParseePushMUC(args->data, id, muc);
|
||||||
|
|
||||||
|
/* Invite the Parsee listener, so that we can have some
|
||||||
|
* events right up */
|
||||||
|
{
|
||||||
|
char *rev = StrConcat(2, muc, "/parsee");
|
||||||
|
Log(LOG_NOTICE, "Sending presence to %s", rev);
|
||||||
|
XMPPJoinMUC(args->data->jabber, "parsee", rev);
|
||||||
|
|
||||||
|
Free(rev);
|
||||||
|
}
|
||||||
|
|
||||||
response = HashMapCreate();
|
response = HashMapCreate();
|
||||||
end:
|
end:
|
||||||
if (chatid)
|
if (chatid)
|
||||||
|
|
|
||||||
|
|
@ -14,10 +14,6 @@ static XMPPComponent *jabber = NULL;
|
||||||
static void
|
static void
|
||||||
SignalHandler(int signal)
|
SignalHandler(int signal)
|
||||||
{
|
{
|
||||||
size_t i;
|
|
||||||
XMLElement *message, *body, *data;
|
|
||||||
char *from;
|
|
||||||
|
|
||||||
switch (signal)
|
switch (signal)
|
||||||
{
|
{
|
||||||
case SIGPIPE:
|
case SIGPIPE:
|
||||||
|
|
@ -32,6 +28,8 @@ SignalHandler(int signal)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* Create a loopback stanza, forcing the thread to die */
|
/* Create a loopback stanza, forcing the thread to die */
|
||||||
|
|
||||||
|
/* TODO: Better way to break out. */
|
||||||
Log(LOG_INFO, "Killing thread...");
|
Log(LOG_INFO, "Killing thread...");
|
||||||
XMPPKillThread(jabber, "killer");
|
XMPPKillThread(jabber, "killer");
|
||||||
pthread_join(xmpp_thr, NULL);
|
pthread_join(xmpp_thr, NULL);
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,6 @@ struct XMLexer {
|
||||||
static bool XMLookahead(XMLexer *lexer, const char *str, bool skip);
|
static bool XMLookahead(XMLexer *lexer, const char *str, bool skip);
|
||||||
|
|
||||||
/* Parses an XML "name" */
|
/* Parses an XML "name" */
|
||||||
static bool XMLIsStart(XMLexer *lexer);
|
|
||||||
static char * XMLParseName(XMLexer *lexer);
|
static char * XMLParseName(XMLexer *lexer);
|
||||||
static bool XMLSkipSpace(XMLexer *lexer);
|
static bool XMLSkipSpace(XMLexer *lexer);
|
||||||
static char * XMLParseAttValue(XMLexer *lexer);
|
static char * XMLParseAttValue(XMLexer *lexer);
|
||||||
|
|
@ -122,11 +121,8 @@ XMLEvent *
|
||||||
XMLCrank(XMLexer *lexer)
|
XMLCrank(XMLexer *lexer)
|
||||||
{
|
{
|
||||||
XMLEvent *event = NULL;
|
XMLEvent *event = NULL;
|
||||||
char c;
|
|
||||||
int ch;
|
|
||||||
char *attrname;
|
char *attrname;
|
||||||
HashMap *props;
|
HashMap *props;
|
||||||
char *key, *val;
|
|
||||||
char cbuf[2] = { 0 };
|
char cbuf[2] = { 0 };
|
||||||
char *tmp;
|
char *tmp;
|
||||||
if (!lexer)
|
if (!lexer)
|
||||||
|
|
@ -259,6 +255,9 @@ XMLCrank(XMLexer *lexer)
|
||||||
XMLFreeEvent(event);
|
XMLFreeEvent(event);
|
||||||
event = XMLCreateEnd(lexer, attrname);
|
event = XMLCreateEnd(lexer, attrname);
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
/* TODO */
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
/* TODO: Crank our XML parser. */
|
/* TODO: Crank our XML parser. */
|
||||||
return event;
|
return event;
|
||||||
|
|
@ -608,7 +607,7 @@ static char *
|
||||||
XMLDecodeString(char *s)
|
XMLDecodeString(char *s)
|
||||||
{
|
{
|
||||||
char *ret = NULL, *tmp;
|
char *ret = NULL, *tmp;
|
||||||
char c, cs[2] = { 0 };
|
char cs[2] = { 0 };
|
||||||
|
|
||||||
while (*s)
|
while (*s)
|
||||||
{
|
{
|
||||||
|
|
@ -724,10 +723,9 @@ XMLParseAttQuote(XMLexer *lexer)
|
||||||
|
|
||||||
while ((c = XMLGetc(lexer)))
|
while ((c = XMLGetc(lexer)))
|
||||||
{
|
{
|
||||||
//Log(LOG_INFO, "E1=%c", c);
|
|
||||||
if (c == '&')
|
if (c == '&')
|
||||||
{
|
{
|
||||||
char *code = NULL;
|
//char *code = NULL;
|
||||||
int c2;
|
int c2;
|
||||||
int p2 = XMLInitialiseBuffer(lexer);
|
int p2 = XMLInitialiseBuffer(lexer);
|
||||||
int j = 0;
|
int j = 0;
|
||||||
|
|
@ -774,7 +772,6 @@ XMLParseAttDouble(XMLexer *lexer)
|
||||||
//Log(LOG_INFO, "E2=%c", c);
|
//Log(LOG_INFO, "E2=%c", c);
|
||||||
if (c == '&')
|
if (c == '&')
|
||||||
{
|
{
|
||||||
char *code = NULL;
|
|
||||||
int c2;
|
int c2;
|
||||||
int p2 = XMLInitialiseBuffer(lexer);
|
int p2 = XMLInitialiseBuffer(lexer);
|
||||||
int j = 0;
|
int j = 0;
|
||||||
|
|
@ -811,7 +808,7 @@ XMLParseAttDouble(XMLexer *lexer)
|
||||||
static char *
|
static char *
|
||||||
XMLParseAttValue(XMLexer *lexer)
|
XMLParseAttValue(XMLexer *lexer)
|
||||||
{
|
{
|
||||||
ssize_t point = XMLInitialiseBuffer(lexer);
|
XMLInitialiseBuffer(lexer);
|
||||||
|
|
||||||
if (XMLookahead(lexer, "'", true))
|
if (XMLookahead(lexer, "'", true))
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -78,6 +78,8 @@ XMPPInitialiseCompStream(char *host, int port)
|
||||||
comp->stream = stream;
|
comp->stream = stream;
|
||||||
pthread_mutex_init(&comp->write_lock, NULL);
|
pthread_mutex_init(&comp->write_lock, NULL);
|
||||||
|
|
||||||
|
(void) error;
|
||||||
|
|
||||||
return comp;
|
return comp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ XMPPQueryMUC(XMPPComponent *jabber, char *muc, MUCInfo *out)
|
||||||
char *uuid, *from;
|
char *uuid, *from;
|
||||||
if (!jabber || !muc)
|
if (!jabber || !muc)
|
||||||
{
|
{
|
||||||
|
Log(LOG_WARNING, ":(");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -32,25 +33,19 @@ XMPPQueryMUC(XMPPComponent *jabber, char *muc, MUCInfo *out)
|
||||||
|
|
||||||
XMLAddChild(iq_query, query);
|
XMLAddChild(iq_query, query);
|
||||||
Free(from);
|
Free(from);
|
||||||
Free(uuid);
|
|
||||||
|
|
||||||
/* Pause the XMPP thread */
|
|
||||||
XMPPKillThread(jabber, "suspend");
|
|
||||||
UtilSleepMillis(500);
|
|
||||||
{
|
{
|
||||||
XMLElement *identity;
|
XMLElement *identity;
|
||||||
/* -- WE ARE ON OUR OWN HERE WITH STANZAS -- */
|
|
||||||
XMLEncode(jabber->stream, iq_query);
|
XMLEncode(jabber->stream, iq_query);
|
||||||
StreamFlush(jabber->stream);
|
StreamFlush(jabber->stream);
|
||||||
XMLFreeElement(iq_query);
|
XMLFreeElement(iq_query);
|
||||||
|
|
||||||
/* Except an IQ reply */
|
/* Except an IQ reply */
|
||||||
iq_query = XMLDecode(jabber->stream, false);
|
iq_query = ParseeAwaitStanza(uuid);
|
||||||
/* TODO: I've spotted presence requests spawning there. */
|
Free(uuid);
|
||||||
if (!iq_query || !StrEquals(iq_query->name, "iq"))
|
if (!iq_query || !StrEquals(iq_query->name, "iq"))
|
||||||
{
|
{
|
||||||
XMLFreeElement(iq_query);
|
XMLFreeElement(iq_query);
|
||||||
ParseeWakeupThread();
|
|
||||||
pthread_mutex_unlock(&jabber->write_lock);
|
pthread_mutex_unlock(&jabber->write_lock);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -62,7 +57,6 @@ XMPPQueryMUC(XMPPComponent *jabber, char *muc, MUCInfo *out)
|
||||||
"conference"))
|
"conference"))
|
||||||
{
|
{
|
||||||
XMLFreeElement(iq_query);
|
XMLFreeElement(iq_query);
|
||||||
ParseeWakeupThread();
|
|
||||||
pthread_mutex_unlock(&jabber->write_lock);
|
pthread_mutex_unlock(&jabber->write_lock);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -79,9 +73,7 @@ XMPPQueryMUC(XMPPComponent *jabber, char *muc, MUCInfo *out)
|
||||||
XMLFreeElement(iq_query);
|
XMLFreeElement(iq_query);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Wake it up once we're done */
|
|
||||||
pthread_mutex_unlock(&jabber->write_lock);
|
pthread_mutex_unlock(&jabber->write_lock);
|
||||||
ParseeWakeupThread();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -198,7 +198,7 @@ XMPPJoinMUC(XMPPComponent *comp, char *fr, char *muc)
|
||||||
void
|
void
|
||||||
XMPPKillThread(XMPPComponent *jabber, char *killer)
|
XMPPKillThread(XMPPComponent *jabber, char *killer)
|
||||||
{
|
{
|
||||||
XMLElement *message, *body, *data;
|
XMLElement *message, *body;
|
||||||
char *from;
|
char *from;
|
||||||
|
|
||||||
if (!jabber || !killer)
|
if (!jabber || !killer)
|
||||||
|
|
|
||||||
160
src/XMPPThread.c
160
src/XMPPThread.c
|
|
@ -49,8 +49,8 @@ typedef struct XMPPIdentity {
|
||||||
static int
|
static int
|
||||||
ICollate(unsigned char *cata, unsigned char *catb)
|
ICollate(unsigned char *cata, unsigned char *catb)
|
||||||
{
|
{
|
||||||
size_t al = cata ? strlen(cata) : 0;
|
size_t al = cata ? strlen((char *) cata) : 0;
|
||||||
size_t bl = catb ? strlen(catb) : 0;
|
size_t bl = catb ? strlen((char *) catb) : 0;
|
||||||
|
|
||||||
if (!al && !bl)
|
if (!al && !bl)
|
||||||
{
|
{
|
||||||
|
|
@ -89,8 +89,8 @@ IdentitySort(void *idap, void *idbp)
|
||||||
{
|
{
|
||||||
XMPPIdentity *ida = idap;
|
XMPPIdentity *ida = idap;
|
||||||
XMPPIdentity *idb = idbp;
|
XMPPIdentity *idb = idbp;
|
||||||
unsigned char *cata = ida->category;
|
unsigned char *cata = (unsigned char *) ida->category;
|
||||||
unsigned char *catb = idb->category;
|
unsigned char *catb = (unsigned char *) idb->category;
|
||||||
|
|
||||||
return ICollate(cata, catb);
|
return ICollate(cata, catb);
|
||||||
}
|
}
|
||||||
|
|
@ -144,7 +144,7 @@ XMPPGenerateVer(void)
|
||||||
|
|
||||||
Sha = Sha1(S);
|
Sha = Sha1(S);
|
||||||
Free(S);
|
Free(S);
|
||||||
S = Base64Encode(Sha, 20);
|
S = Base64Encode((const char *) Sha, 20);
|
||||||
Free(Sha);
|
Free(Sha);
|
||||||
|
|
||||||
ArrayFree(features);
|
ArrayFree(features);
|
||||||
|
|
@ -159,17 +159,6 @@ XMPPGenerateVer(void)
|
||||||
return S;
|
return S;
|
||||||
}
|
}
|
||||||
|
|
||||||
static pthread_mutex_t cond_var_lock = PTHREAD_MUTEX_INITIALIZER;
|
|
||||||
static pthread_cond_t cond_var = PTHREAD_COND_INITIALIZER;
|
|
||||||
|
|
||||||
void
|
|
||||||
ParseeWakeupThread(void)
|
|
||||||
{
|
|
||||||
pthread_mutex_lock(&cond_var_lock);
|
|
||||||
pthread_cond_signal(&cond_var);
|
|
||||||
pthread_mutex_unlock(&cond_var_lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
ParseeGetBridgedRoom(ParseeData *data, XMLElement *stanza)
|
ParseeGetBridgedRoom(ParseeData *data, XMLElement *stanza)
|
||||||
{
|
{
|
||||||
|
|
@ -222,7 +211,6 @@ ParseeGetReactedEvent(ParseeData *data, XMLElement *stanza)
|
||||||
XMLElement *reactions = XMLookForTKV(stanza,
|
XMLElement *reactions = XMLookForTKV(stanza,
|
||||||
"reactions", "xmlns", "urn:xmpp:reactions:0"
|
"reactions", "xmlns", "urn:xmpp:reactions:0"
|
||||||
);
|
);
|
||||||
char *from = (HashMapGet(stanza->attrs, "from"));
|
|
||||||
char *reacted_id = reactions ? HashMapGet(reactions->attrs, "id") : NULL;
|
char *reacted_id = reactions ? HashMapGet(reactions->attrs, "id") : NULL;
|
||||||
|
|
||||||
return ParseeGetEventFromID(data, stanza, reacted_id);
|
return ParseeGetEventFromID(data, stanza, reacted_id);
|
||||||
|
|
@ -237,7 +225,6 @@ ParseePushAllStanza(ParseeData *args, XMLElement *stanza, char *event)
|
||||||
|
|
||||||
char *id_str = HashMapGet(stanza->attrs, "id");
|
char *id_str = HashMapGet(stanza->attrs, "id");
|
||||||
char *s_id_str = XMPPGetStanzaID(stanza);
|
char *s_id_str = XMPPGetStanzaID(stanza);
|
||||||
char *o_id_str = XMPPGetOriginID(stanza);
|
|
||||||
|
|
||||||
if (!chat_id)
|
if (!chat_id)
|
||||||
{
|
{
|
||||||
|
|
@ -389,6 +376,8 @@ ManageProfileItem(ParseeData *args, XMLElement *item, XMLElement *stanza, XMPPTh
|
||||||
pthread_mutex_unlock(&jabber->write_lock);
|
pthread_mutex_unlock(&jabber->write_lock);
|
||||||
|
|
||||||
XMLFreeElement(request);
|
XMLFreeElement(request);
|
||||||
|
|
||||||
|
(void) url; /* TODO */
|
||||||
}
|
}
|
||||||
|
|
||||||
end:
|
end:
|
||||||
|
|
@ -406,7 +395,7 @@ MessageStanza(ParseeData *args, XMLElement *stanza, XMPPThread *thr)
|
||||||
XMLElement *event = NULL;
|
XMLElement *event = NULL;
|
||||||
|
|
||||||
char *to, *room, *from, *from_matrix, *decode_from;
|
char *to, *room, *from, *from_matrix, *decode_from;
|
||||||
char *chat_id = NULL, *mroom_id = NULL;
|
char *mroom_id = NULL;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
to = NULL;
|
to = NULL;
|
||||||
|
|
@ -506,9 +495,6 @@ MessageStanza(ParseeData *args, XMLElement *stanza, XMPPThread *thr)
|
||||||
{
|
{
|
||||||
char *res = ParseeGetResource(from);
|
char *res = ParseeGetResource(from);
|
||||||
char *encoded = ParseeEncodeJID(args->config, decode_from, false);
|
char *encoded = ParseeEncodeJID(args->config, decode_from, false);
|
||||||
char *s_id_str = XMPPGetStanzaID(stanza);
|
|
||||||
char *o_id_str = XMPPGetOriginID(stanza);
|
|
||||||
char *id_str = HashMapGet(stanza->attrs, "id");
|
|
||||||
char *event_id = NULL;
|
char *event_id = NULL;
|
||||||
char *replaced = XMPPGetReplacedID(stanza);
|
char *replaced = XMPPGetReplacedID(stanza);
|
||||||
char *reply_to = XMPPGetReply(stanza);
|
char *reply_to = XMPPGetReply(stanza);
|
||||||
|
|
@ -548,7 +534,7 @@ MessageStanza(ParseeData *args, XMLElement *stanza, XMPPThread *thr)
|
||||||
ASSetName(args->config, encoded, res);
|
ASSetName(args->config, encoded, res);
|
||||||
}
|
}
|
||||||
ASInvite(args->config, mroom_id, encoded);
|
ASInvite(args->config, mroom_id, encoded);
|
||||||
ASJoin(args->config, mroom_id, encoded);
|
Free(ASJoin(args->config, mroom_id, encoded));
|
||||||
|
|
||||||
/* Check if it is a media link */
|
/* Check if it is a media link */
|
||||||
oob = XMLookForTKV(stanza, "x", "xmlns", "jabber:x:oob");
|
oob = XMLookForTKV(stanza, "x", "xmlns", "jabber:x:oob");
|
||||||
|
|
@ -574,7 +560,6 @@ MessageStanza(ParseeData *args, XMLElement *stanza, XMPPThread *thr)
|
||||||
}
|
}
|
||||||
else if (reactions)
|
else if (reactions)
|
||||||
{
|
{
|
||||||
char *reacted_id = HashMapGet(reactions->attrs, "id");
|
|
||||||
Array *react_child = reactions->children;
|
Array *react_child = reactions->children;
|
||||||
size_t reacts = ArraySize(react_child);
|
size_t reacts = ArraySize(react_child);
|
||||||
event_id = ParseeGetReactedEvent(args, stanza);
|
event_id = ParseeGetReactedEvent(args, stanza);
|
||||||
|
|
@ -642,8 +627,6 @@ MessageStanza(ParseeData *args, XMLElement *stanza, XMPPThread *thr)
|
||||||
XMLElement *parsee = XMLookForUnique(stanza, "x-parsee");
|
XMLElement *parsee = XMLookForUnique(stanza, "x-parsee");
|
||||||
XMLElement *event = XMLookForUnique(parsee, "event-id");
|
XMLElement *event = XMLookForUnique(parsee, "event-id");
|
||||||
XMLElement *e_d = ArrayGet(event ? event->children : NULL, 0);
|
XMLElement *e_d = ArrayGet(event ? event->children : NULL, 0);
|
||||||
char *s_id_str = XMPPGetStanzaID(stanza);
|
|
||||||
char *id_str = HashMapGet(stanza->attrs, "id");
|
|
||||||
|
|
||||||
ParseePushAllStanza(args, stanza, e_d->data);
|
ParseePushAllStanza(args, stanza, e_d->data);
|
||||||
}
|
}
|
||||||
|
|
@ -752,7 +735,6 @@ TrimBase64(char *b64)
|
||||||
static void
|
static void
|
||||||
IQResult(ParseeData *args, XMLElement *stanza)
|
IQResult(ParseeData *args, XMLElement *stanza)
|
||||||
{
|
{
|
||||||
XMPPComponent *jabber = args->jabber;
|
|
||||||
XMLElement *vcard = XMLookForTKV(stanza, "vCard", "xmlns", "vcard-temp");
|
XMLElement *vcard = XMLookForTKV(stanza, "vCard", "xmlns", "vcard-temp");
|
||||||
|
|
||||||
XMLElement *event = XMLookForTKV(stanza, "pubsub",
|
XMLElement *event = XMLookForTKV(stanza, "pubsub",
|
||||||
|
|
@ -776,7 +758,7 @@ IQResult(ParseeData *args, XMLElement *stanza)
|
||||||
char *id = HashMapGet(item->attrs, "id");
|
char *id = HashMapGet(item->attrs, "id");
|
||||||
char *from = HashMapGet(stanza->attrs, "from");
|
char *from = HashMapGet(stanza->attrs, "from");
|
||||||
char *base64;
|
char *base64;
|
||||||
unsigned char *bdata;
|
char *bdata;
|
||||||
size_t length, b64len;
|
size_t length, b64len;
|
||||||
Stream *datastream;
|
Stream *datastream;
|
||||||
char *mxc, *from_matrix, *jid;
|
char *mxc, *from_matrix, *jid;
|
||||||
|
|
@ -804,8 +786,8 @@ IQResult(ParseeData *args, XMLElement *stanza)
|
||||||
b64len = base64 ? strlen(base64) : 0;
|
b64len = base64 ? strlen(base64) : 0;
|
||||||
length = Base64DecodedSize(base64, b64len);
|
length = Base64DecodedSize(base64, b64len);
|
||||||
|
|
||||||
/* TODO: Bound checks! */
|
/* TODO: Bound checks for a size limit. */
|
||||||
bdata = Base64Decode(base64, b64len);
|
bdata = (char *) Base64Decode(base64, b64len);
|
||||||
datastream = StrStreamReaderN(bdata, length);
|
datastream = StrStreamReaderN(bdata, length);
|
||||||
mxc = ASUpload(args->config, datastream, length);
|
mxc = ASUpload(args->config, datastream, length);
|
||||||
|
|
||||||
|
|
@ -837,13 +819,16 @@ IQResult(ParseeData *args, XMLElement *stanza)
|
||||||
if (nickname)
|
if (nickname)
|
||||||
{
|
{
|
||||||
XMLElement *data = ArrayGet(nickname->children, 0);
|
XMLElement *data = ArrayGet(nickname->children, 0);
|
||||||
|
/* TODO: Use the nickname for something.
|
||||||
|
* And the rest of the vCard, somewhere. */
|
||||||
|
(void) data;
|
||||||
}
|
}
|
||||||
if (photo)
|
if (photo)
|
||||||
{
|
{
|
||||||
XMLElement *binval = XMLookForUnique(photo, "BINVAL");
|
XMLElement *binval = XMLookForUnique(photo, "BINVAL");
|
||||||
XMLElement *data = ArrayGet(binval->children, 0);
|
XMLElement *data = ArrayGet(binval->children, 0);
|
||||||
char *base64;
|
char *base64;
|
||||||
unsigned char *bdata;
|
char *bdata;
|
||||||
size_t length, b64len;
|
size_t length, b64len;
|
||||||
Stream *datastream;
|
Stream *datastream;
|
||||||
char *mxc, *from_matrix, *jid;
|
char *mxc, *from_matrix, *jid;
|
||||||
|
|
@ -885,7 +870,7 @@ IQGet(ParseeData *args, XMLElement *stanza)
|
||||||
else if (XMLookForTKV(stanza, "query", "xmlns", "jabber:iq:version"))
|
else if (XMLookForTKV(stanza, "query", "xmlns", "jabber:iq:version"))
|
||||||
{
|
{
|
||||||
XMLElement *iq_reply, *query;
|
XMLElement *iq_reply, *query;
|
||||||
XMLElement *name, *version, *val;
|
XMLElement *name, *version;
|
||||||
char *from = HashMapGet(stanza->attrs, "from");
|
char *from = HashMapGet(stanza->attrs, "from");
|
||||||
char *to = HashMapGet(stanza->attrs, "to");
|
char *to = HashMapGet(stanza->attrs, "to");
|
||||||
char *id = HashMapGet(stanza->attrs, "id");
|
char *id = HashMapGet(stanza->attrs, "id");
|
||||||
|
|
@ -980,24 +965,22 @@ PresenceStanza(ParseeData *args, XMLElement *stanza)
|
||||||
if ((user_info = XMLookForTKV(stanza, "x", "xmlns", MUC_USER_NS)))
|
if ((user_info = XMLookForTKV(stanza, "x", "xmlns", MUC_USER_NS)))
|
||||||
{
|
{
|
||||||
XMLElement *item = XMLookForUnique(user_info, "item");
|
XMLElement *item = XMLookForUnique(user_info, "item");
|
||||||
XMPPComponent *jabber = args->jabber;
|
|
||||||
char *jid = item ? HashMapGet(item->attrs, "jid") : NULL;
|
char *jid = item ? HashMapGet(item->attrs, "jid") : NULL;
|
||||||
char *from, *best = jid ? jid : oid;
|
char *from;
|
||||||
char *type = HashMapGet(stanza->attrs, "type");
|
char *type = HashMapGet(stanza->attrs, "type");
|
||||||
|
|
||||||
if (StrEquals(type, "unavailable"))
|
if (StrEquals(type, "unavailable"))
|
||||||
{
|
{
|
||||||
/* TODO: Treat as a ban if the role is outcast */
|
/* TODO: Treat as a ban if the role is outcast.
|
||||||
|
* Modify the code to be more accurate later. */
|
||||||
char *room = ParseeGetBridgedRoom(args, stanza);
|
char *room = ParseeGetBridgedRoom(args, stanza);
|
||||||
char *decode_from = ParseeLookupJID(oid);
|
char *decode_from = ParseeLookupJID(oid);
|
||||||
char *from_matrix = ParseeDecodeMXID(decode_from);
|
char *from_matrix = ParseeDecodeMXID(decode_from);
|
||||||
char *affiliation = HashMapGet(item->attrs, "affiliation");
|
char *affiliation = HashMapGet(item->attrs, "affiliation");
|
||||||
|
|
||||||
if (!from_matrix || *from_matrix != '@')
|
|
||||||
{
|
Log(LOG_INFO, "Acting on %s", from_matrix);
|
||||||
Free(from_matrix);
|
Log(LOG_INFO, "OID=%s DF=%s", oid, decode_from);
|
||||||
from_matrix = ParseeEncodeJID(args->config, oid, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (StrEquals(affiliation, "outcast"))
|
if (StrEquals(affiliation, "outcast"))
|
||||||
{
|
{
|
||||||
|
|
@ -1097,11 +1080,11 @@ XMPPDispatcher(void *argp)
|
||||||
{
|
{
|
||||||
XMPPThread *thread = argp;
|
XMPPThread *thread = argp;
|
||||||
ParseeData *args = thread->info->args;
|
ParseeData *args = thread->info->args;
|
||||||
XMPPComponent *jabber = thread->info->jabber;
|
|
||||||
|
|
||||||
while (thread->info->running)
|
while (thread->info->running)
|
||||||
{
|
{
|
||||||
XMLElement *stanza = RetrieveStanza(thread);
|
XMLElement *stanza = RetrieveStanza(thread);
|
||||||
|
|
||||||
if (!stanza)
|
if (!stanza)
|
||||||
{
|
{
|
||||||
UtilSleepMillis(1);
|
UtilSleepMillis(1);
|
||||||
|
|
@ -1116,7 +1099,6 @@ XMPPDispatcher(void *argp)
|
||||||
}
|
}
|
||||||
else if (StrEquals(stanza->name, "message"))
|
else if (StrEquals(stanza->name, "message"))
|
||||||
{
|
{
|
||||||
size_t i;
|
|
||||||
if (!MessageStanza(args, stanza, thread))
|
if (!MessageStanza(args, stanza, thread))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -1135,8 +1117,19 @@ XMPPDispatcher(void *argp)
|
||||||
}
|
}
|
||||||
XMLFreeElement(stanza);
|
XMLFreeElement(stanza);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct XMPPAwait {
|
||||||
|
pthread_mutex_t cond_lock;
|
||||||
|
pthread_cond_t condition;
|
||||||
|
|
||||||
|
XMLElement *stanza;
|
||||||
|
} XMPPAwait;
|
||||||
|
static pthread_mutex_t await_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
static HashMap *await_table = NULL;
|
||||||
|
|
||||||
void *
|
void *
|
||||||
ParseeXMPPThread(void *argp)
|
ParseeXMPPThread(void *argp)
|
||||||
{
|
{
|
||||||
|
|
@ -1144,9 +1137,10 @@ ParseeXMPPThread(void *argp)
|
||||||
XMPPComponent *jabber = args->jabber;
|
XMPPComponent *jabber = args->jabber;
|
||||||
XMLElement *stanza = NULL;
|
XMLElement *stanza = NULL;
|
||||||
XMPPThreadInfo info;
|
XMPPThreadInfo info;
|
||||||
pthread_mutex_t stanzas_lock = PTHREAD_MUTEX_INITIALIZER;
|
size_t i;
|
||||||
size_t i, j = 0;
|
|
||||||
|
|
||||||
|
/* Initialise the await table */
|
||||||
|
await_table = HashMapCreate();
|
||||||
|
|
||||||
/* Initialise the FIFO */
|
/* Initialise the FIFO */
|
||||||
info.stanzas = ArrayCreate();
|
info.stanzas = ArrayCreate();
|
||||||
|
|
@ -1174,9 +1168,7 @@ ParseeXMPPThread(void *argp)
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
char *to, *room, *from, *from_matrix;
|
char *from, *id;
|
||||||
char *chat_id, *mroom_id;
|
|
||||||
ssize_t cntr;
|
|
||||||
|
|
||||||
stanza = XMLDecode(jabber->stream, false);
|
stanza = XMLDecode(jabber->stream, false);
|
||||||
if (!stanza)
|
if (!stanza)
|
||||||
|
|
@ -1184,25 +1176,37 @@ ParseeXMPPThread(void *argp)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
id = HashMapGet(stanza->attrs, "id");
|
||||||
|
if (id)
|
||||||
|
{
|
||||||
|
XMPPAwait *await;
|
||||||
|
/* Lock out the table to see if we're awaiting. */
|
||||||
|
pthread_mutex_lock(&await_lock);
|
||||||
|
if ((await = HashMapGet(await_table, id)))
|
||||||
|
{
|
||||||
|
await->stanza = stanza;
|
||||||
|
pthread_mutex_lock(&await->cond_lock);
|
||||||
|
pthread_cond_signal(&await->condition);
|
||||||
|
pthread_mutex_unlock(&await->cond_lock);
|
||||||
|
|
||||||
|
HashMapDelete(await_table, id);
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&await_lock);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&await_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (StrEquals(stanza->name, "message") && XMPPIsKiller(stanza))
|
if (StrEquals(stanza->name, "message") && XMPPIsKiller(stanza))
|
||||||
{
|
{
|
||||||
const char *killer = "killer";
|
const char *killer = "killer";
|
||||||
const char *suspend="suspend";
|
|
||||||
from = HashMapGet(stanza->attrs, "from");
|
from = HashMapGet(stanza->attrs, "from");
|
||||||
if (!strncmp(from, killer, strlen(killer)))
|
if (!strncmp(from, killer, strlen(killer)))
|
||||||
{
|
{
|
||||||
XMLFreeElement(stanza);
|
XMLFreeElement(stanza);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (!strncmp(from, suspend, strlen(suspend)))
|
|
||||||
{
|
|
||||||
/* TODO */
|
|
||||||
XMLFreeElement(stanza);
|
|
||||||
pthread_mutex_lock(&cond_var_lock);
|
|
||||||
pthread_cond_wait(&cond_var, &cond_var_lock);
|
|
||||||
pthread_mutex_unlock(&cond_var_lock);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PushStanza(&info, stanza);
|
PushStanza(&info, stanza);
|
||||||
|
|
@ -1222,6 +1226,48 @@ ParseeXMPPThread(void *argp)
|
||||||
}
|
}
|
||||||
ArrayFree(info.stanzas);
|
ArrayFree(info.stanzas);
|
||||||
|
|
||||||
|
HashMapFree(await_table);
|
||||||
|
|
||||||
pthread_mutex_destroy(&info.lock);
|
pthread_mutex_destroy(&info.lock);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
XMLElement *
|
||||||
|
ParseeAwaitStanza(char *identifier)
|
||||||
|
{
|
||||||
|
XMPPAwait awa, *await;
|
||||||
|
XMLElement *stanza;
|
||||||
|
if (!identifier)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: Pthreads HATE me using Malloc here, so I'm abusing stackspace.
|
||||||
|
* Not *too much* of a problem, just a weird oddity. If anyone has a clue
|
||||||
|
* on why that happens (at least on ARM64 with a Pi4 running Debian), let
|
||||||
|
* me know! */
|
||||||
|
await = &awa;
|
||||||
|
pthread_mutex_lock(&await_lock);
|
||||||
|
|
||||||
|
pthread_cond_init(&await->condition, NULL);
|
||||||
|
pthread_mutex_init(&await->cond_lock, NULL);
|
||||||
|
await->stanza = NULL;
|
||||||
|
|
||||||
|
HashMapSet(await_table, identifier, await);
|
||||||
|
pthread_mutex_unlock(&await_lock);
|
||||||
|
|
||||||
|
pthread_mutex_lock(&await->cond_lock);
|
||||||
|
while (!await->stanza)
|
||||||
|
{
|
||||||
|
pthread_cond_wait(&await->condition, &await->cond_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
stanza = await->stanza;
|
||||||
|
pthread_mutex_lock(&await_lock);
|
||||||
|
pthread_mutex_unlock(&await_lock);
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&await->cond_lock);
|
||||||
|
|
||||||
|
pthread_cond_destroy(&await->condition);
|
||||||
|
pthread_mutex_destroy(&await->cond_lock);
|
||||||
|
return stanza;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ extern void ASPing(const ParseeConfig *);
|
||||||
|
|
||||||
/* Joins a room from an ID and a given user we want to masquerade
|
/* Joins a room from an ID and a given user we want to masquerade
|
||||||
* as. */
|
* as. */
|
||||||
extern void ASJoin(const ParseeConfig *, char *, char *);
|
extern char * ASJoin(const ParseeConfig *, char *, char *);
|
||||||
|
|
||||||
/* Bans from a room a specific user */
|
/* Bans from a room a specific user */
|
||||||
extern void ASBan(const ParseeConfig *, char *, char *);
|
extern void ASBan(const ParseeConfig *, char *, char *);
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,12 @@
|
||||||
); \
|
); \
|
||||||
char *id = GrabString(event, 1, "room_id")
|
char *id = GrabString(event, 1, "room_id")
|
||||||
|
|
||||||
|
#define BotRequired(prop) prop = HashMapGet(cmd->arguments, #prop); \
|
||||||
|
if (!prop) \
|
||||||
|
{ \
|
||||||
|
ReplyBasic("Field `" #prop "` REQUIRED."); \
|
||||||
|
}
|
||||||
|
|
||||||
#define BotDestroy() Free(profile)
|
#define BotDestroy() Free(profile)
|
||||||
|
|
||||||
#define ReplyBasic(rep) do \
|
#define ReplyBasic(rep) do \
|
||||||
|
|
|
||||||
|
|
@ -119,8 +119,8 @@ extern void ParseeRequest(HttpServerContext *, void *);
|
||||||
/* A pthread callback used for listening to a component */
|
/* A pthread callback used for listening to a component */
|
||||||
extern void * ParseeXMPPThread(void *data);
|
extern void * ParseeXMPPThread(void *data);
|
||||||
|
|
||||||
/* Wakes up the XMPP thread from a "suspend" killer stanza */
|
/* Wait for a specific stanza with an ID */
|
||||||
extern void ParseeWakeupThread(void);
|
extern XMLElement * ParseeAwaitStanza(char *identifier);
|
||||||
|
|
||||||
/* Finds the room a DM is associated to, from a Matrix user and a Jabber
|
/* Finds the room a DM is associated to, from a Matrix user and a Jabber
|
||||||
* ID. */
|
* ID. */
|
||||||
|
|
@ -204,7 +204,7 @@ extern void ParseeDestroyJIDTable(void);
|
||||||
|
|
||||||
/* Globally bans a Matrix user from ever interacting with Parsee, and bans
|
/* Globally bans a Matrix user from ever interacting with Parsee, and bans
|
||||||
* them from bridged rooms where the bot has administrator. */
|
* them from bridged rooms where the bot has administrator. */
|
||||||
extern void ParseeGlobalBan(ParseeData *, char *user);
|
extern void ParseeGlobalBan(ParseeData *, char *user, char *reason);
|
||||||
|
|
||||||
/* Verifies if a user was globally banned. If so, then apply actions to the
|
/* Verifies if a user was globally banned. If so, then apply actions to the
|
||||||
* room ID */
|
* room ID */
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,12 @@ typedef struct ParseeCmdArg {
|
||||||
"Sets the power level to send a specific event " \
|
"Sets the power level to send a specific event " \
|
||||||
"in a Parsee room" \
|
"in a Parsee room" \
|
||||||
) \
|
) \
|
||||||
|
X_COMMAND( \
|
||||||
|
"plumb-muc", CmdPlumb, \
|
||||||
|
"Plumbs an existing Matrix room to a MUC." \
|
||||||
|
"You'll need to give the Parsee bot enough " \
|
||||||
|
"privileges, however. " \
|
||||||
|
) \
|
||||||
X_COMMAND( \
|
X_COMMAND( \
|
||||||
"help", CmdHelp, \
|
"help", CmdHelp, \
|
||||||
"Shows the command list" \
|
"Shows the command list" \
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue