static int jabber_buddy_msg(struct im_connection *ic, char *who, char *message, int flags) { struct jabber_data *jd = ic->proto_data; struct jabber_buddy *bud; struct xt_node *node; char *s; int st; if (g_strcasecmp(who, JABBER_XMLCONSOLE_HANDLE) == 0) { return jabber_write(ic, message, strlen(message)); } if (g_strcasecmp(who, JABBER_OAUTH_HANDLE) == 0 && !(jd->flags & OPT_LOGGED_IN) && jd->fd == -1) { if (sasl_oauth2_get_refresh_token(ic, message)) { return 1; } else { imcb_error(ic, "OAuth failure"); imc_logout(ic, TRUE); return 0; } } if ((s = strchr(who, '=')) && jabber_chat_by_jid(ic, s + 1)) { bud = jabber_buddy_by_ext_jid(ic, who, 0); } else { bud = jabber_buddy_by_jid(ic, who, GET_BUDDY_BARE_OK); } node = xt_new_node("body", message, NULL); node = jabber_make_packet("message", "chat", bud ? bud->full_jid : who, node); if (bud && (jd->flags & JFLAG_WANT_TYPING) && ((bud->flags & JBFLAG_DOES_XEP85) || !(bud->flags & JBFLAG_PROBED_XEP85))) { struct xt_node *act; /* If the user likes typing notification and if we don't know (and didn't probe before) if this resource supports XEP85, include a probe in this packet now. Also, if we know this buddy does support XEP85, we have to send this <active/> tag to tell that the user stopped typing (well, that's what we guess when s/he pressed Enter...). */ act = xt_new_node("active", NULL, NULL); xt_add_attr(act, "xmlns", XMLNS_CHATSTATES); xt_add_child(node, act); /* Just make sure we do this only once. */ bud->flags |= JBFLAG_PROBED_XEP85; } st = jabber_write_packet(ic, node); xt_free_node(node); return st; }
static void jabber_keepalive( struct im_connection *ic ) { /* Just any whitespace character is enough as a keepalive for XMPP sessions. */ if( !jabber_write( ic, "\n", 1 ) ) return; /* This runs the garbage collection every minute, which means every packet is in the cache for about a minute (which should be enough AFAIK). */ jabber_cache_clean( ic ); }
int jabber_write_packet( struct im_connection *ic, struct xt_node *node ) { char *buf; int st; buf = xt_to_string( node ); st = jabber_write( ic, buf, strlen( buf ) ); g_free( buf ); return st; }
void jabber_end_stream( struct im_connection *ic ) { struct jabber_data *jd = ic->proto_data; /* Let's only do this if the queue is currently empty, otherwise it'd take too long anyway. */ if( jd->tx_len == 0 ) { char eos[] = "</stream:stream>"; struct xt_node *node; int st = 1; if( ic->flags & OPT_LOGGED_IN ) { node = jabber_make_packet( "presence", "unavailable", NULL, NULL ); st = jabber_write_packet( ic, node ); xt_free_node( node ); } if( st ) jabber_write( ic, eos, strlen( eos ) ); } }
gboolean jabber_start_stream( struct im_connection *ic ) { struct jabber_data *jd = ic->proto_data; int st; char *greet; /* We'll start our stream now, so prepare everything to receive one from the server too. */ xt_free( jd->xt ); /* In case we're RE-starting. */ jd->xt = xt_new( jabber_handlers, ic ); if( jd->r_inpa <= 0 ) jd->r_inpa = b_input_add( jd->fd, GAIM_INPUT_READ, jabber_read_callback, ic ); greet = g_strdup_printf( "<?xml version='1.0' ?>" "<stream:stream to=\"%s\" xmlns=\"jabber:client\" " "xmlns:stream=\"http://etherx.jabber.org/streams\" version=\"1.0\">", jd->server ); st = jabber_write( ic, greet, strlen( greet ) ); g_free( greet ); return st; }
void jabber_dcc_close_handler(struct dcc_s *d) { jabber_dcc_t *p = d->priv; debug_error("jabber_dcc_close_handler() d->priv: 0x%x\n", d->priv); if (!p) return; if (!d->active && d->type == DCC_GET) { session_t *s = p->session; jabber_private_t *j; if (!s || !(j= session_private_get(s))) return; jabber_write(s, "<iq type='error' to='%s' id='%s'><error code='403'>Declined</error></iq>", d->uid+5, p->req); } d->priv = NULL; if (p) { if (p->protocol == JABBER_DCC_PROTOCOL_BYTESTREAMS) { /* XXX, free protocol-specified data */ } if (p->sfd != -1) close(p->sfd); if (p->fd) fclose(p->fd); xfree(p->req); xfree(p->sid); xfree(p); } else { debug_error("[jabber] jabber_dcc_close_handler() d->priv == NULL ?! wtf?\n"); } }