void aim_transport(instance i, xmlnode x) { ati ti; xmlnode config; char *eightbitcode, *utf8code = "UTF-8", *latin1code = "CP1252"; ti = pmalloco(i->p, sizeof(_ati)); ti->i = i; ti->xc = xdb_cache(i); log_notice(i->id, "AIM-Transport starting up for instance %s...", i->id); config = xdb_get(ti->xc, jid_new(xmlnode_pool(x), "config@-internal"), "jabber:config:aimtrans"); ti->vcard = xmlnode_new_tag_pool(i->p,"vCard"); xmlnode_put_attrib(ti->vcard,"xmlns",NS_VCARD); xmlnode_insert_node(ti->vcard,xmlnode_get_firstchild(xmlnode_get_tag(config,"vCard"))); ti->start_time = time(NULL); ti->session__list=xhash_new(101); ti->iq__callbacks = xhash_new(23); ti->pending__buddies = xhash_new(101); /* The aim.exe binary should not be necessary any more. */ ti->aimbinarydir = pstrdup(i->p, xmlnode_get_tag_data(config, "aimbinarydir")); eightbitcode = pstrdup(i->p, xmlnode_get_tag_data(config, "charset")); if( eightbitcode == NULL ) { log_notice( i->id, "Charset is not specified, using CP1252" ); eightbitcode = latin1code; } xmlnode_free(config); fromutf8 = iconv_open(eightbitcode, utf8code); if(fromutf8 == (iconv_t)(-1)) { log_error(i->id, "Conversion from %s to %s is not supported", utf8code, eightbitcode); raise(SIGINT); } toutf8 = iconv_open(utf8code, eightbitcode); if(toutf8 == (iconv_t)(-1)) { log_error(i->id, "Conversion from %s to %s is not supported", eightbitcode, utf8code); raise(SIGINT); } ti->send_buf = NULL; ti->modname = NULL; pth_mutex_init(&ti->buddies_mutex); at_init_iqcbs(ti); register_phandler(i, o_DELIVER, at_phandler, ti); pool_cleanup(i->p, at_shutdown, (void*)i); }
mreturn mod_agents_agent(mapi m) { xmlnode ret, retq, info, agents, reg; /* get data from the config file */ info = js_config(m->si, "vCard"); agents = js_config(m->si, "agents"); reg = js_config(m->si, "register"); /* if we don't have anything to say, bounce */ if (info == NULL && agents == NULL && reg == NULL) return M_PASS; log_debug("handling agent query"); /* build the result IQ */ ret = jutil_iqresult(m->packet->x); retq = xmlnode_insert_tag(ret, "query"); xmlnode_put_attrib(retq, "xmlns", NS_AGENT); /* copy in the vCard info */ xmlnode_insert_cdata(xmlnode_insert_tag(retq, "name"), xmlnode_get_tag_data(info, "FN"), -1); xmlnode_insert_cdata(xmlnode_insert_tag(retq, "url"), xmlnode_get_tag_data(info, "URL"), -1); xmlnode_insert_cdata(xmlnode_insert_tag(retq, "service"), "jabber", 6); /* set the flags */ if (agents != NULL) xmlnode_insert_tag(retq, "agents"); if (reg != NULL) xmlnode_insert_tag(retq, "register"); jpacket_reset(m->packet); if (m->s != NULL) { /* XXX null session hack! */ xmlnode_put_attrib(m->packet->x, "from", m->packet->from->server); js_session_to(m->s, m->packet); } else { js_deliver(m->si, m->packet); } return M_HANDLED; }
int at_iq_gateway(ati ti, jpacket jp) { if(jp->to->user != NULL) { at_bounce(ti, jp, TERROR_NOTALLOWED); return 1; } switch(jpacket_subtype(jp)) { case JPACKET__GET: { xmlnode q; jutil_iqresult(jp->x); q = xmlnode_insert_tag(jp->x,"query"); xmlnode_put_attrib(q,"xmlns",NS_GATEWAY); xmlnode_insert_cdata(xmlnode_insert_tag(q,"desc"),"Enter the user's screenname",-1); xmlnode_insert_tag(q,"prompt"); break; } case JPACKET__SET: { char *user, *id; user = xmlnode_get_tag_data(jp->iq,"prompt"); id = user ? spools(jp->p,at_normalize(user),"@",jp->to->server,jp->p) : NULL; if (id) { xmlnode q; jutil_iqresult(jp->x); q = xmlnode_insert_tag(jp->x,"query"); xmlnode_put_attrib(q,"xmlns",NS_GATEWAY); xmlnode_insert_cdata(xmlnode_insert_tag(q,"prompt"),id,-1); } else jutil_error(jp->x,TERROR_BAD); break; } default: jutil_error(jp->x,TERROR_BAD); break; } at_deliver(ti,jp->x); return 1; }
void con_room_leaveall(gpointer key, gpointer data, gpointer arg) { cnu user = (cnu)data; xmlnode info = (xmlnode)arg; char *alt, *reason; xmlnode presence; xmlnode tag; xmlnode element; xmlnode node; xmlnode destroy; log_debug(NAME, "[%s] reason : %s", FZONE, xmlnode2str(info)); if(user == NULL) { log_warn(NAME, "[%s] Aborting - NULL user attribute found", FZONE); return; } if (user->remote == 1) return; presence = jutil_presnew(JPACKET__UNAVAILABLE, NULL, NULL); tag = xmlnode_insert_tag(presence,"x"); xmlnode_put_attrib(tag, "xmlns", NS_MUC_USER); element = xmlnode_insert_tag(tag, "item"); xmlnode_put_attrib(element, "role", "none"); xmlnode_put_attrib(element, "affiliation", "none"); if (info != NULL) { destroy = xmlnode_insert_tag(tag, "destroy"); reason = xmlnode_get_tag_data(info, "reason"); node = xmlnode_insert_tag(destroy, "reason"); if(reason != NULL) { xmlnode_insert_cdata(node, reason, -1); } alt = xmlnode_get_attrib(info, "jid"); if (alt != NULL) { xmlnode_put_attrib(destroy, "jid", alt); } } con_user_send(user, user, presence); }
xmlnode mod_browse_get(mapi m, jid id) { xmlnode browse, x; if (id == NULL) /* use the user id as a backup */ id = m->user->id; /* get main account browse */ if ((browse = xdb_get(m->si->xc, id, NS_BROWSE)) == NULL) { /* no browse is set up yet, we must create one for this user! */ if (id->resource == NULL) { /* a user is only the user@host */ browse = xmlnode_new_tag("user"); /* get the friendly name for this user from somewhere */ if ((x = xdb_get(m->si->xc, m->user->id, NS_VCARD)) != NULL) xmlnode_put_attrib(browse, "name", xmlnode_get_tag_data(x, "FN")); else if ((x = xdb_get(m->si->xc, m->user->id, NS_REGISTER)) != NULL) xmlnode_put_attrib(browse, "name", xmlnode_get_tag_data(x, "name")); xmlnode_free(x); } else { /* everything else is generic unless set by the user */ browse = xmlnode_new_tag("item"); } xmlnode_put_attrib(browse, "xmlns", NS_BROWSE); xmlnode_put_attrib(browse, "jid", jid_full(id)); xdb_set(m->si->xc, id, NS_BROWSE, browse); } return browse; }
int at_iq_browse(ati ti, jpacket jp) { xmlnode q; if(jpacket_subtype(jp) != JPACKET__GET) { at_bounce(ti, jp, TERROR_BAD); return 1; } if(jp->to->user != NULL) { q = xmlnode_insert_tag(jutil_iqresult(jp->x),"item"); xmlnode_put_attrib(q,"xmlns",NS_BROWSE); xmlnode_put_attrib(q,"category","user"); xmlnode_put_attrib(q,"type","client"); xmlnode_put_attrib(q,"jid",jid_full(jp->to)); xmlnode_put_attrib(q,"name", jp->to->user); at_deliver(ti,jp->x); return 1; } q = xmlnode_insert_tag(jutil_iqresult(jp->x),"item"); xmlnode_put_attrib(q,"xmlns",NS_BROWSE); xmlnode_put_attrib(q,"category","service"); xmlnode_put_attrib(q,"type","aim"); xmlnode_put_attrib(q,"jid",jp->to->server); xmlnode_put_attrib(q,"name",xmlnode_get_tag_data(ti->vcard,"FN")); xmlnode_insert_cdata(xmlnode_insert_tag(q,"ns"),NS_DISCO_INFO,-1); xmlnode_insert_cdata(xmlnode_insert_tag(q,"ns"),NS_DISCO_ITEMS,-1); xmlnode_insert_cdata(xmlnode_insert_tag(q,"ns"),NS_REGISTER,-1); xmlnode_insert_cdata(xmlnode_insert_tag(q,"ns"),NS_GATEWAY,-1); at_deliver(ti,jp->x); // WHY! DAMNIT! WHY? return 1; }
/** Start up transport. Read configuration, register callbacks. */ void icqtrans(instance i, xmlnode x) { iti ti; pool p = i->p; xmlnode config; xmlnode cur; int check; log_debug(ZONE,"ICQ Transport, initializing for section '%s'",i->id); /* create new transport instance */ ti = pmalloco(p,sizeof(_iti)); ti->i = i; ti->xc = xdb_cache(i); config = xdb_get(ti->xc,jid_new(xmlnode_pool(x),"config@-internal"),"jabber:config:icqtrans"); if (config == NULL) { log_error(i->id,"Configuration not found!"); return; } ti->registration_instructions = pstrdup(p,xmlnode_get_tag_data(config,"instructions")); if (ti->registration_instructions == NULL) { log_debug(i->id,"Registration instructions not found"); } ti->search_instructions = pstrdup(p,xmlnode_get_tag_data(config,"search")); if (ti->search_instructions == NULL) { log_debug(i->id,"Search instructions not found"); } ti->charset = pstrdup(p,xmlnode_get_tag_data(config,"charset")); if (ti->charset == NULL) { log_debug(i->id,"Charset not specified, set default to %s ",DEFAULT_CHARSET); ti->charset = pstrdup(p,DEFAULT_CHARSET); } _ucs2utf = iconv_open("UTF-8","UCS-2BE"); _win2utf = iconv_open("UTF-8",ti->charset); if (_win2utf==(iconv_t)-1) { ti->charset = pstrdup(p,DEFAULT_CHARSET); _win2utf = iconv_open("UTF-8",ti->charset); if (_win2utf==(iconv_t)-1) { log_error(i->id,"Charset error!"); return; } } _utf2win = iconv_open(ti->charset,"UTF-8"); if (_utf2win ==(iconv_t)-1) { ti->charset = pstrdup(p,DEFAULT_CHARSET); _utf2win = iconv_open(ti->charset,"UTF-8"); if (_utf2win ==(iconv_t)-1) { log_error(i->id,"Charset error!"); return; } } log_notice("config","charset %s",ti->charset); ti->msg_chat = xmlnode_get_tag(config,"chat") ? 1 : 0; if (ti->msg_chat) { log_notice("config","chat messages enabled"); } ti->web_aware = xmlnode_get_tag(config,"web") ? 1 : 0; if (ti->web_aware) { log_notice("config","web presence enabled"); } ti->own_roster = xmlnode_get_tag(config,"own_roster") ? 1 : 0; if (ti->own_roster) { log_notice("config","JIT will use own roster"); } ti->no_jabber_roster = xmlnode_get_tag(config,"no_jabber_roster") ? 1 : 0; if (ti->no_jabber_roster) { log_notice("config","JIT willn't get users from jabber roster"); } ti->no_x_data = xmlnode_get_tag(config,"no_xdata") ? 1 : 0; if (ti->no_x_data) { log_notice("config","JIT will not use xdata"); } cur = xmlnode_get_tag(config,"sms"); if (cur) { ti->sms_id = pstrdup(p,xmlnode_get_tag_data(cur,"host")); if (ti->sms_id) { ti->sms_show = jit_show2status(xmlnode_get_tag_data(cur,"show")); if (ti->sms_show==ICQ_STATUS_NOT_IN_LIST) { ti->sms_show = ICQ_STATUS_ONLINE; } log_notice("config","sms host %s show: %d",ti->sms_id,ti->sms_show); ti->sms_status = pstrdup(p,xmlnode_get_tag_data(cur,"status")); if (ti->sms_status) { log_debug(ZONE,"sms st %s ",ti->sms_status); } ti->sms_name = pstrdup(p,xmlnode_get_tag_data(cur,"name")); if (ti->sms_name) { log_debug(ZONE,"sms name %s",ti->sms_name); } } } ti->count_file = pstrdup(p,xmlnode_get_tag_data(config,"user_count_file")); if (ti->count_file == NULL) { ti->count_file = "icqcount"; } log_notice("config","Using %s as count log file",ti->count_file); for (cur = xmlnode_get_firstchild(xmlnode_get_tag(config,"server")); cur != NULL; cur = xmlnode_get_nextsibling(cur)) { char * port; char * host; if (xmlnode_get_type(cur) != NTYPE_TAG) continue; if ((port = xmlnode_get_attrib(cur,"port")) == NULL) continue; if ((host = xmlnode_get_data(cur)) == NULL) continue; ti->auth_hosts[ti->auth_hosts_count] = pstrdup(p,host); ti->auth_ports[ti->auth_hosts_count] = j_atoi(port,5190); log_debug(ZONE,"Host %s port %d at pos %d", ti->auth_hosts[ti->auth_hosts_count], ti->auth_ports[ti->auth_hosts_count], ti->auth_hosts_count); ti->auth_hosts_count++; if (ti->auth_hosts_count >= MAX_AUTH_HOSTS) break; } if (ti->auth_hosts_count == 0) { log_alert("err","No hosts to auth icq client !. Using default"); ti->auth_hosts[ti->auth_hosts_count] = pstrdup(p,"205.188.179.233"); ti->auth_ports[ti->auth_hosts_count] = 5190; ti->auth_hosts_count++; } /* add queue for unknown packets */ ti->q = mtq_new(i->p); ti->sessions = wpxhash_new(j_atoi(xmlnode_get_tag_data(config,"prime"),509)); ti->sessions_alt = wpxhash_new(j_atoi(xmlnode_get_tag_data(config,"prime"),509)); SEM_INIT(ti->sessions_sem); ti->vcard = xmlnode_new_tag_pool(p,"vCard"); xmlnode_put_attrib(ti->vcard,"xmlns",NS_VCARD); xmlnode_insert_node(ti->vcard,xmlnode_get_firstchild(xmlnode_get_tag(config,"vCard"))); /* default 5 hours */ ti->session_timeout = j_atoi(xmlnode_get_tag_data(config,"session_timeout"),18000); log_notice("config","session_timeout in sec : %d",ti->session_timeout); ti->reconnect = j_atoi(xmlnode_get_tag_data(config,"reconnects"),0); log_notice("config","Number of reconnects for session %d",ti->reconnect); check = j_atoi(xmlnode_get_tag_data(config,"session_check"),10); log_notice("config","JIT will check session every %d sec",check); // ti->admin = xmlnode_dup(xmlnode_get_tag(config,"admin")); ti->start = time(NULL); /* Register callbacks */ register_phandler(i,o_DELIVER,it_receive,(void *) ti); register_shutdown(it_shutdown,(void *) ti); /* Start up heartbeat thread */ register_beat(check,it_sessions_check,(void *) ti); xmlnode_free(config); }
void con_room_send_invite(cnu sender, xmlnode node) { xmlnode result; xmlnode element; xmlnode invite; xmlnode pass; char *body, *user, *reason, *inviter; cnr room; pool p; if(sender == NULL || node == NULL) { log_warn(NAME, "[%s] Aborting - NULL attribute found", FZONE); return; } log_debug(NAME, "[%s] Sending room invite", FZONE); room = sender->room; invite = xmlnode_get_tag(node, "invite"); user = xmlnode_get_attrib(invite, "to"); reason = xmlnode_get_tag_data(invite, "reason"); p = xmlnode_pool(node); if(room->visible == 1) { inviter = jid_full(sender->realid); } else { inviter = jid_full(sender->localid); } xmlnode_put_attrib(invite, "from", inviter); xmlnode_hide_attrib(invite, "to"); if(reason == NULL) { reason = spools(p, "None given", p); } body = spools(p, "You have been invited to the ", jid_full(room->id), " room by ", inviter, "\nReason: ", reason, p); result = jutil_msgnew("normal", user , "Invitation", body); xmlnode_put_attrib(result, "from", jid_full(room->id)); xmlnode_insert_node(result, node); if(room->secret != NULL) { pass = xmlnode_get_tag(result, "x"); xmlnode_insert_cdata(xmlnode_insert_tag(pass, "password"), room->secret, -1); } element = xmlnode_insert_tag(result, "x"); xmlnode_put_attrib(element, "jid", jid_full(room->id)); xmlnode_put_attrib(element, "xmlns", NS_X_CONFERENCE); xmlnode_insert_cdata(element, reason, -1); log_debug(NAME, "[%s] >>>%s<<<", FZONE, xmlnode2str(result)); deliver(dpacket_new(result), NULL); return; }
/* session thread */ mreturn mod_presence_out(mapi m, void *arg) { xmlnode pnew, delay, pold; modpres mp = (modpres) arg; session cur = NULL; int oldpri, newpri; char *priority; if (m->packet->type != JPACKET_PRESENCE) return M_IGNORE; if (m->packet->to != NULL || jpacket_subtype(m->packet) == JPACKET__PROBE || jpacket_subtype(m->packet) == JPACKET__ERROR) return M_PASS; log_debug("new presence from %s of %s", jid_full(m->s->id), xmlnode2str(m->packet->x)); /* pre-existing conditions (no, we are not an insurance company) */ oldpri = m->s->priority; /* check that the priority is in the valid range */ priority = xmlnode_get_tag_data(m->packet->x, "priority"); if (priority == NULL) { newpri = 0; } else { newpri = j_atoi(priority, 0); if (newpri < -128 || newpri > 127) { log_notice("mod_presence", "got presence with invalid priority value from %s", jid_full(m->s->id)); xmlnode_free(m->packet->x); return M_HANDLED; } } /* invisible mode is special, don't you wish you were special too? */ if (jpacket_subtype(m->packet) == JPACKET__INVISIBLE) { log_debug("handling invisible mode request"); /* if we get this and we're available, it means go unavail first then reprocess this packet, nifty trick :) */ if (oldpri >= -128) { js_session_from(m->s, jpacket_new(jutil_presnew (JPACKET__UNAVAILABLE, NULL, xmlnode_get_tag_data(m->packet->x,"status") ))); js_session_from(m->s, m->packet); return M_HANDLED; } /* now, pretend we come online :) */ /* (this is the handling of the reinjected invisible presence * or an initial invisible presence) */ mp->invisible = 1; mod_presence_roster(m, NULL); /* send out probes to users we are subscribed to */ m->s->priority = newpri; /* store presence in xdb? */ if (mp->conf->pres_to_xdb > 0) mod_presence_store(m); xmlnode_free(m->packet->x); /* we do not broadcast invisible presences without a to attribute */ return M_HANDLED; } /* our new presence */ pnew = xmlnode_dup(m->packet->x); /* store presence in xdb? */ if (mp->conf->pres_to_xdb > 0) mod_presence_store(m); /* stamp the sessions presence */ delay = xmlnode_insert_tag(pnew, "x"); xmlnode_put_attrib(delay, "xmlns", NS_DELAY); xmlnode_put_attrib(delay, "from", jid_full(m->s->id)); xmlnode_put_attrib(delay, "stamp", jutil_timestamp()); /* our old presence */ pold = m->s->presence; m->s->presence = pnew; m->s->priority = jutil_priority(pnew); log_debug("presence oldp %d newp %d", oldpri, m->s->priority); /* if we're going offline now, let everyone know */ if (m->s->priority < -128) { /* jutil_priority returns -129 in case the "type" attribute is missing */ if (!mp->invisible) /* bcc's don't get told if we were invisible */ _mod_presence_broadcast(m->s, mp->conf->bcc, m->packet->x, NULL); _mod_presence_broadcast(m->s, mp->A, m->packet->x, NULL); _mod_presence_broadcast(m->s, mp->I, m->packet->x, NULL); /* reset vars */ mp->invisible = 0; mp->A->next = NULL; mp->I = NULL; xmlnode_free(m->packet->x); xmlnode_free(pold); return M_HANDLED; } /* available presence updates, intersection of A and T */ if (oldpri >= -128 && !mp->invisible) { _mod_presence_broadcast_trusted(m->s, mp->A, m->packet->x); xmlnode_free(m->packet->x); xmlnode_free(pold); return M_HANDLED; } /* at this point we're coming out of the closet */ mp->invisible = 0; /* make sure we get notified for any presence about ourselves */ /* XXX: the following is the original code: it caused existing presences * to be stamped several times and the presence to be sent out twice. pnew = jutil_presnew(JPACKET__PROBE,jid_full(m->s->uid),NULL); xmlnode_put_attrib(pnew,"from",jid_full(m->s->uid)); js_session_from(m->s, jpacket_new(pnew)); */ /* XXX: I think this should be okay as well: */ /* send us all presences of our other resources */ for (cur = m->user->sessions; cur != NULL; cur = cur->next) { pool pool_for_existing_presence = NULL; xmlnode duplicated_presence = NULL; jpacket packet = NULL; /* skip our own session (and sanity check) */ if (cur == m->s || cur->presence == NULL) { continue; } /* send the presence to us: we need a new pool as js_session_to() will free the packet's pool */ pool_for_existing_presence = pool_new(); duplicated_presence = xmlnode_dup_pool(pool_for_existing_presence, cur->presence); xmlnode_put_attrib(duplicated_presence, "to", jid_full(m->user->id)); packet = jpacket_new(duplicated_presence); js_session_to(m->s, packet); } /* probe s10ns and populate A */ mod_presence_roster(m, mp->A); /* we broadcast this baby! */ _mod_presence_broadcast(m->s, mp->conf->bcc, m->packet->x, NULL); _mod_presence_broadcast(m->s, mp->A, m->packet->x, NULL); xmlnode_free(m->packet->x); xmlnode_free(pold); return M_HANDLED; }
/** Process presence from Jabber */ void it_presence(session s, jpacket jp) { log_debug(ZONE,"Session[%s], handling presence",jid_full(s->id)); switch (jpacket_subtype(jp)) { case JPACKET__PROBE: if (jp->to->user) { UIN_t uin; contact c; uin = it_jid2uin(jp->to); if (j_strcmp(jp->to->server,s->ti->sms_id)==0) { uin = SMS_CONTACT; } if (uin == SMS_CONTACT) c = it_sms_get(s,jp->to->user); else c = it_contact_get(s,uin); if (c != NULL) it_contact_send_presence(c,NULL); else { c = it_unknown_contact_add(s, jp->to->user, uin); if (c != NULL) it_contact_send_presence(c,NULL); } } break; case JPACKET__INVISIBLE: { icqstatus status; char *text; if (jp->to->user) /* presence to groupchat here */ break; /* update users presence */ s->p_db = ppdb_insert(s->p_db,jp->from,jp->x); text = xmlnode_get_tag_data(jp->x,"status"); if (text != NULL) strncpy(s->status_text,text,MAX_STATUS_TEXT); else s->status_text[0] = '\0'; status = ICQ_STATUS_INVISIBLE; if (status != s->status) { s->status = status; /* propagate to C++ backend */ SendStatus(s); } /* echo.... */ /* only when connected */ if (!s->connected) { xmlnode_free(jp->x); return; } xmlnode_put_attrib(jp->x,"from",jid_full(jp->to)); xmlnode_put_attrib(jp->x,"to",jid_full(jid_user(jp->from))); it_deliver(s->ti,jp->x); return; } case JPACKET__AVAILABLE: { icqstatus status; char *text; if (jp->to->user) /* presence to groupchat here */ break; log_debug(ZONE,"presence"); /* update user's presence */ s->p_db = ppdb_insert(s->p_db,jp->from,jp->x); text = xmlnode_get_tag_data(jp->x,"status"); if (text != NULL) { strncpy(s->status_text,text,MAX_STATUS_TEXT); } else s->status_text[0] = '\0'; status = jit_show2status(xmlnode_get_tag_data(jp->x,"show")); if (status != s->status) { s->status = status; /* Always set status regardless of being connected or not */ /* Client class will set this status */ /* after connecting */ SendStatus(s); } /* echo.... */ /* only when connected */ if (!s->connected) { xmlnode_free(jp->x); return; } xmlnode_put_attrib(jp->x,"from",jid_full(jp->to)); xmlnode_put_attrib(jp->x,"to",jid_full(jid_user(jp->from))); it_deliver(s->ti,jp->x); return; } case JPACKET__UNAVAILABLE: if (jp->to->user == NULL) { /* kill the session if there are no available resources left */ s->p_db = ppdb_insert(s->p_db,jp->from,jp->x); if (ppdb_primary(s->p_db,s->id) == NULL){ if (!s->exit_flag) EndClient(s); // will call it_session_end } } default: break; } xmlnode_free(jp->x); }
int at_iq_disco_info(ati ti, jpacket jp) { xmlnode q, info; if(jpacket_subtype(jp) != JPACKET__GET) { at_bounce(ti, jp, TERROR_BAD); return 1; } if(xmlnode_get_attrib(xmlnode_get_tag(jp->x, "query"),"node") != NULL) { at_bounce(ti, jp, TERROR_NOTALLOWED); return 1; } if(jp->to->user != NULL) { q = xmlnode_insert_tag(jutil_iqresult(jp->x),"query"); xmlnode_put_attrib(q,"xmlns",NS_DISCO_INFO); info = xmlnode_insert_tag(q, "identity"); xmlnode_put_attrib(info, "category", "client"); xmlnode_put_attrib(info, "type", "pc"); xmlnode_put_attrib(info, "name", jp->to->user); info = xmlnode_insert_tag(q, "feature"); xmlnode_put_attrib(info, "var", NS_VCARD); info = xmlnode_insert_tag(q, "feature"); xmlnode_put_attrib(info, "var", NS_LAST); info = xmlnode_insert_tag(q, "feature"); xmlnode_put_attrib(info, "var", NS_TIME); info = xmlnode_insert_tag(q, "feature"); xmlnode_put_attrib(info, "var", NS_VERSION); at_deliver(ti,jp->x); return 1; } q = xmlnode_insert_tag(jutil_iqresult(jp->x),"query"); xmlnode_put_attrib(q,"xmlns",NS_DISCO_INFO); info = xmlnode_insert_tag(q, "identity"); xmlnode_put_attrib(info, "category", "gateway"); xmlnode_put_attrib(info, "type", "aim"); xmlnode_put_attrib(info,"name",xmlnode_get_tag_data(ti->vcard,"FN")); info = xmlnode_insert_tag(q, "feature"); xmlnode_put_attrib(info, "var", NS_VCARD); info = xmlnode_insert_tag(q, "feature"); xmlnode_put_attrib(info, "var", NS_LAST); info = xmlnode_insert_tag(q, "feature"); xmlnode_put_attrib(info, "var", NS_TIME); info = xmlnode_insert_tag(q, "feature"); xmlnode_put_attrib(info, "var", NS_VERSION); info = xmlnode_insert_tag(q, "feature"); xmlnode_put_attrib(info, "var", NS_GATEWAY); info = xmlnode_insert_tag(q, "feature"); xmlnode_put_attrib(info, "var", NS_REGISTER); at_deliver(ti,jp->x); return 1; }