#define HAVE_XML_STOPPARSER
#endif
-struct xmpp_event *xmpp_queue = NULL;
HashList *XMPP_StartHandlers = NULL;
HashList *XMPP_EndHandlers = NULL;
+HashList *XMPP_SupportedNamespaces = NULL;
+HashList *XMPP_NameSpaces = NULL;
+HashList *FlatToken = NULL;
int XMPPSrvDebugEnable = 0;
{
StrBufAppendBufPlain(XMPP->OutBuf, Str, Len, 0);
}
-#define XPUT(CONSTSTR) XPut(CONSTSTR, sizeof(CONSTSTR) -1)
void XPrintf(const char *Format, ...)
{
}
+void XPrint(const char *Token, long tlen,
+ int Flags,
+ ...)
+
+{
+ int BodySeen = 0;
+ int ArgType;
+ int Finished = 0;
+ char *PName;
+ long PLen;
+ char *Val;
+ long VLen;
+ va_list arg_ptr;
+
+ XPUT("<");
+ XPut(Token, tlen);
+
+ va_start(arg_ptr, Flags);
+ while (!Finished)
+ {
+ ArgType = va_arg(arg_ptr, int);
+ switch (ArgType)
+ {
+ case TYPE_STR:
+ PName = va_arg(arg_ptr, char*);
+ PLen = va_arg(arg_ptr, long);
+ Val = va_arg(arg_ptr, char*);
+ VLen = va_arg(arg_ptr, long);
+ XPUT(" ");
+ XPut(PName, PLen);
+ XPUT("=\"");
+ XPutProp(Val, VLen);
+ XPUT("\"");
+ break;
+ case TYPE_OPTSTR:
+ PName = va_arg(arg_ptr, char*);
+ PLen = va_arg(arg_ptr, long);
+ Val = va_arg(arg_ptr, char*);
+ VLen = va_arg(arg_ptr, long);
+ if (VLen > 0)
+ {
+ XPUT(" ");
+ XPut(PName, PLen);
+ XPUT("=\"");
+ XPutProp(Val, VLen);
+ XPUT("\"");
+ }
+ break;
+ case TYPE_INT:
+ PName = va_arg(arg_ptr, char*);
+ PLen = va_arg(arg_ptr, long);
+ VLen = va_arg(arg_ptr, long);
+ XPUT(" ");
+ XPut(PName, PLen);
+ XPUT("=\"");
+ XPrintf("%ld", VLen);
+ XPUT("\"");
+ break;
+ case TYPE_BODYSTR:
+ BodySeen = 1;
+ XPUT(">");
+ Val = va_arg(arg_ptr, char*);
+ VLen = va_arg(arg_ptr, long);
+ XPutBody(Val, VLen);
+ break;
+ case TYPE_ARGEND:
+ Finished = 1;
+ break;
+ }
+ }
+ if (Flags == XCLOSED)
+ {
+ if (BodySeen)
+ {
+ XPUT("</");
+ XPut(Token, tlen);
+ XPUT(">");
+ }
+ else
+ {
+ XPUT("></");
+ XPut(Token, tlen);
+ XPUT(">");
+ }
+ }
+ else
+ XPUT(">");
+ va_end(arg_ptr);
+}
+
#ifdef HAVE_XML_STOPPARSER
/* Stop the parser if an entity declaration is hit. */
static void xmpp_entity_declaration(void *userData, const XML_Char *entityName,
/*
* TLS encryption (but only if it isn't already active)
*/
+/*
#ifdef HAVE_OPENSSL
if (!CC->redirect_ssl) {
XPUT("<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'></starttls>");
}
#endif
-
+*/
if (!CC->logged_in) {
/* If we're not logged in yet, offer SASL as our feature set */
xmpp_output_auth_mechs();
XMPP->bind_requested = 1;
}
-void xmpp_start_iq(void *data, const char *supplied_el, const char **attr)
-{
- int i;
- for (i=0; attr[i] != NULL; i+=2) {
- if (!strcasecmp(attr[i], "type")) {
- safestrncpy(XMPP->iq_type, attr[i+1], sizeof XMPP->iq_type);
- }
- else if (!strcasecmp(attr[i], "id")) {
- safestrncpy(XMPP->iq_id, attr[i+1], sizeof XMPP->iq_id);
- }
- else if (!strcasecmp(attr[i], "from")) {
- safestrncpy(XMPP->iq_from, attr[i+1], sizeof XMPP->iq_from);
- }
- else if (!strcasecmp(attr[i], "to")) {
- safestrncpy(XMPP->iq_to, attr[i+1], sizeof XMPP->iq_to);
- }
- }
-}
-
void xmpp_start_auth(void *data, const char *supplied_el, const char **attr)
{
int i;
}
}
}
-
+/*
void xmpp_start_message(void *data, const char *supplied_el, const char **attr)
{
int i;
}
}
}
-
+*/
void xmpp_start_html(void *data, const char *supplied_el, const char **attr)
{
++XMPP->html_tag_level;
void xmpp_xml_start(void *data, const char *supplied_el, const char **attr)
{
- char el[256];
- long newlen;
+ HashList *ThisNamespace = NULL;
+ const char *pToken;
+ const char *pch;
+ const char *NS = NULL;
+ long NSLen;
long len;
- char *sep = NULL;
void *pv;
/* Axe the namespace, we don't care about it */
- newlen = len = safestrncpy(el, supplied_el, sizeof el);
- while (sep = strchr(el, ':'), sep)
+ pToken = supplied_el;
+ pch = strchr(pToken, ':');
+ while (pch != NULL)
{
- newlen -= ++sep - el;
- memmove(el, sep, newlen + 1);
- len = newlen;
+ pToken = pch;
+ pch = strchr(pToken + 1, ':');
}
+ if (*pToken == ':')
+ {
+ NS = supplied_el;
+ NSLen = pToken - supplied_el;
+ if (GetHash(XMPP_NameSpaces, NS, NSLen, &pv))
+ {
+ ThisNamespace = pv;
+
+ }
+
+ pToken ++;
+ }
+
+ len = strlen(pToken);
+
+
+ if (ThisNamespace != NULL)
+ {
+ if (GetHash(ThisNamespace, pToken, len, &pv))
+ {
+ TokenHandler *th;
+ void *value;
+ long i = 0;
+
+ th = (TokenHandler*) pv;
+ value = th->GetToken();
+
+ while (attr[i] != NULL)
+ {
+
+ if (GetHash(th->Properties, attr[i], strlen(attr[i]), &pv))
+ {
+ PropertyHandler* ph = pv;
+ char *val;
+ StrBuf **pVal;
+ long len;
+
+ len = strlen(attr[i+1]);
+ val = value;
+ val += ph->offset;
+ pVal = (StrBuf**) val;
+ if (*pVal != NULL)
+ StrBufPlain(*pVal, attr[i+1], len);
+ else
+ *pVal = NewStrBufPlain(attr[i+1], len);
+ }
+ i+=2;
+ }
+ return;
+ }
+
+ }
/*
XMPP_syslog(LOG_DEBUG, "XMPP ELEMENT START: <%s>\n", el);
for (i=0; attr[i] != NULL; i+=2) {
}
uncomment for more verbosity */
- if (GetHash(XMPP_StartHandlers, el, len, &pv))
+ if (GetHash(XMPP_StartHandlers, pToken, len, &pv))
{
xmpp_handler *h;
h = (xmpp_handler*) pv;
/*
* iq type="get" (handle queries)
*/
- if (!strcasecmp(Xmpp->iq_type, "get"))
+ if (!strcasecmp(ChrPtr(Xmpp->IQ.type), "get"))
{
/*
* Query on a namespace
*/
if (!IsEmptyStr(Xmpp->iq_query_xmlns)) {
- xmpp_query_namespace(Xmpp->iq_id, Xmpp->iq_from,
- Xmpp->iq_to, Xmpp->iq_query_xmlns);
+ xmpp_query_namespace(&Xmpp->IQ, Xmpp->iq_query_xmlns);
}
/*
*/
else if (Xmpp->ping_requested) {
XPUT("<iq type=\"result\" ");
- if (!IsEmptyStr(Xmpp->iq_from)) {
+ if (StrLength(Xmpp->IQ.from) > 0) {
XPUT("to=\"");
- XPutProp(Xmpp->iq_from, strlen(Xmpp->iq_from));
+ XPutSProp(Xmpp->IQ.from);
XPUT("\" ");
}
- if (!IsEmptyStr(Xmpp->iq_to)) {
+ if (StrLength(Xmpp->IQ.to)>0) {
XPUT("from=\"");
- XPutProp(Xmpp->iq_to, strlen(Xmpp->iq_to));
+ XPutSProp(Xmpp->IQ.to);
XPUT("\" ");
}
XPUT("id=\"");
- XPutProp(Xmpp->iq_id, strlen(Xmpp->iq_id));
+ XPutSProp(Xmpp->IQ.id);
XPUT("\"/>");
}
);
*/
XPUT("<iq type=\"error\" id=\"");
- XPutProp(Xmpp->iq_id, strlen(Xmpp->iq_id));
+ XPutSProp(Xmpp->IQ.id);
XPUT("\">"
"<error code=\"503\" type=\"cancel\">"
"<service-unavailable xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\"/>"
* Non SASL authentication
*/
else if (
- (!strcasecmp(Xmpp->iq_type, "set"))
+ (!strcasecmp(ChrPtr(Xmpp->IQ.type), "set"))
&& (!strcasecmp(Xmpp->iq_query_xmlns, "jabber:iq:auth:query"))
) {
xmpp_non_sasl_authenticate(
- Xmpp->iq_id,
+ Xmpp->IQ.id,
Xmpp->iq_client_username,
Xmpp->iq_client_password,
Xmpp->iq_client_resource
*/
else if (
(Xmpp->bind_requested)
- && (!IsEmptyStr(Xmpp->iq_id))
+ && (StrLength(Xmpp->IQ.id)>0)
&& (!IsEmptyStr(Xmpp->iq_client_resource))
&& (CC->logged_in)
) {
/* Tell the client what its JID is */
XPUT("<iq type=\"result\" id=\"");
- XPutProp(Xmpp->iq_id, strlen(Xmpp->iq_id));
+ XPutSProp(Xmpp->IQ.id);
XPUT("\">"
"<bind xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\">");
XPUT("<jid>");
else if (Xmpp->iq_session) {
XPUT("<iq type=\"result\" id=\"");
- XPutProp(Xmpp->iq_id, strlen(Xmpp->iq_id));
+ XPutSProp(Xmpp->IQ.id);
XPUT("\">"
"</iq>");
}
else {
XPUT("<iq type=\"error\" id=\"");
- XPutProp(Xmpp->iq_id, strlen(Xmpp->iq_id));
+ XPutSProp(Xmpp->IQ.id);
XPUT("\">");
XPUT("<error>Don't know howto do '");
- XPutBody(Xmpp->iq_type, strlen(Xmpp->iq_type));
+ XPutBody(SKEY(Xmpp->IQ.type));
XPUT("'!</error>"
"</iq>");
}
/* Now clear these fields out so they don't get used by a future stanza */
- Xmpp->iq_id[0] = 0;
- Xmpp->iq_from[0] = 0;
- Xmpp->iq_to[0] = 0;
- Xmpp->iq_type[0] = 0;
+ FlushStrBuf(Xmpp->IQ.id);
+ FlushStrBuf(Xmpp->IQ.from);
+ FlushStrBuf(Xmpp->IQ.to);
+ FlushStrBuf(Xmpp->IQ.type);
Xmpp->iq_client_resource[0] = 0;
Xmpp->iq_session = 0;
Xmpp->iq_query_xmlns[0] = 0;
void xmpp_xml_end(void *data, const char *supplied_el)
{
- char el[256];
+ const char *pToken;
+ const char *pch;
long len;
- long newlen;
- char *sep = NULL;
void *pv;
/* Axe the namespace, we don't care about it */
- newlen = len = safestrncpy(el, supplied_el, sizeof el);
- while (sep = strchr(el, ':'), sep) {
-
- newlen -= ++sep - el;
- memmove(el, sep, newlen + 1);
- len = newlen;
+ pToken = supplied_el;
+ pch = strchr(pToken, ':');
+ while (pch != NULL)
+ {
+ pToken = pch;
+ pch = strchr(pToken + 1, ':');
}
+ if (*pToken == ':')
+ pToken ++;
+
+ len = strlen(pToken);
+
/*
XMPP_syslog(LOG_DEBUG, "XMPP ELEMENT END : <%s>\n", el);
if (XMPP->chardata_len > 0) {
}
uncomment for more verbosity */
- if (GetHash(XMPP_EndHandlers, el, len, &pv))
+ if (GetHash(XMPP_EndHandlers, pToken, len, &pv))
{
xmpp_handler *h;
h = (xmpp_handler*) pv;
}
else
{
- XMPP_syslog(LOG_DEBUG, "Ignoring unknown tag <%s>\n", el);
+ XMPP_syslog(LOG_DEBUG, "Ignoring unknown tag <%s>\n", pToken);
}
XMPP->chardata_len = 0;
free(XMPP->message_body);
}
}
+ free_buf_iq(&XMPP->IQ);
+
XML_ParserFree(XMPP->xp);
FreeStrBuf(&XMPP->OutBuf);
free(XMPP);
XMPPSrvDebugEnable = n;
}
const char *CitadelServiceXMPP="XMPP";
-extern void xmpp_cleanup_events(void);
Put(XMPP_EndHandlers, key, len, h, NULL);
}
+void HFreePropertyHandler(void *FreeMe)
+{
+ free(FreeMe);
+}
+
+void HDeleteTokenHandler(void *FreeMe)
+{
+ TokenHandler *th = (TokenHandler *) FreeMe;
+ DeleteHash(&th->Properties);
+ free(th);
+}
+
+void XMPP_RegisterTokenProperty(const char *NS, long NSLen,
+ const char *Token, long TLen,
+ const char *Property, long PLen,
+ GetTokenDataFunc GetToken,
+ long offset)
+{
+ void *pv;
+ HashList *ThisNamespace = NULL;
+ PropertyHandler *h;
+ TokenHandler *th;
+
+ h = (PropertyHandler*) malloc(sizeof(PropertyHandler));
+ h->NameSpace = NS;
+ h->NameSpaceLen = NSLen;
+ h->Token = Token;
+ h->TokenLen = TLen;
+ h->Property = Property;
+ h->PropertyLen = PLen;
+ h->offset = offset;
+
+ if (!GetHash(XMPP_SupportedNamespaces, NS, NSLen, &pv))
+ {
+ Put(XMPP_SupportedNamespaces, NS, NSLen, NewStrBufPlain(NS, NSLen), HFreeStrBuf);
+ }
+
+
+ if (GetHash(XMPP_NameSpaces, NS, NSLen, &pv))
+ {
+ ThisNamespace = pv;
+ }
+ else
+ {
+ ThisNamespace = NewHash(1, NULL);
+ Put(XMPP_NameSpaces, NS, NSLen, ThisNamespace, HDeleteHash);
+ }
+
+ if (GetHash(ThisNamespace, Token, TLen, &pv))
+ {
+ th = pv;
+ }
+ else
+ {
+ th = (TokenHandler*) malloc (sizeof(TokenHandler));
+ th->GetToken = GetToken;
+ th->Properties = NewHash(1, NULL);
+ Put(ThisNamespace, Token, TLen, th, HDeleteTokenHandler);
+ }
+
+
+ if (PLen > 0)
+ Put(th->Properties, Property, PLen, h, HFreePropertyHandler);
+ /*
+ if (!GetHash(FlatToken, Token, TLen, &pv))
+ {
+ // todo mark pv as non uniq
+ Put(FlatToken, Token, TLen, ThisToken, reference_free_handler);
+ }
+ */
+}
+
+void xmpp_cleanup(void)
+{
+ DeleteHash(&XMPP_StartHandlers);
+ DeleteHash(&XMPP_EndHandlers);
+ DeleteHash(&XMPP_SupportedNamespaces);
+ DeleteHash(&XMPP_NameSpaces);
+ DeleteHash(&FlatToken);
+}
+
CTDL_MODULE_INIT(xmpp)
{
if (!threading) {
XMPP_StartHandlers = NewHash(1, NULL);
XMPP_EndHandlers = NewHash(1, NULL);
+ XMPP_NameSpaces = NewHash(1, NULL);
+ XMPP_SupportedNamespaces = NewHash(1, NULL);
+ FlatToken = NewHash(1, NULL);
AddXMPPEndHandler(HKEY("resource"), xmpp_end_resource, 0);
AddXMPPEndHandler(HKEY("username"), xmpp_end_username, 0);
AddXMPPStartHandler(HKEY("stream"), xmpp_stream_start, 0);
AddXMPPStartHandler(HKEY("query"), xmpp_start_query, 0);
AddXMPPStartHandler(HKEY("bind"), xmpp_start_bind, 0);
- AddXMPPStartHandler(HKEY("iq"), xmpp_start_iq, 0);
AddXMPPStartHandler(HKEY("auth"), xmpp_start_auth, 0);
- AddXMPPStartHandler(HKEY("message"), xmpp_start_message, 0);
+/// AddXMPPStartHandler(HKEY("message"), xmpp_start_message, 0);
AddXMPPStartHandler(HKEY("html"), xmpp_start_html, 0);
CtdlRegisterSessionHook(xmpp_logout_hook, EVT_LOGOUT, PRIO_LOGOUT + 90);
CtdlRegisterSessionHook(xmpp_login_hook, EVT_UNSTEALTH, PRIO_UNSTEALTH + 1);
CtdlRegisterSessionHook(xmpp_logout_hook, EVT_STEALTH, PRIO_STEALTH + 1);
- CtdlRegisterCleanupHook(xmpp_cleanup_events);
-
+ CtdlRegisterCleanupHook(xmpp_cleanup);
}
/* return our module name for the log */
return "xmpp";
}
+
+