/* loop through both a and b comparing everything, attribs, cdata, children, etc */ int xode_cmp(xode a, xode b) { int ret = 0; while(1) { if(a == NULL && b == NULL) return 0; if(a == NULL || b == NULL) return -1; if(xode_get_type(a) != xode_get_type(b)) return -1; switch(xode_get_type(a)) { case XODE_TYPE_ATTRIB: ret = _xode_strcmp(xode_get_name(a), xode_get_name(b)); if(ret != 0) return -1; ret = _xode_strcmp(xode_get_data(a), xode_get_data(b)); if(ret != 0) return -1; break; case XODE_TYPE_TAG: ret = _xode_strcmp(xode_get_name(a), xode_get_name(b)); if(ret != 0) return -1; ret = xode_cmp(xode_get_firstattrib(a), xode_get_firstattrib(b)); if(ret != 0) return -1; ret = xode_cmp(xode_get_firstchild(a), xode_get_firstchild(b)); if(ret != 0) return -1; break; case XODE_TYPE_CDATA: ret = _xode_strcmp(xode_get_data(a), xode_get_data(b)); if(ret != 0) return -1; } a = xode_get_nextsibling(a); b = xode_get_nextsibling(b); } }
/* return the cdata from any tag */ char *xode_get_tagdata(xode parent, const char *name) { xode tag; tag = xode_get_tag(parent, name); if(tag == NULL) return NULL; return xode_get_data(tag); }
static xode_spool _xode_tospool(xode node) { xode_spool s; int level=0,dir=0; xode tmp; if(!node || xode_get_type(node) != XODE_TYPE_TAG) return NULL; s = xode_spool_newfrompool(xode_get_pool(node)); if(!s) return(NULL); while(1) { if(dir==0) { if(xode_get_type(node) == XODE_TYPE_TAG) { if(xode_has_children(node)) { _xode_tag2str(s,node,1); node = xode_get_firstchild(node); level++; continue; } else { _xode_tag2str(s,node,0); } } else { xode_spool_add(s,xode_strescape(xode_get_pool(node),xode_get_data(node))); } } tmp = xode_get_nextsibling(node); if(!tmp) { node = xode_get_parent(node); level--; if(level>=0) _xode_tag2str(s,node,2); if(level<1) break; dir = 1; } else { node = tmp; dir = 0; } } return s; }
void _xode_to_prettystr( xode_spool s, xode x, int deep ) { int i; xode y; if(xode_get_type(x) != XODE_TYPE_TAG) return; for(i=0; i<deep; i++) xode_spool_add(s, "\t"); xode_spooler( s , "<" , xode_get_name(x) , s ); y = xode_get_firstattrib(x); while( y ) { xode_spooler( s , " " , xode_get_name(y) , "='", xode_get_data(y) , "'" , s ); y = xode_get_nextsibling( y ); } xode_spool_add(s,">"); xode_spool_add(s,"\n"); if( xode_get_data(x)) { for(i=0; i<=deep; i++) xode_spool_add(s, "\t"); xode_spool_add( s , xode_get_data(x)); } y = xode_get_firstchild(x); while( y ) { _xode_to_prettystr(s , y, deep+1); y = xode_get_nextsibling(y); xode_spool_add(s,"\n"); } for(i=0; i<deep; i++) xode_spool_add(s, "\t"); xode_spooler( s , "</" , xode_get_name(x) , ">" , s ); return; }
/* places copy of node and node's siblings in parent */ void xode_insert_node(xode parent, xode node) { if(node == NULL || parent == NULL) return; while(node != NULL) { switch(xode_get_type(node)) { case XODE_TYPE_ATTRIB: xode_put_attrib(parent, xode_get_name(node), xode_get_data(node)); break; case XODE_TYPE_TAG: xode_insert_tagnode(parent, node); break; case XODE_TYPE_CDATA: xode_insert_cdata(parent, xode_get_data(node), xode_get_datasz(node)); } node = xode_get_nextsibling(node); } }
/** * parse incoming message from Jabber server */ int xj_manage_jab(char *buf, int len, int *pos, xj_jalias als, xj_jcon jbc) { int j, err=0; char *p, *to, *from, *msg, *type, *emsg, *ecode, lbuf[4096], fbuf[128]; xj_jconf jcf = NULL; str ts, tf; xode x, y, z; str *sid; xj_pres_cell prc = NULL; if(!jbc) return -1; sid = jbc->jkey->id; x = xode_from_strx(buf, len, &err, &j); #ifdef XJ_EXTRA_DEBUG DBG("XJAB:xj_parse_jab: XODE ret:%d pos:%d\n", err, j); #endif if(err && pos != NULL) *pos= j; if(x == NULL) return -1; lbuf[0] = 0; ecode = NULL; /******************** XMPP 'MESSAGE' HANDLING **********************/ if(!strncasecmp(xode_get_name(x), "message", 7)) { #ifdef XJ_EXTRA_DEBUG DBG("XJAB:xj_manage_jab: jabber [message] received\n"); #endif if((to = xode_get_attrib(x, "to")) == NULL) { #ifdef XJ_EXTRA_DEBUG DBG("XJAB:xj_manage_jab: missing 'to' attribute\n"); #endif err = -1; goto ready; } if((from = xode_get_attrib(x, "from")) == NULL) { #ifdef XJ_EXTRA_DEBUG DBG("XJAB:xj_manage_jab: missing 'from' attribute\n"); #endif err = -1; goto ready; } if((y = xode_get_tag(x, "body")) == NULL || (msg = xode_get_data(y)) == NULL) { #ifdef XJ_EXTRA_DEBUG DBG("XJAB:xj_manage_jab: missing 'body' of message\n"); #endif err = -1; goto ready; } type = xode_get_attrib(x, "type"); if(type != NULL && !strncasecmp(type, "error", 5)) { if((y = xode_get_tag(x, "error")) == NULL || (emsg = xode_get_data(y)) == NULL) strcpy(lbuf, "{Error sending following message} - "); else { ecode = xode_get_attrib(y, "code"); strcpy(lbuf, "{Error ("); if(ecode != NULL) { strcat(lbuf, ecode); strcat(lbuf, " - "); } strcat(lbuf, emsg); strcat(lbuf, ") when trying to send following message}"); } } // is from a conference?!?! if((jcf=xj_jcon_check_jconf(jbc, from))!=NULL) { if(lbuf[0] == 0) { p = from + strlen(from); while(p>from && *p != '/') p--; if(*p == '/') { if(jcf->nick.len>0 && strlen(p+1) == jcf->nick.len && !strncasecmp(p+1, jcf->nick.s, jcf->nick.len)) { #ifdef XJ_EXTRA_DEBUG DBG("XJAB:xj_manage_jab: message sent by myself\n"); #endif goto ready; } lbuf[0] = '['; lbuf[1] = 0; strcat(lbuf, p+1); strcat(lbuf, "] "); } } else { jcf->status = XJ_JCONF_NULL; xj_jcon_jconf_presence(jbc,jcf,NULL,"online"); } strcat(lbuf, msg); ts.s = lbuf; ts.len = strlen(lbuf); if(xj_send_sip_msg(als->proxy, sid, &jcf->uri, &ts, &jbc->jkey->flag)<0) DBG("XJAB:xj_manage_jab: ERROR SIP MESSAGE was not sent!\n"); #ifdef XJ_EXTRA_DEBUG else DBG("XJAB:xj_manage_jab: SIP MESSAGE was sent!\n"); #endif goto ready; } strcat(lbuf, msg); ts.s = from; ts.len = strlen(from); tf.s = fbuf; tf.len = 0; if(xj_address_translation(&ts, &tf, als, XJ_ADDRTR_J2S) == 0) { ts.s = lbuf; ts.len = strlen(lbuf); if(xj_send_sip_msg(als->proxy, sid, &tf, &ts, &jbc->jkey->flag)<0) DBG("XJAB:xj_manage_jab: ERROR SIP MESSAGE was not sent ...\n"); #ifdef XJ_EXTRA_DEBUG else DBG("XJAB:xj_manage_jab: SIP MESSAGE was sent.\n"); #endif } goto ready; } /*------------------- END 'MESSAGE' HANDLING ----------------------*/ /******************** XMPP 'PRESENCE' HANDLING *********************/ if(!strncasecmp(xode_get_name(x), "presence", 8)) { #ifdef XJ_EXTRA_DEBUG DBG("XJAB:xj_manage_jab: jabber [presence] received\n"); #endif type = xode_get_attrib(x, "type"); from = xode_get_attrib(x, "from"); if(from == NULL) goto ready; ts.s = from; p = from; while(p<from + strlen(from) && *p != '/') p++; if(*p == '/') ts.len = p - from; else ts.len = strlen(from); if(type == NULL || !strncasecmp(type, "online", 6) || !strncasecmp(type, "available", 9)) { if(strchr(from, '@') == NULL) { if(!strncasecmp(from, XJ_AIM_NAME, XJ_AIM_LEN)) { jbc->ready |= XJ_NET_AIM; #ifdef XJ_EXTRA_DEBUG DBG("XJAB:xj_manage_jab: AIM network ready\n"); #endif } else if(!strncasecmp(from, XJ_ICQ_NAME, XJ_ICQ_LEN)) { jbc->ready |= XJ_NET_ICQ; #ifdef XJ_EXTRA_DEBUG DBG("XJAB:xj_manage_jab: ICQ network ready\n"); #endif } else if(!strncasecmp(from, XJ_MSN_NAME, XJ_MSN_LEN)) { jbc->ready |= XJ_NET_MSN; #ifdef XJ_EXTRA_DEBUG DBG("XJAB:xj_manage_jab: MSN network ready\n"); #endif } else if(!strncasecmp(from, XJ_YAH_NAME, XJ_YAH_LEN)) { jbc->ready |= XJ_NET_YAH; #ifdef XJ_EXTRA_DEBUG DBG("XJAB:xj_manage_jab: YAHOO network ready\n"); #endif } } else if((jcf=xj_jcon_check_jconf(jbc, from))!=NULL) { jcf->status = XJ_JCONF_READY; #ifdef XJ_EXTRA_DEBUG DBG("XJAB:xj_manage_jab: %s conference ready\n", from); #endif } else { #ifdef XJ_EXTRA_DEBUG DBG("XJAB:xj_manage_jab: user <%.*s> is online\n",ts.len,ts.s); #endif prc = xj_pres_list_check(jbc->plist, &ts); if(prc) { if(prc->state != XJ_PS_ONLINE) { prc->state = XJ_PS_ONLINE; goto call_pa_cbf; } } else { #ifdef XJ_EXTRA_DEBUG DBG("XJAB:xj_manage_jab: user state received - creating" " presence cell for [%.*s]\n", ts.len, ts.s); #endif prc = xj_pres_cell_new(); if(prc == NULL) { DBG("XJAB:xj_manage_jab: cannot create presence" " cell for [%s]\n", from); goto ready; } if(xj_pres_cell_init(prc, &ts, NULL, NULL)<0) { DBG("XJAB:xj_manage_jab: cannot init presence" " cell for [%s]\n", from); xj_pres_cell_free(prc); goto ready; } prc = xj_pres_list_add(jbc->plist, prc); if(prc) { prc->state = XJ_PS_ONLINE; goto call_pa_cbf; } } } goto ready; } if(strchr(from, '@') == NULL) goto ready; if(!strncasecmp(type, "error", 5)) { if((jcf=xj_jcon_check_jconf(jbc, from))!=NULL) { tf.s = from; tf.len = strlen(from); if((y = xode_get_tag(x, "error")) == NULL) goto ready; if ((p = xode_get_attrib(y, "code")) != NULL && atoi(p) == 409) { xj_send_sip_msgz(als->proxy, sid, &tf, XJ_DMSG_ERR_JCONFNICK, &jbc->jkey->flag); goto ready; } xj_send_sip_msgz(als->proxy,sid,&tf,XJ_DMSG_ERR_JCONFREFUSED, &jbc->jkey->flag); } goto ready; } if(type!=NULL && !strncasecmp(type, "subscribe", 9)) { xj_jcon_send_presence(jbc, from, "subscribed", NULL, NULL); goto ready; } prc = xj_pres_list_check(jbc->plist, &ts); if(!prc) goto ready; if(!strncasecmp(type, "unavailable", 11)) { #ifdef XJ_EXTRA_DEBUG DBG("XJAB:xj_manage_jab: user <%s> is offline\n", from); #endif if(prc->state != XJ_PS_OFFLINE) { prc->state = XJ_PS_OFFLINE; goto call_pa_cbf; } goto ready; } if(!strncasecmp(type, "unsubscribed", 12)) { #ifdef XJ_EXTRA_DEBUG DBG("XJAB:xj_manage_jab: user <%s> does not allow to see his" " presence status\n", from); #endif if(prc->state != XJ_PS_REFUSED) { prc->state = XJ_PS_REFUSED; goto call_pa_cbf; } } // ignoring unknown types goto ready; } /*------------------- END XMPP 'PRESENCE' HANDLING ----------------*/ /******************** XMPP 'IQ' HANDLING ***************************/ if(!strncasecmp(xode_get_name(x), "iq", 2)) { #ifdef XJ_EXTRA_DEBUG DBG("XJAB:xj_manage_jab: jabber [iq] received\n"); #endif if(!strncasecmp(xode_get_attrib(x, "type"), "result", 6)) { if((y = xode_get_tag(x, "query?xmlns=jabber:iq:roster")) == NULL) goto ready; z = xode_get_firstchild(y); while(z) { if(!strncasecmp(xode_get_name(z), "item", 5) && (from = xode_get_attrib(z, "jid")) != NULL) { if(strchr(from, '@') == NULL) { // transports if(!strncasecmp(from, XJ_AIM_NAME, XJ_AIM_LEN)) { jbc->allowed |= XJ_NET_AIM; #ifdef XJ_EXTRA_DEBUG DBG("XJAB:xj_manage_jab:AIM network available\n"); #endif } else if(!strncasecmp(from, XJ_ICQ_NAME, XJ_ICQ_LEN)) { jbc->allowed |= XJ_NET_ICQ; #ifdef XJ_EXTRA_DEBUG DBG("XJAB:xj_manage_jab:ICQ network available\n"); #endif } else if(!strncasecmp(from, XJ_MSN_NAME, XJ_MSN_LEN)) { jbc->allowed |= XJ_NET_MSN; #ifdef XJ_EXTRA_DEBUG DBG("XJAB:xj_manage_jab:MSN network available\n"); #endif } else if(!strncasecmp(from, XJ_YAH_NAME, XJ_YAH_LEN)) { jbc->allowed |= XJ_NET_YAH; #ifdef XJ_EXTRA_DEBUG DBG("XJAB:xj_manage_jab:YAHOO network available\n"); #endif } goto next_sibling; } } next_sibling: z = xode_get_nextsibling(z); } } goto ready; } /*------------------- END XMPP 'IQ' HANDLING ----------------------*/ call_pa_cbf: if(prc && prc->cbf) { // call the PA callback function tf.s = fbuf; tf.len = 0; if(xj_address_translation(&ts,&tf,als,XJ_ADDRTR_J2S)==0) { #ifdef XJ_EXTRA_DEBUG DBG("XJAB:xj_manage_jab: calling CBF(%.*s,%d)\n", tf.len, tf.s, prc->state); #endif (*(prc->cbf))(&tf, &tf, prc->state, prc->cbp); } } ready: xode_free(x); return err; }
static void stream_node_callback(int type, xode node, void *arg) { struct xmpp_private_data *priv = (struct xmpp_private_data *) arg; char *id, *hash, *tag; char buf[4096]; xode x; LM_DBG("stream callback: %d: %s\n", type, node ? xode_get_name(node) : "n/a"); switch (type) { case XODE_STREAM_ROOT: id = xode_get_attrib(node, "id"); snprintf(buf, sizeof(buf), "%s%s", id, xmpp_password); hash = shahash(buf); x = xode_new_tag("handshake"); xode_insert_cdata(x, hash, -1); xode_send(priv->fd, x); xode_free(x); break; case XODE_STREAM_NODE: tag = xode_get_name(node); if (!strcmp(tag, "handshake")) { LM_DBG("handshake succeeded\n"); } else if (!strcmp(tag, "message")) { LM_DBG("XMPP IM received\n"); char *from = xode_get_attrib(node, "from"); char *to = xode_get_attrib(node, "to"); char *type = xode_get_attrib(node, "type"); xode body = xode_get_tag(node, "body"); char *msg; if (!type) type = "chat"; if (!strcmp(type, "error")) { LM_DBG("received message error stanza\n"); goto out; } if (!from || !to || !body) { LM_DBG("invalid <message/> attributes\n"); goto out; } if (!(msg = xode_get_data(body))) msg = ""; xmpp_send_sip_msg( encode_uri_xmpp_sip(from), decode_uri_xmpp_sip(to), msg); } else if (!strcmp(tag, "presence")) { /* call presence callbacks */ LM_DBG("XMPP Presence received\n"); run_xmpp_callbacks(XMPP_RCV_PRESENCE, xode_to_str(node)); }else if (!strcmp(tag, "iq")) { /* call presence callbacks */ LM_DBG("XMPP IQ received\n"); run_xmpp_callbacks(XMPP_RCV_IQ, xode_to_str(node)); } break; case XODE_STREAM_ERROR: LM_ERR("stream error\n"); /* fall-through */ case XODE_STREAM_CLOSE: priv->running = 0; break; } out: xode_free(node); }
tt_user *users_read(const char *jid) { tt_user *user; xode cfg, x; char *file, *temp; if (jid == NULL) return NULL; if ((file = malloc(strlen(config_dir) + strlen(jid) + 2)) == NULL) { perror("malloc()"); exit(1); } sprintf(file, "%s/%s", config_dir, jid); my_debug(0, "users: Wczytuje plik %s", file); if ((cfg = xode_from_file(file)) == NULL) { my_debug(0, "users: Nie moge wczytac usera"); return NULL; } user = (tt_user*)malloc(sizeof(tt_user)); memset(user, 0, sizeof(tt_user)); x = xode_get_tag(cfg, "jid"); temp = xode_get_data(x); my_strcpy(user->jid, temp); x = xode_get_tag(cfg, "tid"); temp = xode_get_data(x); my_strcpy(user->tid_short, temp); user->tid = malloc(strlen(user->tid_short) + strlen("@tlen.pl") + 1); sprintf(user->tid, "*****@*****.**", user->tid_short); x = xode_get_tag(cfg, "password"); temp = xode_get_data(x); my_strcpy(user->password, temp); user->tlen_sesja = NULL; user->tlen_loged = 0; user->last_ping_time = 0; user->roster = NULL; user->search = NULL; user->search_id = NULL; x = xode_get_tag(cfg, "notify"); temp = xode_get_attrib(x, "mail"); if (temp != NULL) { if (strcmp(temp, "1") == 0) { user->mailnotify = 1; } else if (strcmp(temp, "0") == 0) { user->mailnotify = 0; } else { user->mailnotify = 0; my_debug(0, "Blad w pliku"); } } else { user->mailnotify = 0; } temp = xode_get_attrib(x, "typing"); if (temp != NULL) { if (strcmp(temp, "1") == 0) { user->typingnotify = 1; } else if (strcmp(temp, "0") == 0) { user->typingnotify = 0; } else { user->typingnotify = 0; my_debug(0, "Blad w pliku"); } } else { user->typingnotify = 0; } temp = xode_get_attrib(x, "alarm"); if (temp != NULL) { if (strcmp(temp, "1") == 0) { user->alarmnotify = 1; } else if (strcmp(temp, "0") == 0) { user->alarmnotify = 0; } else { user->alarmnotify = 0; my_debug(0, "Blad w pliku"); } } else { user->alarmnotify = 0; } user->status = NULL; user->status_type = 0; user->jabber_status = NULL; user->jabber_status_type = NULL; xode_free(cfg); t_free(file); return user; }
static void in_stream_node_callback(int type, xode node, void *arg) { struct xmpp_connection *conn = (struct xmpp_connection *) arg; char *tag; xode x; LM_DBG("instream callback: %d: %s\n", type, node ? xode_get_name(node) : "n/a"); switch (type) { case XODE_STREAM_ROOT: conn->stream_id = strdup(random_secret()); net_printf(conn->fd, "<?xml version='1.0'?>" "<stream:stream xmlns:stream='http://etherx.jabber.org/streams' xmlns='jabber:server' version='1.0'" " xmlns:db='jabber:server:dialback' id='%s' from='%s'>", conn->stream_id, xmpp_domain); net_printf(conn->fd,"<stream:features xmlns:stream='http://etherx.jabber.org/streams'/>"); break; case XODE_STREAM_NODE: tag = xode_get_name(node); if (!strcmp(tag, "db:result")) { char *from = xode_get_attrib(node, "from"); char *to = xode_get_attrib(node, "to"); /* char *id = xode_get_attrib(node, "id"); */ char *type = xode_get_attrib(node, "type"); char *cdata = xode_get_data(node); if (!type) { if (conn->domain) { LM_DBG("connection %d has old domain '%s'\n",conn->fd, conn->domain); free(conn->domain); } conn->domain = strdup(from); LM_DBG("connection %d set domain '%s'\n", conn->fd, conn->domain); /* it's a request; send verification over outgoing connection */ x = xode_new_tag("db:verify"); xode_put_attrib(x, "xmlns:db", "jabber:server:dialback"); xode_put_attrib(x, "from", to); xode_put_attrib(x, "to", from); //xode_put_attrib(x, "id", "someid"); /* XXX fix ID */ xode_put_attrib(x, "id", conn->stream_id); xode_insert_cdata(x, cdata, -1); xode_send_domain(from, x); } } else if (!strcmp(tag, "db:verify")) { char *from = xode_get_attrib(node, "from"); char *to = xode_get_attrib(node, "to"); char *id = xode_get_attrib(node, "id"); char *type = xode_get_attrib(node, "type"); char *cdata = xode_get_data(node); if (!type) { /* it's a request */ x = xode_new_tag("db:verify"); xode_put_attrib(x, "xmlns:db", "jabber:server:dialback"); xode_put_attrib(x, "from", to); xode_put_attrib(x, "to", from); xode_put_attrib(x, "id", id); //if (cdata && !strcmp(cdata, DB_KEY)) { if (cdata && !strcmp(cdata, db_key(local_secret, from, id))) { xode_put_attrib(x, "type", "valid"); } else { xode_put_attrib(x, "type", "invalid"); } xode_send(conn->fd, x); xode_free(x); } } else if (!strcmp(tag, "message")) { char *from = xode_get_attrib(node, "from"); char *to = xode_get_attrib(node, "to"); char *type = xode_get_attrib(node, "type"); xode body = xode_get_tag(node, "body"); char *msg; if (!type) type = "chat"; if (!strcmp(type, "error")) { LM_DBG("received message error stanza\n"); goto out; } if (!from || !to || !body) { LM_DBG("invalid <message/> attributes\n"); goto out; } if (!(msg = xode_get_data(body))) msg = ""; xmpp_send_sip_msg( encode_uri_xmpp_sip(from), decode_uri_xmpp_sip(to), msg); } else if (!strcmp(tag, "presence")) { /* run presence callbacks */ } break; break; case XODE_STREAM_ERROR: LM_ERR("instream error\n"); /* fall-through */ case XODE_STREAM_CLOSE: conn->type = CONN_DEAD; break; } out: xode_free(node); }
static void _xode_tag2str(xode_spool s, xode node, int flag) { xode tmp; if(flag==0 || flag==1) { xode_spooler(s,"<",xode_get_name(node),s); tmp = xode_get_firstattrib(node); while(tmp) { xode_spooler(s," ",xode_get_name(tmp),"='",xode_strescape(xode_get_pool(node),xode_get_data(tmp)),"'",s); tmp = xode_get_nextsibling(tmp); } if(flag==0) xode_spool_add(s,"/>"); else xode_spool_add(s,">"); } else { xode_spooler(s,"</",xode_get_name(node),">",s); } }