[FIX/MOD] Stanza send function, fix some errors

Negociating stanza sizes seems to be real trouble. Also this code is now
`-fanalyzer'-safe!
Also kills the last GNUMakefile present. It wasn't even used...
This commit is contained in:
LDA 2024-10-19 16:58:48 +02:00
commit ff5f085b7f
24 changed files with 114 additions and 152 deletions

View file

@ -33,7 +33,7 @@ jobs:
- name: Build Parsee - name: Build Parsee
run: | run: |
cc configure.c -o configure && ./configure cc configure.c -o configure && ./configure
echo 'CFLAGS=-Werror -Wall -Wextra -pedantic' >> build.conf echo 'CFLAGS=-Werror -Wall -Wextra -pedantic -fanalyzer' >> build.conf
cat build.conf cat build.conf
make && make ayadoc make && make ayadoc
- name: Install Parsee - name: Install Parsee

View file

@ -97,6 +97,9 @@ restricted to Parsee admins, with permission from MUC owners, too
support XMPP->Matrix bridging. support XMPP->Matrix bridging.
- Manage MUC DMs in a reasonable manner. Thanks `@freeoffers4u:matrix.org` for being - Manage MUC DMs in a reasonable manner. Thanks `@freeoffers4u:matrix.org` for being
a fucking annoyance and DMing an old Parsee semi-anon user for no clear reason. a fucking annoyance and DMing an old Parsee semi-anon user for no clear reason.
- Make Parsee cope well with unexcepted stream closures (e.g: with an XMPP server
turning off, etc...). Shutting it off seems like an easy solution, but would go
against principles.
## 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

View file

@ -445,10 +445,15 @@ main_build(int argc, char *argv[])
if (repo) if (repo)
{ {
char *lf = strchr(repo, '\n'); char *lf = strchr(repo, '\n');
*lf = '\0'; if (lf)
{
*lf = '\0';
}
} }
else else
{
repo = strdup("N/A"); repo = strdup("N/A");
}
while ((opt = getopt(argc, argv, "sl")) != -1) while ((opt = getopt(argc, argv, "sl")) != -1)
{ {
@ -465,8 +470,9 @@ main_build(int argc, char *argv[])
} }
makefile = fopen("Makefile", "w"); makefile = fopen("Makefile", "w");
fprintf(makefile, "# Autogenerated POSIX Makefile\n"); fprintf(makefile, "# Autogenerated POSIX Makefile from Parsee\n");
fprintf(makefile, "# Ideally do not touch.\n\n"); fprintf(makefile, "# Ideally do not touch, unless you have a very ");
fprintf(makefile, "good reason to do it. \n\n");
fprintf(makefile, ".POSIX: \n"); fprintf(makefile, ".POSIX: \n");
fprintf(makefile, "include build.conf\n\n"); fprintf(makefile, "include build.conf\n\n");
fprintf(makefile, "AYAYAS=ayaya\n"); fprintf(makefile, "AYAYAS=ayaya\n");

View file

@ -40,6 +40,8 @@ FileInfoFromXMPP(XMLElement *stanza)
file = XMLookForTKV(sims, file = XMLookForTKV(sims,
"file", "xmlns", "urn:xmpp:jingle:apps:file-transfer:5" "file", "xmlns", "urn:xmpp:jingle:apps:file-transfer:5"
); );
/* TODO: We'll definitely need MIME types to do things like
* WebXDC */
if (!file) if (!file)
{ {
return NULL; return NULL;

View file

@ -1,5 +1,6 @@
#include <Cytoplasm/HttpServer.h> #include <Cytoplasm/HttpServer.h>
#include <Cytoplasm/Cytoplasm.h> #include <Cytoplasm/Cytoplasm.h>
#include <Cytoplasm/Platform.h>
#include <Cytoplasm/Memory.h> #include <Cytoplasm/Memory.h>
#include <Cytoplasm/Util.h> #include <Cytoplasm/Util.h>
#include <Cytoplasm/Cron.h> #include <Cytoplasm/Cron.h>
@ -81,6 +82,13 @@ Main(Array *args, HashMap *env)
Log(LOG_INFO, "======================="); Log(LOG_INFO, "=======================");
Log(LOG_INFO, "(C)opyright 2024 LDA"); Log(LOG_INFO, "(C)opyright 2024 LDA");
Log(LOG_INFO, "(This program is free software, see LICENSE.)"); Log(LOG_INFO, "(This program is free software, see LICENSE.)");
#ifdef PLATFORM_IPHONE
Log(LOG_WARNING, "Wait. Are you running this on an iPhone?");
Log(LOG_WARNING, "You *ought* to have spoofed this, haven't you?");
Log(LOG_WARNING, "Simply jealous of you for doing this.");
#endif
LogConfigIndent(LogConfigGlobal()); LogConfigIndent(LogConfigGlobal());
{ {

View file

@ -62,6 +62,12 @@ ParseeConfigLoad(char *conf)
CopyToInt(component_port, "component_port"); CopyToInt(component_port, "component_port");
CopyToStr(component_host, "component_host"); CopyToStr(component_host, "component_host");
CopyToStr(shared_comp_secret, "shared_secret"); CopyToStr(shared_comp_secret, "shared_secret");
CopyToInt(max_stanza_size, "max_stanza_size");
if (!config->max_stanza_size)
{
/* Standard XMPP "minimum" maximum */
config->max_stanza_size = 10 KB;
}
CopyToStr(media_base, "media_base"); CopyToStr(media_base, "media_base");

View file

@ -59,6 +59,7 @@ ParseeInitData(XMPPComponent *comp)
{ {
Log(LOG_WARNING, "Version mismatch(curr=%s db=%s).", VERSION, version); Log(LOG_WARNING, "Version mismatch(curr=%s db=%s).", VERSION, version);
Log(LOG_WARNING, "Yeah. You may want to _not_ do that."); Log(LOG_WARNING, "Yeah. You may want to _not_ do that.");
Log(LOG_WARNING, "(Parsee still needs an upgradepath mechanism.)");
DbUnlock(data->db, ref); DbUnlock(data->db, ref);
DbClose(data->db); DbClose(data->db);
@ -126,8 +127,6 @@ ParseeCleanup(void *datp)
uint64_t ts = UtilTsMillis(); uint64_t ts = UtilTsMillis();
size_t entries = 0; size_t entries = 0;
Log(LOG_DEBUG, "Cleaning up...");
chats = DbList(data->db, 1, "chats"); chats = DbList(data->db, 1, "chats");
for (i = 0; i < ArraySize(chats); i++) for (i = 0; i < ArraySize(chats); i++)
@ -242,7 +241,6 @@ ParseeCleanup(void *datp)
DbUnlock(data->db, ref); DbUnlock(data->db, ref);
} }
DbListFree(chats); DbListFree(chats);
Log(LOG_DEBUG, "Cleant up %d entries...", entries);
} }
void void

View file

@ -25,6 +25,8 @@ SignalHandler(int signal)
if (signal == SIGPIPE) if (signal == SIGPIPE)
{ {
Log(LOG_DEBUG, "Caught a SIGPIPE..."); Log(LOG_DEBUG, "Caught a SIGPIPE...");
XMPPFinishCompStream(jabber);
pthread_join(xmpp_thr, NULL);
return; return;
} }
} }

View file

@ -237,13 +237,8 @@ WriteoutStanza(StanzaBuilder *builder, XMPPComponent *jabber)
} }
elem = ExportStanza(builder); elem = ExportStanza(builder);
pthread_mutex_lock(&jabber->write_lock); XMPPSendStanza(jabber, elem);
XMLEncode(jabber->stream, elem);
StreamFlush(jabber->stream);
pthread_mutex_unlock(&jabber->write_lock);
XMLFreeElement(elem); XMLFreeElement(elem);
return;
} }
StanzaBuilder * StanzaBuilder *

View file

@ -11,6 +11,7 @@
#include <errno.h> #include <errno.h>
#include <netdb.h> #include <netdb.h>
#include <StringStream.h>
#include <Parsee.h> #include <Parsee.h>
#include <XML.h> #include <XML.h>
@ -134,7 +135,7 @@ XMPPAuthenticateCompStream(XMPPComponent *comp, char *shared)
} }
break; break;
} }
if (ev->type != XML_LEXER_STARTELEM || if (!ev || ev->type != XML_LEXER_STARTELEM ||
!StrEquals(ev->element, "stream:stream")) !StrEquals(ev->element, "stream:stream"))
{ {
Log(LOG_ERR, "Excepted stream:stream element."); Log(LOG_ERR, "Excepted stream:stream element.");
@ -159,10 +160,9 @@ XMPPAuthenticateCompStream(XMPPComponent *comp, char *shared)
} }
break; break;
} }
if (ev->type != XML_LEXER_ELEM || if (!ev || ev->type != XML_LEXER_ELEM ||
!StrEquals(ev->element, "handshake")) !StrEquals(ev->element, "handshake"))
{ {
Log(LOG_DEBUG, "type=%d elem='%s'", ev->type, ev->element);
Log(LOG_ERR, "Excepted empty handshake reply, got nonsense."); Log(LOG_ERR, "Excepted empty handshake reply, got nonsense.");
Log(LOG_ERR, "Another service (possibly Parsee) may have taken over."); Log(LOG_ERR, "Another service (possibly Parsee) may have taken over.");
Log(LOG_ERR, ""); Log(LOG_ERR, "");
@ -213,3 +213,18 @@ XMPPEndCompStream(XMPPComponent *comp)
Free(comp->host); Free(comp->host);
Free(comp); Free(comp);
} }
void
XMPPSendStanza(XMPPComponent *comp, XMLElement *stanza)
{
if (!comp || !stanza)
{
return;
}
pthread_mutex_lock(&comp->write_lock);
/* TODO: Find a way to negociate to the server about stanza size
* (beyond the 10KB limit that is REQUIRED by XMPP standards) */
XMLEncode(comp->stream, stanza);
StreamFlush(comp->stream);
pthread_mutex_unlock(&comp->write_lock);
}

View file

@ -18,8 +18,6 @@ XMPPQueryMUC(XMPPComponent *jabber, char *muc, MUCInfo *out)
return false; return false;
} }
pthread_mutex_lock(&jabber->write_lock);
iq_query = XMLCreateTag("iq"); iq_query = XMLCreateTag("iq");
query = XMLCreateTag("query"); query = XMLCreateTag("query");
@ -35,8 +33,7 @@ XMPPQueryMUC(XMPPComponent *jabber, char *muc, MUCInfo *out)
{ {
XMLElement *identity; XMLElement *identity;
XMLEncode(jabber->stream, iq_query); XMPPSendStanza(jabber, iq_query);
StreamFlush(jabber->stream);
XMLFreeElement(iq_query); XMLFreeElement(iq_query);
/* Except an IQ reply. 10 seconds of timeout is pretty /* Except an IQ reply. 10 seconds of timeout is pretty
@ -46,7 +43,6 @@ XMPPQueryMUC(XMPPComponent *jabber, char *muc, MUCInfo *out)
if (!iq_query || !StrEquals(iq_query->name, "iq")) if (!iq_query || !StrEquals(iq_query->name, "iq"))
{ {
XMLFreeElement(iq_query); XMLFreeElement(iq_query);
pthread_mutex_unlock(&jabber->write_lock);
return false; return false;
} }
query = XMLookForUnique(iq_query, "query"); query = XMLookForUnique(iq_query, "query");
@ -57,7 +53,6 @@ XMPPQueryMUC(XMPPComponent *jabber, char *muc, MUCInfo *out)
"conference")) "conference"))
{ {
XMLFreeElement(iq_query); XMLFreeElement(iq_query);
pthread_mutex_unlock(&jabber->write_lock);
return false; return false;
} }
@ -73,7 +68,6 @@ XMPPQueryMUC(XMPPComponent *jabber, char *muc, MUCInfo *out)
XMLFreeElement(iq_query); XMLFreeElement(iq_query);
} }
} }
pthread_mutex_unlock(&jabber->write_lock);
return true; return true;
} }
@ -116,7 +110,6 @@ XMPPRequestVoice(XMPPComponent *jabber, char *from, char *muc)
return; return;
} }
pthread_mutex_lock(&jabber->write_lock);
stanza = XMLCreateTag("message"); stanza = XMLCreateTag("message");
XMLAddAttr(stanza, "id", (identifier = StrRandom(32))); XMLAddAttr(stanza, "id", (identifier = StrRandom(32)));
XMLAddAttr(stanza, "from", from); XMLAddAttr(stanza, "from", from);
@ -160,9 +153,7 @@ XMPPRequestVoice(XMPPComponent *jabber, char *from, char *muc)
} }
XMLAddChild(stanza, x); XMLAddChild(stanza, x);
} }
XMLEncode(jabber->stream, stanza); XMPPSendStanza(jabber, stanza);
StreamFlush(jabber->stream);
pthread_mutex_unlock(&jabber->write_lock);
XMLFreeElement(stanza); XMLFreeElement(stanza);
Free(identifier); Free(identifier);
@ -177,8 +168,6 @@ XMPPJoinMUC(XMPPComponent *comp, char *fr, char *muc, char *hash, int time, bool
return false; return false;
} }
pthread_mutex_lock(&comp->write_lock);
presence = XMLCreateTag("presence"); presence = XMLCreateTag("presence");
x = XMLCreateTag("x"); x = XMLCreateTag("x");
XMLAddAttr(presence, "from", (from = StrConcat(3, fr, "@", comp->host))); XMLAddAttr(presence, "from", (from = StrConcat(3, fr, "@", comp->host)));
@ -212,14 +201,10 @@ XMPPJoinMUC(XMPPComponent *comp, char *fr, char *muc, char *hash, int time, bool
XMLAddChild(presence, x); XMLAddChild(presence, x);
} }
XMLEncode(comp->stream, presence); XMPPSendStanza(comp, presence);
StreamFlush(comp->stream);
XMLFreeElement(presence); XMLFreeElement(presence);
Free(from); Free(from);
pthread_mutex_unlock(&comp->write_lock);
if (ret && (reply = ParseeAwaitStanza(id, 500))) if (ret && (reply = ParseeAwaitStanza(id, 500)))
{ {
bool exit_code = true; bool exit_code = true;
@ -246,8 +231,6 @@ XMPPLeaveMUC(XMPPComponent *comp, char *fr, char *muc, char *reason)
return; return;
} }
pthread_mutex_lock(&comp->write_lock);
presence = XMLCreateTag("presence"); presence = XMLCreateTag("presence");
XMLAddAttr(presence, "from", (from = StrConcat(3, fr, "@", comp->host))); XMLAddAttr(presence, "from", (from = StrConcat(3, fr, "@", comp->host)));
XMLAddAttr(presence, "to", muc); XMLAddAttr(presence, "to", muc);
@ -265,12 +248,9 @@ XMPPLeaveMUC(XMPPComponent *comp, char *fr, char *muc, char *reason)
XMPPAnnotatePresence(presence); XMPPAnnotatePresence(presence);
XMLEncode(comp->stream, presence); XMPPSendStanza(comp, presence);
StreamFlush(comp->stream);
XMLFreeElement(presence); XMLFreeElement(presence);
Free(from); Free(from);
Free(id); Free(id);
pthread_mutex_unlock(&comp->write_lock);
} }

View file

@ -66,13 +66,9 @@ XMPPRetract(XMPPComponent *comp, char *fr, char *to, char *type, char *redact)
} }
pthread_mutex_lock(&comp->write_lock); XMPPSendStanza(comp, message);
XMLEncode(comp->stream, message);
StreamFlush(comp->stream);
XMLFreeElement(message); XMLFreeElement(message);
pthread_mutex_unlock(&comp->write_lock);
Free(from); Free(from);
Free(ident); Free(ident);
} }
@ -85,6 +81,8 @@ XMPPIsParseeStanza(XMLElement *stanza)
return false; return false;
} }
/* TODO: Check if the user is a trustworthy Parsee puppet instead of some
* guy sending random stanzas */
return !!XMLookForUnique(stanza, "x-parsee"); return !!XMLookForUnique(stanza, "x-parsee");
} }
@ -266,10 +264,7 @@ XMPPSendDisco(ParseeData *data, char *from, char *to)
XMLAddChild(iq, query); XMLAddChild(iq, query);
} }
pthread_mutex_lock(&jabber->write_lock); XMPPSendStanza(jabber, iq);
XMLEncode(jabber->stream, iq);
StreamFlush(jabber->stream);
pthread_mutex_unlock(&jabber->write_lock);
XMLFreeElement(iq); XMLFreeElement(iq);
ret = ParseeAwaitStanza(identifier, 1.25 SECONDS); ret = ParseeAwaitStanza(identifier, 1.25 SECONDS);

View file

@ -274,10 +274,7 @@ XMPPManageCommand(XMPPCommandManager *m, XMLElement *stanza, ParseeData *data)
x = XMPPFormifyCommand(m, cmd, from); x = XMPPFormifyCommand(m, cmd, from);
XMLAddChild(command_xml, x); XMLAddChild(command_xml, x);
pthread_mutex_lock(&jabber->write_lock); XMPPSendStanza(jabber, iq);
XMLEncode(jabber->stream, iq);
StreamFlush(jabber->stream);
pthread_mutex_unlock(&jabber->write_lock);
XMLFreeElement(iq); XMLFreeElement(iq);
goto end; goto end;
@ -305,10 +302,7 @@ XMPPManageCommand(XMPPCommandManager *m, XMLElement *stanza, ParseeData *data)
XMPPExecuteCommand(m, cmd, from, command_xml, NULL); XMPPExecuteCommand(m, cmd, from, command_xml, NULL);
XMLAddChild(iq, command_xml); XMLAddChild(iq, command_xml);
pthread_mutex_lock(&jabber->write_lock); XMPPSendStanza(jabber, iq);
XMLEncode(jabber->stream, iq);
StreamFlush(jabber->stream);
pthread_mutex_unlock(&jabber->write_lock);
XMLFreeElement(iq); XMLFreeElement(iq);
InvalidateSession(m, session_id); InvalidateSession(m, session_id);
@ -348,10 +342,7 @@ XMPPManageCommand(XMPPCommandManager *m, XMLElement *stanza, ParseeData *data)
XMPPExecuteCommand(m, cmd, from, command_xml, x_form); XMPPExecuteCommand(m, cmd, from, command_xml, x_form);
XMLAddChild(iq, command_xml); XMLAddChild(iq, command_xml);
pthread_mutex_lock(&jabber->write_lock); XMPPSendStanza(jabber, iq);
XMLEncode(jabber->stream, iq);
StreamFlush(jabber->stream);
pthread_mutex_unlock(&jabber->write_lock);
XMLFreeElement(iq); XMLFreeElement(iq);
InvalidateSession(m, session_given); InvalidateSession(m, session_given);

View file

@ -72,11 +72,7 @@ PEPAvatarEvent(PEPManager *m, XMLElement *stanza, XMLElement *item)
char *url = HashMapGet(item->attrs, "url"); char *url = HashMapGet(item->attrs, "url");
XMLElement *request = CreateAvatarRequest(from, to, id); XMLElement *request = CreateAvatarRequest(from, to, id);
pthread_mutex_lock(&jabber->write_lock); XMPPSendStanza(jabber, request);
XMLEncode(jabber->stream, request);
StreamFlush(jabber->stream);
pthread_mutex_unlock(&jabber->write_lock);
XMLFreeElement(request); XMLFreeElement(request);
(void) url; /* TODO */ (void) url; /* TODO */

View file

@ -113,10 +113,7 @@ PEPVCardEvent(PEPManager *m, XMLElement *stanza, XMLElement *item)
} }
} }
pthread_mutex_lock(&jabber->write_lock); XMPPSendStanza(jabber, reply);
XMLEncode(jabber->stream, reply);
StreamFlush(jabber->stream);
pthread_mutex_unlock(&jabber->write_lock);
XMLFreeElement(reply); XMLFreeElement(reply);
(void) item; (void) item;
} }

View file

@ -131,11 +131,7 @@ ParseeBroadcastStanza(ParseeData *data, char *from, XMLElement *stanza)
/* TODO: Should we store IDs somewhere? */ /* TODO: Should we store IDs somewhere? */
XMLAddAttr(sub, "id", (storm_id = StrRandom(16))); XMLAddAttr(sub, "id", (storm_id = StrRandom(16)));
pthread_mutex_lock(&jabber->write_lock); XMPPSendStanza(jabber, sub);
XMLEncode(jabber->stream, sub);
StreamFlush(jabber->stream);
pthread_mutex_unlock(&jabber->write_lock);
XMLFreeElement(sub); XMLFreeElement(sub);
Free(storm_id); Free(storm_id);
end: end:

View file

@ -198,6 +198,7 @@ ParseeXMPPThread(void *argp)
stanza = XMLDecode(jabber->stream, false); stanza = XMLDecode(jabber->stream, false);
if (!stanza) if (!stanza)
{ {
/* Try to check if an error is abound */
if (args->verbosity >= PARSEE_VERBOSE_COMICAL) if (args->verbosity >= PARSEE_VERBOSE_COMICAL)
{ {
Log(LOG_DEBUG, "RECEIVED EOF."); Log(LOG_DEBUG, "RECEIVED EOF.");

View file

@ -65,6 +65,14 @@ GenerateAvatarData(ParseeData *data, char *mxid)
goto end; goto end;
} }
b64 = Base64Encode(out, len); b64 = Base64Encode(out, len);
if (!b64 || strlen(b64) > 64 KB) /* We still have stanza limitations. Thanks, Array.
* TODO: Communicate with the server to discover it. */
{
Free(b64);
Free(mime);
b64 = StrDuplicate(media_parsee_logo); /* TODO: Different assets! */
mime = StrDuplicate("image/png");
}
elem = XMLCreateTag("PHOTO"); elem = XMLCreateTag("PHOTO");
type = XMLCreateTag("TYPE"); type = XMLCreateTag("TYPE");
@ -145,11 +153,7 @@ IQDiscoGet(ParseeData *args, XMPPComponent *jabber, XMLElement *stanza)
} }
XMLAddChild(iq_reply, query); XMLAddChild(iq_reply, query);
pthread_mutex_lock(&jabber->write_lock); XMPPSendStanza(jabber, iq_reply);
XMLEncode(jabber->stream, iq_reply);
StreamFlush(jabber->stream);
pthread_mutex_unlock(&jabber->write_lock);
XMLFreeElement(iq_reply); XMLFreeElement(iq_reply);
(void) args; (void) args;
@ -386,10 +390,7 @@ IQGet(ParseeData *args, XMLElement *stanza, XMPPThread *thr)
XMPPShoveCommandList(thr->info->m, to, q); XMPPShoveCommandList(thr->info->m, to, q);
XMLAddChild(iq_reply, q); XMLAddChild(iq_reply, q);
} }
pthread_mutex_lock(&jabber->write_lock); XMPPSendStanza(jabber, iq_reply);
XMLEncode(jabber->stream, iq_reply);
StreamFlush(jabber->stream);
pthread_mutex_unlock(&jabber->write_lock);
XMLFreeElement(iq_reply); XMLFreeElement(iq_reply);
} }
else if (XMLookForTKV(stanza, "vCard", "xmlns", "vcard-temp")) else if (XMLookForTKV(stanza, "vCard", "xmlns", "vcard-temp"))
@ -427,10 +428,7 @@ IQGet(ParseeData *args, XMLElement *stanza, XMPPThread *thr)
XMLAddChild(iqVCard, vCard); XMLAddChild(iqVCard, vCard);
} }
pthread_mutex_lock(&jabber->write_lock); XMPPSendStanza(jabber, iqVCard);
XMLEncode(jabber->stream, iqVCard);
StreamFlush(jabber->stream);
pthread_mutex_unlock(&jabber->write_lock);
XMLFreeElement(iqVCard); XMLFreeElement(iqVCard);
Free(to_matrix); Free(to_matrix);
Free(name); Free(name);
@ -457,10 +455,7 @@ IQGet(ParseeData *args, XMLElement *stanza, XMPPThread *thr)
XMLAddChild(iqVCard, vCard); XMLAddChild(iqVCard, vCard);
} }
pthread_mutex_lock(&jabber->write_lock); XMPPSendStanza(jabber, iqVCard);
XMLEncode(jabber->stream, iqVCard);
StreamFlush(jabber->stream);
pthread_mutex_unlock(&jabber->write_lock);
XMLFreeElement(iqVCard); XMLFreeElement(iqVCard);
Free(to_matrix); Free(to_matrix);
Free(name); Free(name);
@ -474,7 +469,10 @@ IQGet(ParseeData *args, XMLElement *stanza, XMPPThread *thr)
); );
if (a_items) if (a_items)
{ {
/* Do, without regret, start shoving an avatar out the bus */ /* Do, without regret, start shoving an avatar out the bus.
* NOTE: I explicitely choose to not do any manipulation
* because messing with random user images is inherently a
* risk I do *not* want to take. */
char *to_matrix = ParseeDecodeMXID(to); char *to_matrix = ParseeDecodeMXID(to);
char *avatar = ASGetAvatar(args->config, NULL, to_matrix); char *avatar = ASGetAvatar(args->config, NULL, to_matrix);
char *buf, *mime; char *buf, *mime;
@ -484,6 +482,13 @@ IQGet(ParseeData *args, XMLElement *stanza, XMPPThread *thr)
ASGrab(args->config, avatar, &mime, &buf, &len); ASGrab(args->config, avatar, &mime, &buf, &len);
b64 = Base64Encode(buf, len); b64 = Base64Encode(buf, len);
if (!b64 || strlen(b64) > 64 KB)
{
Free(b64);
Free(mime);
b64 = StrDuplicate(media_parsee_logo); /* TODO: Different assets! */
mime = StrDuplicate("image/png");
}
Free(buf); Free(buf);
Log(LOG_DEBUG, "IQ-GET: PUBSUB AVATAR OF=%s", to_matrix); Log(LOG_DEBUG, "IQ-GET: PUBSUB AVATAR OF=%s", to_matrix);
@ -513,10 +518,7 @@ IQGet(ParseeData *args, XMLElement *stanza, XMPPThread *thr)
XMLAddChild(reply, ps); XMLAddChild(reply, ps);
} }
pthread_mutex_lock(&jabber->write_lock); XMPPSendStanza(jabber, reply);
XMLEncode(jabber->stream, reply);
StreamFlush(jabber->stream);
pthread_mutex_unlock(&jabber->write_lock);
XMLFreeElement(reply); XMLFreeElement(reply);
Free(to_matrix); Free(to_matrix);
@ -554,10 +556,7 @@ IQGet(ParseeData *args, XMLElement *stanza, XMPPThread *thr)
XMLAddChild(query, version); XMLAddChild(query, version);
XMLAddChild(iq_reply, query); XMLAddChild(iq_reply, query);
pthread_mutex_lock(&jabber->write_lock); XMPPSendStanza(jabber, iq_reply);
XMLEncode(jabber->stream, iq_reply);
StreamFlush(jabber->stream);
pthread_mutex_unlock(&jabber->write_lock);
XMLFreeElement(iq_reply); XMLFreeElement(iq_reply);
} }
else else

View file

@ -370,19 +370,13 @@ end_error:
ps = CreatePubsubRequest( ps = CreatePubsubRequest(
parsee, decode_from, "urn:xmpp:avatar:metadata" parsee, decode_from, "urn:xmpp:avatar:metadata"
); );
pthread_mutex_lock(&jabber->write_lock); XMPPSendStanza(jabber, ps);
XMLEncode(jabber->stream, ps);
StreamFlush(jabber->stream);
pthread_mutex_unlock(&jabber->write_lock);
XMLFreeElement(ps); XMLFreeElement(ps);
ps = CreatePubsubRequest( ps = CreatePubsubRequest(
parsee, trim, "urn:xmpp:avatar:metadata" parsee, trim, "urn:xmpp:avatar:metadata"
); );
pthread_mutex_lock(&jabber->write_lock); XMPPSendStanza(jabber, ps);
XMLEncode(jabber->stream, ps);
StreamFlush(jabber->stream);
pthread_mutex_unlock(&jabber->write_lock);
XMLFreeElement(ps); XMLFreeElement(ps);
if (args->verbosity >= PARSEE_VERBOSE_TIMINGS) if (args->verbosity >= PARSEE_VERBOSE_TIMINGS)
{ {

View file

@ -158,13 +158,17 @@ PresenceStanza(ParseeData *args, XMLElement *stanza, XMPPThread *thr)
char *room = ParseeGetBridgedRoom(args, stanza); char *room = ParseeGetBridgedRoom(args, stanza);
char *decode_from, *real_matrix; char *decode_from, *real_matrix;
char *matrix_user_pl = ParseeEncodeJID(args->config, trim, false); char *matrix_user_pl = ParseeEncodeJID(args->config, trim, false);
char *affiliation = HashMapGet(item->attrs, "affiliation"); char *affiliation = item ? HashMapGet(item->attrs, "affiliation") : NULL;
char *role = HashMapGet(item->attrs, "role"); char *role = item ? HashMapGet(item->attrs, "role") : NULL;
int power_level = 0; int power_level = 0;
char *parsee = ParseeMXID(args); char *parsee = ParseeMXID(args);
char *parsee_j = ParseeJID(args); char *parsee_j = ParseeJID(args);
Free(trim); Free(trim);
if (!item)
{
goto end_item;
}
if (jid) if (jid)
{ {
@ -280,7 +284,7 @@ PresenceStanza(ParseeData *args, XMLElement *stanza, XMPPThread *thr)
Free(chat_id); Free(chat_id);
} }
end_item:
Free(from); Free(from);
Free(decode_from); Free(decode_from);
Free(real_matrix); Free(real_matrix);
@ -376,11 +380,8 @@ PresenceStanza(ParseeData *args, XMLElement *stanza, XMPPThread *thr)
vcard_request = CreateVCardRequest( vcard_request = CreateVCardRequest(
from, HashMapGet(stanza->attrs, "from") from, HashMapGet(stanza->attrs, "from")
); );
pthread_mutex_lock(&jabber->write_lock);
XMLEncode(jabber->stream, vcard_request);
StreamFlush(jabber->stream);
pthread_mutex_unlock(&jabber->write_lock);
XMPPSendStanza(jabber, vcard_request);
XMLFreeElement(vcard_request); XMLFreeElement(vcard_request);
Free(from); Free(from);
} }

View file

@ -45,6 +45,7 @@ typedef struct ParseeConfig {
char *component_host; char *component_host;
char *shared_comp_secret; char *shared_comp_secret;
int component_port; int component_port;
size_t max_stanza_size;
/* ------- DB -------- */ /* ------- DB -------- */
char *db_path; char *db_path;
@ -80,6 +81,7 @@ typedef struct Argument {
const char *description; const char *description;
} Argument; } Argument;
/* A few helpful macros to make JSON less of a PITA */
#define GrabString(obj, ...) JsonValueAsString(JsonGet(obj, __VA_ARGS__)) #define GrabString(obj, ...) JsonValueAsString(JsonGet(obj, __VA_ARGS__))
#define GrabInteger(obj, ...) JsonValueAsInteger(JsonGet(obj, __VA_ARGS__)) #define GrabInteger(obj, ...) JsonValueAsInteger(JsonGet(obj, __VA_ARGS__))
#define GrabBoolean(obj, ...) JsonValueAsBoolean(JsonGet(obj, __VA_ARGS__)) #define GrabBoolean(obj, ...) JsonValueAsBoolean(JsonGet(obj, __VA_ARGS__))
@ -114,6 +116,9 @@ extern void ParseePrintASCII(void);
/** /**
* Checks if two versions of Parsee can be considered "compatible". * Checks if two versions of Parsee can be considered "compatible".
* This is mainly used for things like database operations. TODO:
* Make an auto-upgrade system to comply with the (undocumented)
* rule of "Don't Make The Sysadmin Think About Parsee Too Much".
* --------------- * ---------------
* Modifies: NOTHING */ * Modifies: NOTHING */
extern bool ParseeIsCompatible(char *ver1, char *ver2); extern bool ParseeIsCompatible(char *ver1, char *ver2);

View file

@ -4,7 +4,7 @@
#include <Cytoplasm/Stream.h> #include <Cytoplasm/Stream.h>
/* Creates a string stream writer. The referenced buffer must be in the heap, /* Creates a string stream writer. The referenced buffer must be in the heap,
* or NULL. */ * or NULL for an empty string. */
extern Stream * StrStreamWriter(char **buffer); extern Stream * StrStreamWriter(char **buffer);
/* Creates a string stream reader. The referenced buffer may be everywhere. */ /* Creates a string stream reader. The referenced buffer may be everywhere. */

View file

@ -29,6 +29,13 @@ extern XMPPComponent * XMPPInitialiseCompStream(char *host, int port);
* after XMPPInitialiseCompStream. */ * after XMPPInitialiseCompStream. */
extern bool XMPPAuthenticateCompStream(XMPPComponent *comp, char *shared); extern bool XMPPAuthenticateCompStream(XMPPComponent *comp, char *shared);
/** Writes an XML stanza through a component, while making sure any locking
* work is done.
* -----------------------
* Modifies: {comp}, the XMPP stream
* See-Also: XMPPInitialiseCompStream, XMPPAuthenticateCompStream, XMPP-core RFC */
extern void XMPPSendStanza(XMPPComponent *comp, XMLElement *stanza);
/* Makes a user join/leave a MUC */ /* Makes a user join/leave a MUC */
extern bool XMPPJoinMUC(XMPPComponent *comp, char *fr, char *muc, char *hash, int secs, bool ret); extern bool XMPPJoinMUC(XMPPComponent *comp, char *fr, char *muc, char *hash, int secs, bool ret);
extern void XMPPLeaveMUC(XMPPComponent *comp, char *fr, char *muc, char *r); extern void XMPPLeaveMUC(XMPPComponent *comp, char *fr, char *muc, char *r);

View file

@ -1,35 +0,0 @@
# Makefile for building Parsee
# ================================
# TODO: Consider making something akin to a configure script that checks
# for dependencies, or maybe even use *autoconf* (the devil!)
# =========================== Parsee Flags =============================
NAME=Parsee
VERSION=0.0.0
REPOSITORY=$(shell git remote get-url origin)
# =========================== Compilation Flags ============================
CYTO_INC=/usr/local/include/ # Where Cytoplasm's include path is
# located.
CYTO_LIB=/usr/local/lib # Where's Cytoplasm's library is
# located.
SOURCE=.
OBJECT=out
CC=cc
CFLAGS=-I$(SOURCE) -I$(CYTO_INC) -DNAME="\"$(NAME)\"" -DVERSION="\"$(VERSION)\"" -DREPOSITORY=\"$(REPOSITORY)\" -g -ggdb -Wall -Werror
LDFLAGS=-L $(CYTO_LIB) -lCytoplasm -g -ggdb
# ============================ Compilation =================================
SRC_FILES:=$(shell find $(SOURCE) -name '*.c')
OBJ_FILES:=${subst $(SOURCE)/,$(OBJECT)/,$(patsubst %.c, %, $(SRC_FILES))}
all: $(OBJ_FILES)
$(OBJECT)/%: $(SOURCE)/%.c
@mkdir -p $(shell dirname "$@")
$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@
clean:
rm -rf $(OBJECT)