static void steam_cb_user_search(SteamApiReq *req, gpointer data) { const gchar *tag; gchar sid[STEAM_ID_STRMAX]; GList *l; guint i; SteamData *sata = data; SteamUserInfo *info; if (steam_req_error(sata, req, TRUE)) { return; } for (l = req->infs->head, i = 0; (l != NULL) && (i < 2); l = l->next, i++); switch (i) { case 0: imcb_error(sata->ic, "Failed to find any friend(s)"); return; case 1: info = req->infs->head->data; req = steam_api_req_new(req->api, steam_cb_user_action, sata); steam_api_req_user_add(req, info->id); return; } imcb_log(sata->ic, "Select from one of the following Steam Friends:"); tag = sata->ic->acc->tag; for (l = req->infs->head, i = 1; l != NULL; l = l->next, i++) { info = l->data; STEAM_ID_STR(info->id, sid); imcb_log(sata->ic, "%u. `%s' %s", i, info->nick, info->profile); imcb_log(sata->ic, "-- add %s steamid:%s", tag, sid); } }
/** * Implemented #SteamApiFunc for #steam_api_req_logon(). * * @param req The #SteamApiReq. * @param data The user defined data, which is #SteamData. **/ static void steam_cb_logon(SteamApiReq *req, gpointer data) { SteamData *sata = data; if (steam_req_error(sata, req, TRUE)) return; set_setstr(&sata->ic->acc->set, "umqid", req->api->umqid); imcb_log(sata->ic, "Requesting friends list"); req = steam_api_req_new(req->api, steam_cb_friends, sata); steam_api_req_friends(req); }
static void *prplcb_notify_userinfo( PurpleConnection *gc, const char *who, PurpleNotifyUserInfo *user_info ) { struct im_connection *ic = purple_ic_by_gc( gc ); GString *info = g_string_new( "" ); GList *l = purple_notify_user_info_get_entries( user_info ); char *key; const char *value; int n; while( l ) { PurpleNotifyUserInfoEntry *e = l->data; switch( purple_notify_user_info_entry_get_type( e ) ) { case PURPLE_NOTIFY_USER_INFO_ENTRY_PAIR: case PURPLE_NOTIFY_USER_INFO_ENTRY_SECTION_HEADER: key = g_strdup( purple_notify_user_info_entry_get_label( e ) ); value = purple_notify_user_info_entry_get_value( e ); if( key ) { strip_html( key ); g_string_append_printf( info, "%s: ", key ); if( value ) { n = strlen( value ) - 1; while( isspace( value[n] ) ) n --; g_string_append_len( info, value, n + 1 ); } g_string_append_c( info, '\n' ); g_free( key ); } break; case PURPLE_NOTIFY_USER_INFO_ENTRY_SECTION_BREAK: g_string_append( info, "------------------------\n" ); break; } l = l->next; } imcb_log( ic, "User %s info:\n%s", who, info->str ); g_string_free( info, TRUE ); return NULL; }
void twitter_login_finish(struct im_connection *ic) { struct twitter_data *td = ic->proto_data; td->flags &= ~TWITTER_DOING_TIMELINE; if (set_getbool(&ic->acc->set, "oauth") && !td->oauth_info) twitter_oauth_start(ic); else if (!(td->flags & TWITTER_MODE_ONE) && !(td->flags & TWITTER_HAVE_FRIENDS)) { imcb_log(ic, "Getting contact list"); twitter_get_friends_ids(ic, -1); } else twitter_main_loop_start(ic); }
int jabber_get_roster( struct im_connection *ic ) { struct xt_node *node; int st; imcb_log( ic, "Authenticated, requesting buddy list" ); node = xt_new_node( "query", NULL, NULL ); xt_add_attr( node, "xmlns", XMLNS_ROSTER ); node = jabber_make_packet( "iq", "get", NULL, node ); jabber_cache_add( ic, node, jabber_parse_roster ); st = jabber_write_packet( ic, node ); return st; }
static gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond ) { struct msn_handler_data *handler = data; struct im_connection *ic = handler->data; struct msn_data *md; if( !g_slist_find( msn_connections, ic ) ) return FALSE; md = ic->proto_data; if( source == -1 ) { imcb_error( ic, "Could not connect to server" ); imc_logout( ic, TRUE ); return FALSE; } g_free( handler->rxq ); handler->rxlen = 0; handler->rxq = g_new0( char, 1 ); if( md->uuid == NULL ) { struct utsname name; sha1_state_t sha[1]; /* UUID == SHA1("BitlBee" + my hostname + MSN username) */ sha1_init( sha ); sha1_append( sha, (void*) "BitlBee", 7 ); if( uname( &name ) == 0 ) { sha1_append( sha, (void*) name.nodename, strlen( name.nodename ) ); } sha1_append( sha, (void*) ic->acc->user, strlen( ic->acc->user ) ); md->uuid = sha1_random_uuid( sha ); memcpy( md->uuid, "b171be3e", 8 ); /* :-P */ } if( msn_ns_write( ic, source, "VER %d %s CVR0\r\n", ++md->trId, MSNP_VER ) ) { handler->inpa = b_input_add( handler->fd, B_EV_IO_READ, msn_ns_callback, handler ); imcb_log( ic, "Connected to server, waiting for reply" ); } return FALSE; }
/* IM->UI callbacks */ void imcb_buddy_status(struct im_connection *ic, const char *handle, int flags, const char *state, const char *message) { bee_t *bee = ic->bee; bee_user_t *bu, *old; if (!(bu = bee_user_by_handle(bee, ic, handle))) { if (g_strcasecmp(set_getstr(&ic->bee->set, "handle_unknown"), "add") == 0) { bu = bee_user_new(bee, ic, handle, BEE_USER_LOCAL); } else { if (g_strcasecmp(set_getstr(&ic->bee->set, "handle_unknown"), "ignore") != 0) { imcb_log(ic, "imcb_buddy_status() for unknown handle %s:\n" "flags = %d, state = %s, message = %s", handle, flags, state ? state : "NULL", message ? message : "NULL"); } return; } } /* May be nice to give the UI something to compare against. */ old = g_memdup(bu, sizeof(bee_user_t)); /* TODO(wilmer): OPT_AWAY, or just state == NULL ? */ bu->flags = flags; bu->status_msg = g_strdup(message); if (state && *state) { bu->status = g_strdup(state); } else if (flags & OPT_AWAY) { bu->status = g_strdup("Away"); } else { bu->status = NULL; } if (bu->status == NULL && (flags & OPT_MOBILE) && set_getbool(&bee->set, "mobile_is_away")) { bu->flags |= BEE_USER_AWAY; bu->status = g_strdup("Mobile"); } if (bee->ui->user_status) { bee->ui->user_status(bee, bu, old); } g_free(old->status_msg); g_free(old->status); g_free(old); }
static char *set_eval_display_name( set_t *set, char *value ) { account_t *acc = set->data; struct im_connection *ic = acc->ic; struct msn_data *md = ic->proto_data; if( md->flags & MSN_EMAIL_UNVERIFIED ) imcb_log( ic, "Warning: Your e-mail address is unverified. MSN doesn't allow " "changing your display name until your e-mail address is verified." ); if( md->flags & MSN_GOT_PROFILE_DN ) msn_soap_profile_set_dn( ic, value ); else msn_soap_addressbook_set_display_name( ic, value ); return msn_ns_set_display_name( ic, value ) ? value : NULL; }
gboolean Skype_connected (gpointer data, void* source, b_input_condition condition) { im_connection* connection = data; SkypeData* skype = connection->proto_data; if (source == NULL) { skype->ssl = NULL; imcb_error(connection, "Could not connect to server"); imc_logout(connection, TRUE); return FALSE; } imcb_log(connection, "Connected to server, logging in"); return Skype_begin(connection); }
void sasl_oauth2_init( struct im_connection *ic ) { struct jabber_data *jd = ic->proto_data; char *msg, *url; imcb_log( ic, "Starting OAuth authentication" ); /* Temporary contact, just used to receive the OAuth response. */ imcb_add_buddy( ic, JABBER_OAUTH_HANDLE, NULL ); url = oauth2_url( jd->oauth2_service ); msg = g_strdup_printf( "Open this URL in your browser to authenticate: %s", url ); imcb_buddy_msg( ic, JABBER_OAUTH_HANDLE, msg, 0, 0 ); imcb_buddy_msg( ic, JABBER_OAUTH_HANDLE, "Respond to this message with the returned " "authorization token.", 0, 0 ); g_free( msg ); g_free( url ); }
gboolean jabber_connected_plain( gpointer data, gint source, b_input_condition cond ) { struct im_connection *ic = data; if( g_slist_find( jabber_connections, ic ) == NULL ) return FALSE; if( source == -1 ) { imcb_error( ic, "Could not connect to server" ); imc_logout( ic, TRUE ); return FALSE; } imcb_log( ic, "Connected to server, logging in" ); return jabber_start_stream( ic ); }
static xt_status jabber_parse_roster( struct im_connection *ic, struct xt_node *node, struct xt_node *orig ) { struct xt_node *query, *c; int initial = ( orig != NULL ); if( !( query = xt_find_node( node->children, "query" ) ) ) { imcb_log( ic, "Warning: Received NULL roster packet" ); return XT_HANDLED; } c = query->children; while( ( c = xt_find_node( c, "item" ) ) ) { struct xt_node *group = xt_find_node( c->children, "group" ); char *jid = xt_find_attr( c, "jid" ); char *name = xt_find_attr( c, "name" ); char *sub = xt_find_attr( c, "subscription" ); if( jid && sub ) { if( ( strcmp( sub, "both" ) == 0 || strcmp( sub, "to" ) == 0 ) ) { imcb_add_buddy( ic, jid, ( group && group->text_len ) ? group->text : NULL ); if( name ) imcb_rename_buddy( ic, jid, name ); } else if( strcmp( sub, "remove" ) == 0 ) { jabber_buddy_remove_bare( ic, jid ); imcb_remove_buddy( ic, jid, NULL ); } } c = c->next; } if( initial ) imcb_connected( ic ); return XT_HANDLED; }
xt_status jabber_iq_query_server( struct im_connection *ic, char *jid, char *xmlns ) { struct xt_node *node, *query; struct jabber_data *jd = ic->proto_data; node = xt_new_node( "query", NULL, NULL ); xt_add_attr( node, "xmlns", xmlns ); if( !( query = jabber_make_packet( "iq", "get", jid, node ) ) ) { imcb_log( ic, "WARNING: Couldn't generate server query" ); xt_free_node( node ); } jd->have_streamhosts--; jabber_cache_add( ic, query, jabber_iq_parse_server_features ); return jabber_write_packet( ic, query ) ? XT_HANDLED : XT_ABORT; }
/** * Implemented #SteamApiFunc for #steam_api_req_key(). * * @param req The #SteamApiReq. * @param data The user defined data, which is #SteamData. **/ static void steam_cb_key(SteamApiReq *req, gpointer data) { SteamData *sata = data; account_t *acc; gchar *ac; gchar *cc; if (steam_req_error(sata, req, TRUE)) return; acc = sata->ic->acc; ac = set_getstr(&acc->set, "authcode"); cc = set_getstr(&acc->set, "captcha"); imcb_log(sata->ic, "Requesting authentication token"); req = steam_api_req_new(req->api, steam_cb_auth, sata); steam_api_req_auth(req, acc->user, acc->pass, ac, cc); }
int sasl_oauth2_get_refresh_token( struct im_connection *ic, const char *msg ) { struct jabber_data *jd = ic->proto_data; char *code; int ret; imcb_log( ic, "Requesting OAuth access token" ); /* Don't do it here because the caller may get confused if the contact we're currently sending a message to is deleted. */ b_timeout_add( 1, sasl_oauth2_remove_contact, ic ); code = g_strdup( msg ); g_strstrip( code ); ret = oauth2_access_token( jd->oauth2_service, OAUTH2_AUTH_CODE, code, sasl_oauth2_got_token, ic ); g_free( code ); return ret; }
/* file_transfer canceled() callback */ void jabber_si_canceled(file_transfer_t *ft, char *reason) { struct jabber_transfer *tf = ft->data; struct xt_node *reply, *iqnode; if (tf->accepted) { return; } iqnode = jabber_make_packet("iq", "error", tf->ini_jid, NULL); xt_add_attr(iqnode, "id", tf->iq_id); reply = jabber_make_error_packet(iqnode, "forbidden", "cancel", "403"); xt_free_node(iqnode); if (!jabber_write_packet(tf->ic, reply)) { imcb_log(tf->ic, "WARNING: Error generating reply to file transfer request"); } xt_free_node(reply); }
static xt_status jabber_add_to_roster_callback( struct im_connection *ic, struct xt_node *node, struct xt_node *orig ) { char *s, *jid = NULL; struct xt_node *c; if( ( c = xt_find_node( orig->children, "query" ) ) && ( c = xt_find_node( c->children, "item" ) ) && ( jid = xt_find_attr( c, "jid" ) ) && ( s = xt_find_attr( node, "type" ) ) && strcmp( s, "result" ) == 0 ) { if( bee_user_by_handle( ic->bee, ic, jid ) == NULL ) imcb_add_buddy( ic, jid, NULL ); } else { imcb_log( ic, "Error while adding `%s' to your contact list.", jid ? jid : "(unknown handle)" ); } return XT_HANDLED; }
void msn_msgq_purge( struct im_connection *ic, GSList **list ) { struct msn_message *m; GString *ret; GSList *l; int n = 0; l = *list; if( l == NULL ) return; m = l->data; ret = g_string_sized_new( 1024 ); g_string_printf( ret, "Warning: Cleaning up MSN (switchboard) connection with unsent " "messages to %s:", m->who ? m->who : "unknown recipient" ); while( l ) { m = l->data; if( strncmp( m->text, "\r\r\r", 3 ) != 0 ) { g_string_append_printf( ret, "\n%s", m->text ); n ++; } g_free( m->who ); g_free( m->text ); g_free( m ); l = l->next; } g_slist_free( *list ); *list = NULL; if( n > 0 ) imcb_log( ic, "%s", ret->str ); g_string_free( ret, TRUE ); }
void imcb_buddy_msg(struct im_connection *ic, const char *handle, const char *msg, uint32_t flags, time_t sent_at) { bee_t *bee = ic->bee; bee_user_t *bu; bu = bee_user_by_handle(bee, ic, handle); if (!bu && !(ic->flags & OPT_LOGGING_OUT)) { char *h = set_getstr(&bee->set, "handle_unknown"); if (g_strcasecmp(h, "ignore") == 0) { return; } else if (g_strncasecmp(h, "add", 3) == 0) { bu = bee_user_new(bee, ic, handle, BEE_USER_LOCAL); } } if (bee->ui->user_msg && bu) { bee->ui->user_msg(bee, bu, msg, sent_at); } else { imcb_log(ic, "Message from unknown handle %s:\n%s", handle, msg); } }
xt_status sasl_pkt_mechanisms( struct xt_node *node, gpointer data ) { struct im_connection *ic = data; struct jabber_data *jd = ic->proto_data; struct xt_node *c, *reply; char *s; int sup_plain = 0, sup_digest = 0, sup_gtalk = 0, sup_fb = 0; int want_oauth = FALSE; GString *mechs; if( !sasl_supported( ic ) ) { /* Should abort this now, since we should already be doing IQ authentication. Strange things happen when you try to do both... */ imcb_log( ic, "XMPP 1.0 non-compliant server seems to support SASL, please report this as a BitlBee bug!" ); return XT_HANDLED; } s = xt_find_attr( node, "xmlns" ); if( !s || strcmp( s, XMLNS_SASL ) != 0 ) { imcb_log( ic, "Stream error while authenticating" ); imc_logout( ic, FALSE ); return XT_ABORT; } want_oauth = set_getbool( &ic->acc->set, "oauth" ); mechs = g_string_new( "" ); c = node->children; while( ( c = xt_find_node( c, "mechanism" ) ) ) { if( c->text && g_strcasecmp( c->text, "PLAIN" ) == 0 ) sup_plain = 1; else if( c->text && g_strcasecmp( c->text, "DIGEST-MD5" ) == 0 ) sup_digest = 1; else if( c->text && g_strcasecmp( c->text, "X-OAUTH2" ) == 0 ) sup_gtalk = 1; else if( c->text && g_strcasecmp( c->text, "X-FACEBOOK-PLATFORM" ) == 0 ) sup_fb = 1; if( c->text ) g_string_append_printf( mechs, " %s", c->text ); c = c->next; } if( !want_oauth && !sup_plain && !sup_digest ) { if( !sup_gtalk && !sup_fb ) imcb_error( ic, "This server requires OAuth " "(supported schemes:%s)", mechs->str ); else imcb_error( ic, "BitlBee does not support any of the offered SASL " "authentication schemes:%s", mechs->str ); imc_logout( ic, FALSE ); g_string_free( mechs, TRUE ); return XT_ABORT; } g_string_free( mechs, TRUE ); reply = xt_new_node( "auth", NULL, NULL ); xt_add_attr( reply, "xmlns", XMLNS_SASL ); if( sup_gtalk && want_oauth ) { int len; /* X-OAUTH2 is, not *the* standard OAuth2 SASL/XMPP implementation. It's currently used by GTalk and vaguely documented on http://code.google.com/apis/cloudprint/docs/rawxmpp.html . */ xt_add_attr( reply, "mechanism", "X-OAUTH2" ); len = strlen( jd->username ) + strlen( jd->oauth2_access_token ) + 2; s = g_malloc( len + 1 ); s[0] = 0; strcpy( s + 1, jd->username ); strcpy( s + 2 + strlen( jd->username ), jd->oauth2_access_token ); reply->text = base64_encode( (unsigned char *)s, len ); reply->text_len = strlen( reply->text ); g_free( s ); } else if( sup_fb && want_oauth ) { xt_add_attr( reply, "mechanism", "X-FACEBOOK-PLATFORM" ); jd->flags |= JFLAG_SASL_FB; } else if( want_oauth ) { imcb_error( ic, "OAuth requested, but not supported by server" ); imc_logout( ic, FALSE ); xt_free_node( reply ); return XT_ABORT; } else if( sup_digest ) { xt_add_attr( reply, "mechanism", "DIGEST-MD5" ); /* The rest will be done later, when we receive a <challenge/>. */ } else if( sup_plain ) { int len; xt_add_attr( reply, "mechanism", "PLAIN" ); /* With SASL PLAIN in XMPP, the text should be b64(\0user\0pass) */ len = strlen( jd->username ) + strlen( ic->acc->pass ) + 2; s = g_malloc( len + 1 ); s[0] = 0; strcpy( s + 1, jd->username ); strcpy( s + 2 + strlen( jd->username ), ic->acc->pass ); reply->text = base64_encode( (unsigned char *)s, len ); reply->text_len = strlen( reply->text ); g_free( s ); } if( reply && !jabber_write_packet( ic, reply ) ) { xt_free_node( reply ); return XT_ABORT; } xt_free_node( reply ); /* To prevent classic authentication from happening. */ jd->flags |= JFLAG_STREAM_STARTED; return XT_HANDLED; }
/* * First function that gets called when a file transfer request comes in. * A lot to parse. * * We choose a stream type from the options given by the initiator. * Then we wait for imcb to call the accept or cancel callbacks. */ int jabber_si_handle_request(struct im_connection *ic, struct xt_node *node, struct xt_node *sinode) { struct xt_node *c, *d, *reply; char *sid, *ini_jid, *tgt_jid, *iq_id, *s, *ext_jid, *size_s; struct jabber_buddy *bud; int requestok = FALSE; char *name, *cmp; size_t size; struct jabber_transfer *tf; struct jabber_data *jd = ic->proto_data; file_transfer_t *ft; /* All this means we expect something like this: ( I think ) * <iq from=... to=... id=...> * <si id=id xmlns=si profile=ft> * <file xmlns=ft/> * <feature xmlns=feature> * <x xmlns=xdata type=submit> * <field var=stream-method> * */ if (!(ini_jid = xt_find_attr(node, "from")) || !(tgt_jid = xt_find_attr(node, "to")) || !(iq_id = xt_find_attr(node, "id")) || !(sid = xt_find_attr(sinode, "id")) || !(cmp = xt_find_attr(sinode, "profile")) || !(0 == strcmp(cmp, XMLNS_FILETRANSFER)) || !(d = xt_find_node(sinode->children, "file")) || !(cmp = xt_find_attr(d, "xmlns")) || !(0 == strcmp(cmp, XMLNS_FILETRANSFER)) || !(name = xt_find_attr(d, "name")) || !(size_s = xt_find_attr(d, "size")) || !(1 == sscanf(size_s, "%zd", &size)) || !(d = xt_find_node(sinode->children, "feature")) || !(cmp = xt_find_attr(d, "xmlns")) || !(0 == strcmp(cmp, XMLNS_FEATURE)) || !(d = xt_find_node(d->children, "x")) || !(cmp = xt_find_attr(d, "xmlns")) || !(0 == strcmp(cmp, XMLNS_XDATA)) || !(cmp = xt_find_attr(d, "type")) || !(0 == strcmp(cmp, "form")) || !(d = xt_find_node(d->children, "field")) || !(cmp = xt_find_attr(d, "var")) || !(0 == strcmp(cmp, "stream-method"))) { imcb_log(ic, "WARNING: Received incomplete Stream Initiation request"); } else { /* Check if we support one of the options */ c = d->children; while ((c = xt_find_node(c, "option"))) { if ((d = xt_find_node(c->children, "value")) && (d->text != NULL) && (strcmp(d->text, XMLNS_BYTESTREAMS) == 0)) { requestok = TRUE; break; } else { c = c->next; } } if (!requestok) { imcb_log(ic, "WARNING: Unsupported file transfer request from %s", ini_jid); } } if (requestok) { /* Figure out who the transfer should come from... */ ext_jid = ini_jid; if ((s = strchr(ini_jid, '/'))) { if ((bud = jabber_buddy_by_jid(ic, ini_jid, GET_BUDDY_EXACT))) { bud->last_msg = time(NULL); ext_jid = bud->ext_jid ? : bud->bare_jid; } else { *s = 0; /* We need to generate a bare JID now. */ } }
/* Separate this from jabber_login() so we can do OAuth first if necessary. Putting this in io.c would probably be more correct. */ void jabber_connect( struct im_connection *ic ) { account_t *acc = ic->acc; struct jabber_data *jd = ic->proto_data; int i; char *connect_to; struct ns_srv_reply **srvl = NULL, *srv = NULL; /* Figure out the hostname to connect to. */ if( acc->server && *acc->server ) connect_to = acc->server; else if( ( srvl = srv_lookup( "xmpp-client", "tcp", jd->server ) ) || ( srvl = srv_lookup( "jabber-client", "tcp", jd->server ) ) ) { /* Find the lowest-priority one. These usually come back in random/shuffled order. Not looking at weights etc for now. */ srv = *srvl; for( i = 1; srvl[i]; i ++ ) if( srvl[i]->prio < srv->prio ) srv = srvl[i]; connect_to = srv->name; } else connect_to = jd->server; imcb_log( ic, "Connecting" ); for( i = 0; jabber_port_list[i] > 0; i ++ ) if( set_getint( &acc->set, "port" ) == jabber_port_list[i] ) break; if( jabber_port_list[i] == 0 ) { imcb_log( ic, "Illegal port number" ); imc_logout( ic, FALSE ); return; } /* For non-SSL connections we can try to use the port # from the SRV reply, but let's not do that when using SSL, SSL usually runs on non-standard ports... */ if( set_getbool( &acc->set, "ssl" ) ) { jd->ssl = ssl_connect( connect_to, set_getint( &acc->set, "port" ), FALSE, jabber_connected_ssl, ic ); jd->fd = jd->ssl ? ssl_getfd( jd->ssl ) : -1; } else { jd->fd = proxy_connect( connect_to, srv ? srv->port : set_getint( &acc->set, "port" ), jabber_connected_plain, ic ); } srv_free( srvl ); if( jd->fd == -1 ) { imcb_error( ic, "Could not connect to server" ); imc_logout( ic, TRUE ); return; } if( set_getbool( &acc->set, "xmlconsole" ) ) { jd->flags |= JFLAG_XMLCONSOLE; /* Shouldn't really do this at this stage already, maybe. But I think this shouldn't break anything. */ imcb_add_buddy( ic, JABBER_XMLCONSOLE_HANDLE, NULL ); } jabber_generate_id_hash( jd ); }
static void skype_parse_user(struct im_connection *ic, char *line) { int flags = 0; char *ptr; struct skype_data *sd = ic->proto_data; char *user = strchr(line, ' '); char *status = strrchr(line, ' '); status++; ptr = strchr(++user, ' '); if (!ptr) return; *ptr = '\0'; ptr++; if (!strncmp(ptr, "ONLINESTATUS ", 13)) { if (!strlen(user) || !strcmp(user, sd->username)) return; if (!set_getbool(&ic->acc->set, "test_join") && !strcmp(user, "echo123")) return; ptr = g_strdup_printf("*****@*****.**", user); imcb_add_buddy(ic, ptr, skype_group_by_username(ic, user)); if (strcmp(status, "OFFLINE") && (strcmp(status, "SKYPEOUT") || !set_getbool(&ic->acc->set, "skypeout_offline"))) flags |= OPT_LOGGED_IN; if (strcmp(status, "ONLINE") && strcmp(status, "SKYPEME")) flags |= OPT_AWAY; imcb_buddy_status(ic, ptr, flags, NULL, NULL); g_free(ptr); } else if (!strncmp(ptr, "RECEIVEDAUTHREQUEST ", 20)) { char *message = ptr + 20; if (strlen(message)) skype_buddy_ask(ic, user, message); } else if (!strncmp(ptr, "BUDDYSTATUS ", 12)) { char *st = ptr + 12; if (!strcmp(st, "3")) { char *buf = g_strdup_printf("*****@*****.**", user); imcb_add_buddy(ic, buf, skype_group_by_username(ic, user)); g_free(buf); } } else if (!strncmp(ptr, "MOOD_TEXT ", 10)) { char *buf = g_strdup_printf("*****@*****.**", user); bee_user_t *bu = bee_user_by_handle(ic->bee, ic, buf); g_free(buf); buf = ptr + 10; if (bu) imcb_buddy_status(ic, bu->handle, bu->flags, NULL, *buf ? buf : NULL); if (set_getbool(&ic->acc->set, "show_moods")) imcb_log(ic, "User `%s' changed mood text to `%s'", user, buf); } else if (!strncmp(ptr, "FULLNAME ", 9)) { char *name = ptr + 9; if (sd->is_info) { sd->is_info = FALSE; sd->info_fullname = g_strdup(name); } else { char *buf = g_strdup_printf("*****@*****.**", user); imcb_rename_buddy(ic, buf, name); g_free(buf); } } else if (!strncmp(ptr, "PHONE_HOME ", 11)) sd->info_phonehome = g_strdup(ptr + 11); else if (!strncmp(ptr, "PHONE_OFFICE ", 13)) sd->info_phoneoffice = g_strdup(ptr + 13); else if (!strncmp(ptr, "PHONE_MOBILE ", 13)) sd->info_phonemobile = g_strdup(ptr + 13); else if (!strncmp(ptr, "NROF_AUTHED_BUDDIES ", 20)) sd->info_nrbuddies = g_strdup(ptr + 20); else if (!strncmp(ptr, "TIMEZONE ", 9)) sd->info_tz = g_strdup(ptr + 9); else if (!strncmp(ptr, "LASTONLINETIMESTAMP ", 20)) sd->info_seen = g_strdup(ptr + 20); else if (!strncmp(ptr, "SEX ", 4)) sd->info_sex = g_strdup(ptr + 4); else if (!strncmp(ptr, "LANGUAGE ", 9)) sd->info_language = g_strdup(ptr + 9); else if (!strncmp(ptr, "COUNTRY ", 8)) sd->info_country = g_strdup(ptr + 8); else if (!strncmp(ptr, "PROVINCE ", 9)) sd->info_province = g_strdup(ptr + 9); else if (!strncmp(ptr, "CITY ", 5)) sd->info_city = g_strdup(ptr + 5); else if (!strncmp(ptr, "HOMEPAGE ", 9)) sd->info_homepage = g_strdup(ptr + 9); else if (!strncmp(ptr, "ABOUT ", 6)) { /* Support multiple about lines. */ if (!sd->info_about) sd->info_about = g_strdup(ptr + 6); else { GString *st = g_string_new(sd->info_about); g_string_append_printf(st, "\n%s", ptr + 6); g_free(sd->info_about); sd->info_about = g_strdup(st->str); g_string_free(st, TRUE); } } else if (!strncmp(ptr, "BIRTHDAY ", 9)) { sd->info_birthday = g_strdup(ptr + 9); GString *st = g_string_new("Contact Information\n"); g_string_append_printf(st, "Skype Name: %s\n", user); if (sd->info_fullname) { if (strlen(sd->info_fullname)) g_string_append_printf(st, "Full Name: %s\n", sd->info_fullname); g_free(sd->info_fullname); sd->info_fullname = NULL; } if (sd->info_phonehome) { if (strlen(sd->info_phonehome)) g_string_append_printf(st, "Home Phone: %s\n", sd->info_phonehome); g_free(sd->info_phonehome); sd->info_phonehome = NULL; } if (sd->info_phoneoffice) { if (strlen(sd->info_phoneoffice)) g_string_append_printf(st, "Office Phone: %s\n", sd->info_phoneoffice); g_free(sd->info_phoneoffice); sd->info_phoneoffice = NULL; } if (sd->info_phonemobile) { if (strlen(sd->info_phonemobile)) g_string_append_printf(st, "Mobile Phone: %s\n", sd->info_phonemobile); g_free(sd->info_phonemobile); sd->info_phonemobile = NULL; } g_string_append_printf(st, "Personal Information\n"); if (sd->info_nrbuddies) { if (strlen(sd->info_nrbuddies)) g_string_append_printf(st, "Contacts: %s\n", sd->info_nrbuddies); g_free(sd->info_nrbuddies); sd->info_nrbuddies = NULL; } if (sd->info_tz) { if (strlen(sd->info_tz)) { char ib[256]; time_t t = time(NULL); t += atoi(sd->info_tz)-(60*60*24); struct tm *gt = gmtime(&t); strftime(ib, 256, "%H:%M:%S", gt); g_string_append_printf(st, "Local Time: %s\n", ib); } g_free(sd->info_tz); sd->info_tz = NULL; } if (sd->info_seen) { if (strlen(sd->info_seen)) { char ib[256]; time_t it = atoi(sd->info_seen); struct tm *tm = localtime(&it); strftime(ib, 256, ("%Y. %m. %d. %H:%M"), tm); g_string_append_printf(st, "Last Seen: %s\n", ib); } g_free(sd->info_seen); sd->info_seen = NULL; } if (sd->info_birthday) { if (strlen(sd->info_birthday) && strcmp(sd->info_birthday, "0")) { char ib[256]; struct tm tm; strptime(sd->info_birthday, "%Y%m%d", &tm); strftime(ib, 256, "%B %d, %Y", &tm); g_string_append_printf(st, "Birthday: %s\n", ib); strftime(ib, 256, "%Y", &tm); int year = atoi(ib); time_t t = time(NULL); struct tm *lt = localtime(&t); g_string_append_printf(st, "Age: %d\n", lt->tm_year+1900-year); } g_free(sd->info_birthday); sd->info_birthday = NULL; } if (sd->info_sex) { if (strlen(sd->info_sex)) { char *iptr = sd->info_sex; while (*iptr++) *iptr = tolower(*iptr); g_string_append_printf(st, "Gender: %s\n", sd->info_sex); } g_free(sd->info_sex); sd->info_sex = NULL; } if (sd->info_language) { if (strlen(sd->info_language)) { char *iptr = strchr(sd->info_language, ' '); if (iptr) iptr++; else iptr = sd->info_language; g_string_append_printf(st, "Language: %s\n", iptr); } g_free(sd->info_language); sd->info_language = NULL; } if (sd->info_country) { if (strlen(sd->info_country)) { char *iptr = strchr(sd->info_country, ' '); if (iptr) iptr++; else iptr = sd->info_country; g_string_append_printf(st, "Country: %s\n", iptr); } g_free(sd->info_country); sd->info_country = NULL; } if (sd->info_province) { if (strlen(sd->info_province)) g_string_append_printf(st, "Region: %s\n", sd->info_province); g_free(sd->info_province); sd->info_province = NULL; } if (sd->info_city) { if (strlen(sd->info_city)) g_string_append_printf(st, "City: %s\n", sd->info_city); g_free(sd->info_city); sd->info_city = NULL; } if (sd->info_homepage) { if (strlen(sd->info_homepage)) g_string_append_printf(st, "Homepage: %s\n", sd->info_homepage); g_free(sd->info_homepage); sd->info_homepage = NULL; } if (sd->info_about) { if (strlen(sd->info_about)) g_string_append_printf(st, "%s\n", sd->info_about); g_free(sd->info_about); sd->info_about = NULL; } imcb_log(ic, "%s", st->str); g_string_free(st, TRUE); } }
/* * Query the server for "items", query each "item" for identities, query each "item" that's a proxy for it's bytestream info */ xt_status jabber_iq_parse_server_features( struct im_connection *ic, struct xt_node *node, struct xt_node *orig ) { struct xt_node *c; struct jabber_data *jd = ic->proto_data; char *xmlns, *from; if( !( c = xt_find_node( node->children, "query" ) ) || !( from = xt_find_attr( node, "from" ) ) || !( xmlns = xt_find_attr( c, "xmlns" ) ) ) { imcb_log( ic, "WARNING: Received incomplete IQ-result packet for discover" ); return XT_HANDLED; } jd->have_streamhosts++; if( strcmp( xmlns, XMLNS_DISCO_ITEMS ) == 0 ) { char *itemjid; /* answer from server */ c = c->children; while( ( c = xt_find_node( c, "item" ) ) ) { itemjid = xt_find_attr( c, "jid" ); if( itemjid ) jabber_iq_query_server( ic, itemjid, XMLNS_DISCO_INFO ); c = c->next; } } else if( strcmp( xmlns, XMLNS_DISCO_INFO ) == 0 ) { char *category, *type; /* answer from potential proxy */ c = c->children; while( ( c = xt_find_node( c, "identity" ) ) ) { category = xt_find_attr( c, "category" ); type = xt_find_attr( c, "type" ); if( type && ( strcmp( type, "bytestreams" ) == 0 ) && category && ( strcmp( category, "proxy" ) == 0 ) ) jabber_iq_query_server( ic, from, XMLNS_BYTESTREAMS ); c = c->next; } } else if( strcmp( xmlns, XMLNS_BYTESTREAMS ) == 0 ) { char *host, *jid, *port_s; int port; /* answer from proxy */ if( ( c = xt_find_node( c->children, "streamhost" ) ) && ( host = xt_find_attr( c, "host" ) ) && ( port_s = xt_find_attr( c, "port" ) ) && ( sscanf( port_s, "%d", &port ) == 1 ) && ( jid = xt_find_attr( c, "jid" ) ) ) { jabber_streamhost_t *sh = g_new0( jabber_streamhost_t, 1 ); sh->jid = g_strdup( jid ); sh->host = g_strdup( host ); g_snprintf( sh->port, sizeof( sh->port ), "%u", port ); imcb_log( ic, "Proxy found: jid %s host %s port %u", jid, host, port ); jd->streamhosts = g_slist_append( jd->streamhosts, sh ); } } if( jd->have_streamhosts == 0 ) jd->have_streamhosts++; return XT_HANDLED; }
static xt_status jabber_iq_display_vcard( struct im_connection *ic, struct xt_node *node, struct xt_node *orig ) { struct xt_node *vc, *c, *sc; /* subchild, ic is already in use ;-) */ GString *reply; char *s; if( ( s = xt_find_attr( node, "type" ) ) == NULL || strcmp( s, "result" ) != 0 || ( vc = xt_find_node( node->children, "vCard" ) ) == NULL ) { s = xt_find_attr( orig, "to" ); /* If this returns NULL something's wrong.. */ imcb_log( ic, "Could not retrieve vCard of %s", s ? s : "(NULL)" ); return XT_HANDLED; } s = xt_find_attr( orig, "to" ); reply = g_string_new( "vCard information for " ); reply = g_string_append( reply, s ? s : "(NULL)" ); reply = g_string_append( reply, ":\n" ); /* I hate this format, I really do... */ if( ( c = xt_find_node( vc->children, "FN" ) ) && c->text_len ) g_string_append_printf( reply, "Name: %s\n", c->text ); if( ( c = xt_find_node( vc->children, "N" ) ) && c->children ) { reply = g_string_append( reply, "Full name:" ); if( ( sc = xt_find_node( c->children, "PREFIX" ) ) && sc->text_len ) g_string_append_printf( reply, " %s", sc->text ); if( ( sc = xt_find_node( c->children, "GIVEN" ) ) && sc->text_len ) g_string_append_printf( reply, " %s", sc->text ); if( ( sc = xt_find_node( c->children, "MIDDLE" ) ) && sc->text_len ) g_string_append_printf( reply, " %s", sc->text ); if( ( sc = xt_find_node( c->children, "FAMILY" ) ) && sc->text_len ) g_string_append_printf( reply, " %s", sc->text ); if( ( sc = xt_find_node( c->children, "SUFFIX" ) ) && sc->text_len ) g_string_append_printf( reply, " %s", sc->text ); reply = g_string_append_c( reply, '\n' ); } if( ( c = xt_find_node( vc->children, "NICKNAME" ) ) && c->text_len ) g_string_append_printf( reply, "Nickname: %s\n", c->text ); if( ( c = xt_find_node( vc->children, "BDAY" ) ) && c->text_len ) g_string_append_printf( reply, "Date of birth: %s\n", c->text ); /* Slightly alternative use of for... ;-) */ for( c = vc->children; ( c = xt_find_node( c, "EMAIL" ) ); c = c->next ) { if( ( sc = xt_find_node( c->children, "USERID" ) ) == NULL || sc->text_len == 0 ) continue; if( xt_find_node( c->children, "HOME" ) ) s = "Home"; else if( xt_find_node( c->children, "WORK" ) ) s = "Work"; else s = "Misc."; g_string_append_printf( reply, "%s e-mail address: %s\n", s, sc->text ); } if( ( c = xt_find_node( vc->children, "URL" ) ) && c->text_len ) g_string_append_printf( reply, "Homepage: %s\n", c->text ); /* Slightly alternative use of for... ;-) */ for( c = vc->children; ( c = xt_find_node( c, "ADR" ) ); c = c->next ) { if( xt_find_node( c->children, "HOME" ) ) s = "Home"; else if( xt_find_node( c->children, "WORK" ) ) s = "Work"; else s = "Misc."; g_string_append_printf( reply, "%s address: ", s ); if( ( sc = xt_find_node( c->children, "STREET" ) ) && sc->text_len ) g_string_append_printf( reply, "%s ", sc->text ); if( ( sc = xt_find_node( c->children, "EXTADR" ) ) && sc->text_len ) g_string_append_printf( reply, "%s, ", sc->text ); if( ( sc = xt_find_node( c->children, "PCODE" ) ) && sc->text_len ) g_string_append_printf( reply, "%s, ", sc->text ); if( ( sc = xt_find_node( c->children, "LOCALITY" ) ) && sc->text_len ) g_string_append_printf( reply, "%s, ", sc->text ); if( ( sc = xt_find_node( c->children, "REGION" ) ) && sc->text_len ) g_string_append_printf( reply, "%s, ", sc->text ); if( ( sc = xt_find_node( c->children, "CTRY" ) ) && sc->text_len ) g_string_append_printf( reply, "%s", sc->text ); if( reply->str[reply->len-2] == ',' ) reply = g_string_truncate( reply, reply->len-2 ); reply = g_string_append_c( reply, '\n' ); } for( c = vc->children; ( c = xt_find_node( c, "TEL" ) ); c = c->next ) { if( ( sc = xt_find_node( c->children, "NUMBER" ) ) == NULL || sc->text_len == 0 ) continue; if( xt_find_node( c->children, "HOME" ) ) s = "Home"; else if( xt_find_node( c->children, "WORK" ) ) s = "Work"; else s = "Misc."; g_string_append_printf( reply, "%s phone number: %s\n", s, sc->text ); } if( ( c = xt_find_node( vc->children, "DESC" ) ) && c->text_len ) g_string_append_printf( reply, "Other information:\n%s", c->text ); /* *sigh* */ imcb_log( ic, "%s", reply->str ); g_string_free( reply, TRUE ); return XT_HANDLED; }
static void skype_parse_call(struct im_connection *ic, char *line) { struct skype_data *sd = ic->proto_data; char *id = strchr(line, ' '); char buf[IRC_LINE_SIZE]; if (!++id) return; char *info = strchr(id, ' '); if (!info) return; *info = '\0'; info++; if (!strncmp(info, "FAILUREREASON ", 14)) sd->failurereason = atoi(strchr(info, ' ')); else if (!strcmp(info, "STATUS RINGING")) { if (sd->call_id) g_free(sd->call_id); sd->call_id = g_strdup(id); skype_printf(ic, "GET CALL %s PARTNER_HANDLE\n", id); sd->call_status = SKYPE_CALL_RINGING; } else if (!strcmp(info, "STATUS MISSED")) { skype_printf(ic, "GET CALL %s PARTNER_HANDLE\n", id); sd->call_status = SKYPE_CALL_MISSED; } else if (!strcmp(info, "STATUS CANCELLED")) { skype_printf(ic, "GET CALL %s PARTNER_HANDLE\n", id); sd->call_status = SKYPE_CALL_CANCELLED; } else if (!strcmp(info, "STATUS FINISHED")) { skype_printf(ic, "GET CALL %s PARTNER_HANDLE\n", id); sd->call_status = SKYPE_CALL_FINISHED; } else if (!strcmp(info, "STATUS REFUSED")) { skype_printf(ic, "GET CALL %s PARTNER_HANDLE\n", id); sd->call_status = SKYPE_CALL_REFUSED; } else if (!strcmp(info, "STATUS UNPLACED")) { if (sd->call_id) g_free(sd->call_id); /* Save the ID for later usage (Cancel/Finish). */ sd->call_id = g_strdup(id); sd->call_out = TRUE; } else if (!strcmp(info, "STATUS FAILED")) { imcb_error(ic, "Call failed: %s", skype_call_strerror(sd->failurereason)); sd->call_id = NULL; } else if (!strncmp(info, "DURATION ", 9)) { if (sd->call_duration) g_free(sd->call_duration); sd->call_duration = g_strdup(info+9); } else if (!strncmp(info, "PARTNER_HANDLE ", 15)) { info += 15; if (!sd->call_status) return; switch (sd->call_status) { case SKYPE_CALL_RINGING: if (sd->call_out) imcb_log(ic, "You are currently ringing the user %s.", info); else { g_snprintf(buf, IRC_LINE_SIZE, "The user %s is currently ringing you.", info); skype_call_ask(ic, sd->call_id, buf); } break; case SKYPE_CALL_MISSED: imcb_log(ic, "You have missed a call from user %s.", info); break; case SKYPE_CALL_CANCELLED: imcb_log(ic, "You cancelled the call to the user %s.", info); sd->call_status = 0; sd->call_out = FALSE; break; case SKYPE_CALL_REFUSED: if (sd->call_out) imcb_log(ic, "The user %s refused the call.", info); else imcb_log(ic, "You refused the call from user %s.", info); sd->call_out = FALSE; break; case SKYPE_CALL_FINISHED: if (sd->call_duration) imcb_log(ic, "You finished the call to the user %s " "(duration: %s seconds).", info, sd->call_duration); else imcb_log(ic, "You finished the call to the user %s.", info); sd->call_out = FALSE; break; default: /* Don't be noisy, ignore other statuses for now. */ break; } sd->call_status = 0; } }
xt_status jabber_pkt_bind_sess( struct im_connection *ic, struct xt_node *node, struct xt_node *orig ) { struct jabber_data *jd = ic->proto_data; struct xt_node *c, *reply = NULL; char *s; if( node && ( c = xt_find_node( node->children, "bind" ) ) ) { c = xt_find_node( c->children, "jid" ); if( !c || !c->text ) { /* Server is crap, but this is no disaster. */ } else if( strncmp( jd->me, c->text, strlen( jd->me ) ) != 0 ) { s = strchr( c->text, '/' ); if( s ) *s = '\0'; jabber_set_me( ic, c->text ); imcb_log( ic, "Server claims your JID is `%s' instead of `%s'. " "This mismatch may cause problems with groupchats " "and possibly other things.", c->text, ic->acc->user ); if( s ) *s = '/'; } else if( c && c->text_len && ( s = strchr( c->text, '/' ) ) && strcmp( s + 1, set_getstr( &ic->acc->set, "resource" ) ) != 0 ) imcb_log( ic, "Server changed session resource string to `%s'", s + 1 ); } if( jd->flags & JFLAG_WANT_BIND ) { reply = xt_new_node( "bind", NULL, xt_new_node( "resource", set_getstr( &ic->acc->set, "resource" ), NULL ) ); xt_add_attr( reply, "xmlns", XMLNS_BIND ); jd->flags &= ~JFLAG_WANT_BIND; } else if( jd->flags & JFLAG_WANT_SESSION ) { reply = xt_new_node( "session", NULL, NULL ); xt_add_attr( reply, "xmlns", XMLNS_SESSION ); jd->flags &= ~JFLAG_WANT_SESSION; } if( reply != NULL ) { reply = jabber_make_packet( "iq", "set", NULL, reply ); jabber_cache_add( ic, reply, jabber_pkt_bind_sess ); if( !jabber_write_packet( ic, reply ) ) return XT_ABORT; } else if( ( jd->flags & ( JFLAG_WANT_BIND | JFLAG_WANT_SESSION ) ) == 0 ) { if( !jabber_get_roster( ic ) ) return XT_ABORT; if( !jabber_iq_disco_server( ic ) ) return XT_ABORT; } return XT_HANDLED; }
xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) { struct im_connection *ic = data; struct jabber_data *jd = ic->proto_data; struct xt_node *c, *reply = NULL; char *type, *s; int st, pack = 1; type = xt_find_attr( node, "type" ); if( !type ) { imcb_error( ic, "Received IQ packet without type." ); imc_logout( ic, TRUE ); return XT_ABORT; } if( strcmp( type, "result" ) == 0 || strcmp( type, "error" ) == 0 ) { return jabber_cache_handle_packet( ic, node ); } else if( strcmp( type, "get" ) == 0 ) { if( !( ( c = xt_find_node( node->children, "query" ) ) || ( c = xt_find_node( node->children, "ping" ) ) || ( c = xt_find_node( node->children, "time" ) ) ) || !( s = xt_find_attr( c, "xmlns" ) ) ) { /* Sigh. Who decided to suddenly invent new elements instead of just sticking with <query/>? */ return XT_HANDLED; } reply = xt_new_node( "query", NULL, NULL ); xt_add_attr( reply, "xmlns", s ); /* Of course this is a very essential query to support. ;-) */ if( strcmp( s, XMLNS_VERSION ) == 0 ) { xt_add_child( reply, xt_new_node( "name", set_getstr( &ic->acc->set, "user_agent" ), NULL ) ); xt_add_child( reply, xt_new_node( "version", BITLBEE_VERSION, NULL ) ); xt_add_child( reply, xt_new_node( "os", ARCH, NULL ) ); } else if( strcmp( s, XMLNS_TIME_OLD ) == 0 ) { time_t time_ep; char buf[1024]; buf[sizeof(buf)-1] = 0; time_ep = time( NULL ); strftime( buf, sizeof( buf ) - 1, "%Y%m%dT%H:%M:%S", gmtime( &time_ep ) ); xt_add_child( reply, xt_new_node( "utc", buf, NULL ) ); strftime( buf, sizeof( buf ) - 1, "%Z", localtime( &time_ep ) ); xt_add_child( reply, xt_new_node( "tz", buf, NULL ) ); } else if( strcmp( s, XMLNS_TIME ) == 0 ) { time_t time_ep; char buf[1024]; buf[sizeof(buf)-1] = 0; time_ep = time( NULL ); xt_free_node( reply ); reply = xt_new_node( "time", NULL, NULL ); xt_add_attr( reply, "xmlns", XMLNS_TIME ); strftime( buf, sizeof( buf ) - 1, "%Y%m%dT%H:%M:%SZ", gmtime( &time_ep ) ); xt_add_child( reply, xt_new_node( "utc", buf, NULL ) ); strftime( buf, sizeof( buf ) - 1, "%z", localtime( &time_ep ) ); if( strlen( buf ) >= 5 ) { buf[6] = '\0'; buf[5] = buf[4]; buf[4] = buf[3]; buf[3] = ':'; } xt_add_child( reply, xt_new_node( "tzo", buf, NULL ) ); } else if( strcmp( s, XMLNS_PING ) == 0 ) { xt_free_node( reply ); reply = jabber_make_packet( "iq", "result", xt_find_attr( node, "from" ), NULL ); if( ( s = xt_find_attr( node, "id" ) ) ) xt_add_attr( reply, "id", s ); pack = 0; } else if( strcmp( s, XMLNS_DISCO_INFO ) == 0 ) { const char *features[] = { XMLNS_DISCO_INFO, XMLNS_VERSION, XMLNS_TIME_OLD, XMLNS_TIME, XMLNS_CHATSTATES, XMLNS_MUC, XMLNS_PING, XMLNS_SI, XMLNS_BYTESTREAMS, XMLNS_FILETRANSFER, NULL }; const char **f; c = xt_new_node( "identity", NULL, NULL ); xt_add_attr( c, "category", "client" ); xt_add_attr( c, "type", "pc" ); xt_add_attr( c, "name", set_getstr( &ic->acc->set, "user_agent" ) ); xt_add_child( reply, c ); for( f = features; *f; f ++ ) { c = xt_new_node( "feature", NULL, NULL ); xt_add_attr( c, "var", *f ); xt_add_child( reply, c ); } } else { xt_free_node( reply ); reply = jabber_make_error_packet( node, "feature-not-implemented", "cancel", NULL ); pack = 0; } } else if( strcmp( type, "set" ) == 0 ) { if( ( c = xt_find_node( node->children, "si" ) ) && ( s = xt_find_attr( c, "xmlns" ) ) && ( strcmp( s, XMLNS_SI ) == 0 ) ) { return jabber_si_handle_request( ic, node, c ); } else if( !( c = xt_find_node( node->children, "query" ) ) || !( s = xt_find_attr( c, "xmlns" ) ) ) { return XT_HANDLED; } else if( strcmp( s, XMLNS_ROSTER ) == 0 ) { /* This is a roster push. XMPP servers send this when someone was added to (or removed from) the buddy list. AFAIK they're sent even if we added this buddy in our own session. */ int bare_len = strlen( jd->me ); if( ( s = xt_find_attr( node, "from" ) ) == NULL || ( strncmp( s, jd->me, bare_len ) == 0 && ( s[bare_len] == 0 || s[bare_len] == '/' ) ) ) { jabber_parse_roster( ic, node, NULL ); /* Should we generate a reply here? Don't think it's very important... */ } else { imcb_log( ic, "Warning: %s tried to fake a roster push!", s ? s : "(unknown)" ); xt_free_node( reply ); reply = jabber_make_error_packet( node, "not-allowed", "cancel", NULL ); pack = 0; } } else if( strcmp( s, XMLNS_BYTESTREAMS ) == 0 ) { /* Bytestream Request (stage 2 of file transfer) */ return jabber_bs_recv_request( ic, node, c ); } else { xt_free_node( reply ); reply = jabber_make_error_packet( node, "feature-not-implemented", "cancel", NULL ); pack = 0; } } /* If we recognized the xmlns and managed to generate a reply, finish and send it. */ if( reply ) { /* Normally we still have to pack it into an iq-result packet, but for errors, for example, we don't. */ if( pack ) { reply = jabber_make_packet( "iq", "result", xt_find_attr( node, "from" ), reply ); if( ( s = xt_find_attr( node, "id" ) ) ) xt_add_attr( reply, "id", s ); } st = jabber_write_packet( ic, reply ); xt_free_node( reply ); if( !st ) return XT_ABORT; } return XT_HANDLED; }
static void prplcb_conn_progress( PurpleConnection *gc, const char *text, size_t step, size_t step_count ) { struct im_connection *ic = purple_ic_by_gc( gc ); imcb_log( ic, "%s", text ); }
static void steam_cb_user_info_nicks(SteamApiReq *req, gpointer data) { const gchar *ctr; gchar *str; GSList *l; guint i; SteamData *sata = data; SteamUserInfo *info = req->infs->head->data; if (steam_req_error(sata, req, TRUE)) { return; } if (info->fullname != NULL) { imcb_log(sata->ic, "Name: %s (%s)", info->nick, info->fullname); } else { imcb_log(sata->ic, "Name: %s", info->nick); } if (info->game != NULL) { if (info->server != NULL) { imcb_log(sata->ic, "Playing: %s - steam://connect/%s", info->game, info->server); } else { imcb_log(sata->ic, "Playing: %s", info->game); } } ctr = steam_user_state_str(info->state); if (info->state == STEAM_USER_STATE_OFFLINE) { str = steam_util_time_since_utc(info->ltime); } else { str = steam_user_flags_str(info->flags); } if (str != NULL) { imcb_log(sata->ic, "Status: %s (%s)", ctr, str); g_free(str); } else { imcb_log(sata->ic, "Status: %s", ctr); } imcb_log(sata->ic, "Steam ID: %" STEAM_ID_FORMAT " (%" G_GINT32_FORMAT ")", info->id, STEAM_ID_ACCID(info->id)); if (info->profile != NULL) { imcb_log(sata->ic, "Profile: %s", info->profile); } if (info->nicks != NULL) { imcb_log(sata->ic, "Nicknames:"); for (l = info->nicks, i = 1; l != NULL; l = l->next, i++) { imcb_log(sata->ic, "%u. `%s'", i, (gchar *) l->data); } } steam_user_status(sata, info, NULL); }