/** * Callback for getting the friends ids. */ static void twitter_http_get_friends_ids(struct http_request *req) { struct im_connection *ic; struct xt_parser *parser; struct twitter_xml_list *txl; struct twitter_data *td; ic = req->data; // Check if the connection is still active. if (!g_slist_find(twitter_connections, ic)) return; td = ic->proto_data; // Check if the HTTP request went well. More strict checks as this is // the first request we do in a session. if (req->status_code == 401) { imcb_error(ic, "Authentication failure"); imc_logout(ic, FALSE); return; } else if (req->status_code != 200) { // It didn't go well, output the error and return. imcb_error(ic, "Could not retrieve %s: %s", TWITTER_FRIENDS_IDS_URL, twitter_parse_error(req)); imc_logout(ic, TRUE); return; } else { td->http_fails = 0; } /* Create the room now that we "logged in". */ if (!td->timeline_gc && g_strcasecmp(set_getstr(&ic->acc->set, "mode"), "chat") == 0) twitter_groupchat_init(ic); txl = g_new0(struct twitter_xml_list, 1); txl->list = td->follow_ids; // Parse the data. parser = xt_new(NULL, txl); xt_feed(parser, req->reply_body, req->body_size); twitter_xt_get_friends_id_list(parser->root, txl); xt_free(parser); td->follow_ids = txl->list; if (txl->next_cursor) /* These were just numbers. Up to 4000 in a response AFAIK so if we get here we may be using a spammer account. \o/ */ twitter_get_friends_ids(ic, txl->next_cursor); else /* Now to convert all those numbers into names.. */ twitter_get_users_lookup(ic); txl->list = NULL; txl_free(txl); }
/** * Callback for getting (twitter)friends... * * Be afraid, be very afraid! This function will potentially add hundreds of "friends". "Who has * hundreds of friends?" you wonder? You probably not, since you are reading the source of * BitlBee... Get a life and meet new people! */ static void twitter_http_get_users_lookup(struct http_request *req) { struct im_connection *ic = req->data; struct twitter_data *td; struct xt_parser *parser; struct twitter_xml_list *txl; GSList *l = NULL; struct twitter_xml_user *user; // Check if the connection is still active. if (!g_slist_find(twitter_connections, ic)) return; td = ic->proto_data; if (req->status_code != 200) { // It didn't go well, output the error and return. imcb_error(ic, "Could not retrieve %s: %s", TWITTER_USERS_LOOKUP_URL, twitter_parse_error(req)); imc_logout(ic, TRUE); return; } else { td->http_fails = 0; } txl = g_new0(struct twitter_xml_list, 1); txl->list = NULL; // Parse the data. parser = xt_new(NULL, txl); xt_feed(parser, req->reply_body, req->body_size); // Get the user list from the parsed xml feed. twitter_xt_get_users(parser->root, txl); xt_free(parser); // Add the users as buddies. for (l = txl->list; l; l = g_slist_next(l)) { user = l->data; twitter_add_buddy(ic, user->screen_name, user->name); } // Free the structure. txl_free(txl); twitter_get_users_lookup(ic); }
struct xt_node *xt_from_string(const char *in, int len) { struct xt_parser *parser; struct xt_node *ret = NULL; if (len == 0) { len = strlen(in); } parser = xt_new(NULL, NULL); xt_feed(parser, in, len); if (parser->cur == NULL) { ret = parser->root; parser->root = NULL; } xt_free(parser); return ret; }
/* Warning: May return a malloc()ed value, which will be free()d on the next call. Only for short-term use. NOT THREADSAFE! */ char *twitter_parse_error(struct http_request *req) { static char *ret = NULL; struct xt_parser *xp = NULL; struct xt_node *node, *err; g_free(ret); ret = NULL; if (req->body_size > 0) { xp = xt_new(NULL, NULL); xt_feed(xp, req->reply_body, req->body_size); for (node = xp->root; node; node = node->next) if ((err = xt_find_node(node->children, "error")) && err->text_len > 0) { ret = g_strdup_printf("%s (%s)", req->status_string, err->text); break; } xt_free(xp); } return ret ? ret : req->status_string; }
static gboolean jabber_read_callback( gpointer data, gint fd, b_input_condition cond ) { struct im_connection *ic = data; struct jabber_data *jd = ic->proto_data; char buf[512]; int st; if( jd->fd == -1 ) return FALSE; if( jd->ssl ) st = ssl_read( jd->ssl, buf, sizeof( buf ) ); else st = read( jd->fd, buf, sizeof( buf ) ); if( st > 0 ) { /* Parse. */ if( xt_feed( jd->xt, buf, st ) < 0 ) { imcb_error( ic, "XML stream error" ); imc_logout( ic, TRUE ); return FALSE; } /* Execute all handlers. */ if( !xt_handle( jd->xt, NULL, 1 ) ) { /* Don't do anything, the handlers should have aborted the connection already. */ return FALSE; } if( jd->flags & JFLAG_STREAM_RESTART ) { jd->flags &= ~JFLAG_STREAM_RESTART; jabber_start_stream( ic ); } /* Garbage collection. */ xt_cleanup( jd->xt, NULL, 1 ); /* This is a bit hackish, unfortunately. Although xmltree has nifty event handler stuff, it only calls handlers when nodes are complete. Since the server should only send an opening <stream:stream> tag, we have to check this by hand. :-( */ if( !( jd->flags & JFLAG_STREAM_STARTED ) && jd->xt && jd->xt->root ) { if( g_strcasecmp( jd->xt->root->name, "stream:stream" ) == 0 ) { jd->flags |= JFLAG_STREAM_STARTED; /* If there's no version attribute, assume this is an old server that can't do SASL authentication. */ if( !sasl_supported( ic ) ) { /* If there's no version= tag, we suppose this server does NOT implement: XMPP 1.0, SASL and TLS. */ if( set_getbool( &ic->acc->set, "tls" ) ) { imcb_error( ic, "TLS is turned on for this " "account, but is not supported by this server" ); imc_logout( ic, FALSE ); return FALSE; } else { return jabber_init_iq_auth( ic ); } } } else { imcb_error( ic, "XML stream error" ); imc_logout( ic, TRUE ); return FALSE; } } } else if( st == 0 || ( st < 0 && !ssl_sockerr_again( jd->ssl ) ) ) { closesocket( jd->fd ); jd->fd = -1; imcb_error( ic, "Error while reading from server" ); imc_logout( ic, TRUE ); return FALSE; } if( ssl_pending( jd->ssl ) ) /* OpenSSL empties the TCP buffers completely but may keep some data in its internap buffers. select() won't see that, but ssl_pending() does. */ return jabber_read_callback( data, fd, cond ); else return TRUE; }
static storage_status_t xml_load_real( irc_t *irc, const char *my_nick, const char *password, xml_pass_st action ) { struct xml_parsedata xd[1]; char *fn, buf[2048]; int fd, st; struct xt_parser *xp = NULL; struct xt_node *node; storage_status_t ret = STORAGE_OTHER_ERROR; xd->irc = irc; strncpy( xd->given_nick, my_nick, MAX_NICK_LENGTH ); xd->given_nick[MAX_NICK_LENGTH] = '\0'; nick_lc( NULL, xd->given_nick ); xd->given_pass = (char*) password; fn = g_strconcat( global.conf->configdir, xd->given_nick, ".xml", NULL ); if( ( fd = open( fn, O_RDONLY ) ) < 0 ) { ret = STORAGE_NO_SUCH_USER; goto error; } xp = xt_new( handlers, xd ); while( ( st = read( fd, buf, sizeof( buf ) ) ) > 0 ) { st = xt_feed( xp, buf, st ); if( st != 1 ) break; } close( fd ); if( st != 0 ) goto error; node = xp->root; if( node == NULL || node->next != NULL || strcmp( node->name, "user" ) != 0 ) goto error; { char *nick = xt_find_attr( node, "nick" ); char *pass = xt_find_attr( node, "password" ); if( !nick || !pass ) { goto error; } else if( ( st = md5_verify_password( xd->given_pass, pass ) ) != 0 ) { ret = STORAGE_INVALID_PASSWORD; goto error; } } if( action == XML_PASS_CHECK_ONLY ) { ret = STORAGE_OK; goto error; } /* DO NOT call xt_handle() before verifying the password! */ if( xt_handle( xp, NULL, 1 ) == XT_HANDLED ) ret = STORAGE_OK; handle_settings( node, &xd->irc->b->set ); error: xt_free( xp ); g_free( fn ); return ret; }
static storage_status_t xml_load_real(irc_t *irc, const char *my_nick, const char *password, xml_action action) { struct xml_parsedata xd[1]; char *fn, buf[2048]; int fd, st; struct xt_parser *xp = NULL; struct xt_node *node; storage_status_t ret = STORAGE_OTHER_ERROR; xd->irc = irc; strncpy(xd->given_nick, my_nick, MAX_NICK_LENGTH); xd->given_nick[MAX_NICK_LENGTH] = '\0'; nick_lc(NULL, xd->given_nick); xd->given_pass = (char *) password; fn = g_strconcat(global.conf->configdir, xd->given_nick, ".xml", NULL); if ((fd = open(fn, O_RDONLY)) < 0) { if (errno == ENOENT) { ret = STORAGE_NO_SUCH_USER; } else { irc_rootmsg(irc, "Error loading user config: %s", g_strerror(errno)); } goto error; } xp = xt_new(handlers, xd); while ((st = read(fd, buf, sizeof(buf))) > 0) { st = xt_feed(xp, buf, st); if (st != 1) { break; } } close(fd); if (st != 0) { goto error; } node = xp->root; if (node == NULL || node->next != NULL || strcmp(node->name, "user") != 0) { goto error; } if (action == XML_PASS_CHECK) { char *nick = xt_find_attr(node, "nick"); char *pass = xt_find_attr(node, "password"); char *backend = xt_find_attr(node, "auth_backend"); if (!nick || !(pass || backend)) { goto error; } if (backend) { g_free(xd->irc->auth_backend); xd->irc->auth_backend = g_strdup(backend); ret = STORAGE_CHECK_BACKEND; } else if ((st = md5_verify_password(xd->given_pass, pass)) != 0) { ret = STORAGE_INVALID_PASSWORD; } else { ret = STORAGE_OK; } goto error; } if (xt_handle(xp, NULL, 1) == XT_HANDLED) { ret = STORAGE_OK; } handle_settings(node, &xd->irc->b->set); error: xt_free(xp); g_free(fn); return ret; }