xmlnode *xmlnode_copy(xmlnode *src) { xmlnode *ret; xmlnode *child; xmlnode *sibling = NULL; if(!src) return NULL; ret = new_node(src->name, src->type); if(src->data) { if(src->data_sz) { ret->data = g_memdup(src->data, src->data_sz); ret->data_sz = src->data_sz; } else { ret->data = g_strdup(src->data); } } for(child = src->child; child; child = child->next) { if(sibling) { sibling->next = xmlnode_copy(child); sibling = sibling->next; } else { ret->child = xmlnode_copy(child); sibling = ret->child; } sibling->parent = ret; } return ret; }
static void twitter_send_xml_request_with_cursor_cb(TwitterRequestor * r, xmlnode * node, gpointer user_data) { TwitterRequestWithCursorData *request_data = user_data; gchar *next_cursor_str; next_cursor_str = xmlnode_get_child_data(node, "next_cursor"); if (next_cursor_str) { request_data->next_cursor = strtoll(next_cursor_str, NULL, 10); g_free(next_cursor_str); } else { request_data->next_cursor = 0; } purple_debug_info(purple_account_get_protocol_id(r->account), "%s next_cursor: %lld\n", G_STRFUNC, request_data->next_cursor); request_data->nodes = g_list_prepend(request_data->nodes, xmlnode_copy(node)); if (request_data->next_cursor) { int len = request_data->params->len; twitter_request_params_add(request_data->params, twitter_request_param_new_ll("cursor", request_data->next_cursor)); twitter_send_xml_request(r, FALSE, request_data->url, request_data->params, twitter_send_xml_request_with_cursor_cb, twitter_send_xml_request_with_cursor_error_cb, request_data); twitter_request_params_set_size(request_data->params, len); } else { request_data->success_callback(r, request_data->nodes, request_data->user_data); twitter_request_with_cursor_data_free(request_data); } }
static gboolean google_session_handle_initiate(JabberStream *js, GoogleSession *session, xmlnode *sess, const char *iq_id) { const gchar *xmlns; GoogleAVSessionData *session_data = (GoogleAVSessionData *) session->session_data; if (session->state != UNINIT) { purple_debug_error("jabber", "Received initiate for active session.\n"); return FALSE; } session->description = xmlnode_copy(xmlnode_get_child(sess, "description")); xmlns = xmlnode_get_namespace(session->description); if (purple_strequal(xmlns, NS_GOOGLE_SESSION_PHONE)) session_data->video = FALSE; else if (purple_strequal(xmlns, NS_GOOGLE_SESSION_VIDEO)) session_data->video = TRUE; else { purple_debug_error("jabber", "Received initiate with " "invalid namespace %s.\n", xmlns); return FALSE; } session_data->media = purple_media_manager_create_media( purple_media_manager_get(), purple_connection_get_account(js->gc), "fsrtpconference", session->remote_jid, FALSE); purple_media_set_prpl_data(session_data->media, session); g_signal_connect_swapped(G_OBJECT(session_data->media), "candidates-prepared", G_CALLBACK(google_session_ready), session); g_signal_connect_swapped(G_OBJECT(session_data->media), "codecs-changed", G_CALLBACK(google_session_ready), session); g_signal_connect(G_OBJECT(session_data->media), "state-changed", G_CALLBACK(google_session_state_changed_cb), session); g_signal_connect(G_OBJECT(session_data->media), "stream-info", G_CALLBACK(google_session_stream_info_cb), session); session->iq_id = g_strdup(iq_id); if (js->google_relay_host && js->google_relay_token) { jabber_google_do_relay_request(js, session, jabber_google_relay_response_session_handle_initiate_cb); } else { jabber_google_relay_response_session_handle_initiate_cb(session, NULL, 0, 0, 0, NULL, NULL); } return TRUE; }
static gboolean twitter_send_request_multipage_all_success_cb(PurpleAccount *acct, xmlnode *node, gboolean last_page, gpointer user_data) { TwitterMultiPageAllRequestData *request_data_all = user_data; request_data_all->nodes = g_list_append(request_data_all->nodes, xmlnode_copy(node)); //TODO: update if (last_page) { request_data_all->success_callback(acct, request_data_all->nodes, request_data_all->user_data); twitter_multipage_all_request_data_free(request_data_all); } return TRUE; }
xmlnode * xmlnode_copy(const xmlnode *src) { xmlnode *ret; xmlnode *child; xmlnode *sibling = NULL; g_return_val_if_fail(src != NULL, NULL); ret = new_node(src->name, src->type); ret->xmlns = g_strdup(src->xmlns); if (src->data) { if (src->data_sz) { ret->data = g_memdup(src->data, src->data_sz); ret->data_sz = src->data_sz; } else { ret->data = g_strdup(src->data); } } ret->prefix = g_strdup(src->prefix); if (src->namespace_map) { ret->namespace_map = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); g_hash_table_foreach(src->namespace_map, xmlnode_copy_foreach_ns, ret->namespace_map); } for (child = src->child; child; child = child->next) { if (sibling) { sibling->next = xmlnode_copy(child); sibling = sibling->next; } else { ret->child = xmlnode_copy(child); sibling = ret->child; } sibling->parent = ret; } ret->lastchild = sibling; return ret; }
/** * Create and insert an identical twin * * Creates a copy of the specified node and inserts it right after * this original node. * * @param node The node to clone * @return A pointer to the new, cloned twin if successful * or NULL otherwise. */ static xmlnode * xmlnode_insert_twin_copy(xmlnode *node) { xmlnode *copy; g_return_val_if_fail(node != NULL, NULL); copy = xmlnode_copy(node); g_return_val_if_fail(copy != NULL, NULL); copy->next = node->next; node->next = copy; return copy; }
void xep_bytestreams_parse(PurpleConnection *pc, xmlnode *packet, PurpleBuddy *pb) { const char *type, *from, *iq_id, *sid; xmlnode *query, *streamhost; BonjourData *bd; PurpleXfer *xfer; g_return_if_fail(pc != NULL); g_return_if_fail(packet != NULL); g_return_if_fail(pb != NULL); bd = (BonjourData*) pc->proto_data; if(bd == NULL) return; purple_debug_info("bonjour", "xep-bytestreams-parse.\n"); type = xmlnode_get_attrib(packet, "type"); from = purple_buddy_get_name(pb); query = xmlnode_get_child(packet,"query"); if(!type) return; query = xmlnode_copy(query); if (!query) return; if(!purple_strequal(type, "set")) { purple_debug_info("bonjour", "bytestream offer Message type - Unknown-%s.\n", type); return; } purple_debug_info("bonjour", "bytestream offer Message type - SET.\n"); iq_id = xmlnode_get_attrib(packet, "id"); sid = xmlnode_get_attrib(query, "sid"); xfer = bonjour_si_xfer_find(bd, sid, from); streamhost = xmlnode_get_child(query, "streamhost"); if(xfer && streamhost && __xep_bytestreams_parse(pb, xfer, streamhost, iq_id)) return; /* success */ purple_debug_error("bonjour", "Didn't find an acceptable streamhost.\n"); if (iq_id && xfer != NULL) xep_ft_si_reject(bd, iq_id, xfer->who, "404", "cancel"); }
static gboolean msn_oim_request_helper(MsnOimRequestData *data) { MsnSession *session = data->oim->session; if (data->send) { /* The Sending of OIM's uses a different token for some reason. */ xmlnode *ticket; ticket = xmlnode_get_child(data->body, "Header/Ticket"); xmlnode_set_attrib(ticket, "passport", msn_nexus_get_token_str(session->nexus, MSN_AUTH_LIVE_SECURE)); } else { xmlnode *passport; xmlnode *xml_t; xmlnode *xml_p; GHashTable *token; const char *msn_t; const char *msn_p; token = msn_nexus_get_token(session->nexus, MSN_AUTH_MESSENGER_WEB); g_return_val_if_fail(token != NULL, FALSE); msn_t = g_hash_table_lookup(token, "t"); msn_p = g_hash_table_lookup(token, "p"); g_return_val_if_fail(msn_t != NULL, FALSE); g_return_val_if_fail(msn_p != NULL, FALSE); passport = xmlnode_get_child(data->body, "Header/PassportCookie"); xml_t = xmlnode_get_child(passport, "t"); xml_p = xmlnode_get_child(passport, "p"); /* frees old token text, or the 'EMPTY' text if first time */ xmlnode_free(xml_t->child); xmlnode_free(xml_p->child); xmlnode_insert_data(xml_t, msn_t, -1); xmlnode_insert_data(xml_p, msn_p, -1); } msn_soap_message_send(session, msn_soap_message_new(data->action, xmlnode_copy(data->body)), data->host, data->url, FALSE, msn_oim_request_cb, data); return FALSE; }
static gboolean twitter_send_xml_request_multipage_all_success_cb(TwitterRequestor * r, xmlnode * node, gboolean last_page, TwitterMultiPageRequestData * request_multi, gpointer user_data) { TwitterMultiPageAllRequestData *request_data_all = user_data; purple_debug_info(purple_account_get_protocol_id(r->account), "%s\n", G_STRFUNC); request_data_all->nodes = g_list_prepend(request_data_all->nodes, xmlnode_copy(node)); //TODO: update request_data_all->current_count += xmlnode_child_count(node); purple_debug_info(purple_account_get_protocol_id(r->account), "%s last_page: %d current_count: %d max_count: %d count: %d\n", G_STRFUNC, last_page ? 1 : 0, request_data_all->current_count, request_data_all->max_count, request_multi->expected_count); if (last_page || (request_data_all->max_count > 0 && request_data_all->current_count >= request_data_all->max_count)) { request_data_all->success_callback(r, request_data_all->nodes, request_data_all->user_data); twitter_multipage_all_request_data_free(request_data_all); return FALSE; } else if (request_data_all->max_count > 0 && (request_data_all->current_count + request_multi->expected_count > request_data_all->max_count)) { request_multi->expected_count = request_data_all->max_count - request_data_all->current_count; } return TRUE; }
void jabber_iq_parse(JabberStream *js, xmlnode *packet) { JabberCallbackData *jcd; xmlnode *query, *error, *x; const char *xmlns; const char *type, *id, *from; JabberIqHandler *jih; query = xmlnode_get_child(packet, "query"); type = xmlnode_get_attrib(packet, "type"); from = xmlnode_get_attrib(packet, "from"); id = xmlnode_get_attrib(packet, "id"); if(type == NULL || !(!strcmp(type, "get") || !strcmp(type, "set") || !strcmp(type, "result") || !strcmp(type, "error"))) { purple_debug_error("jabber", "IQ with invalid type ('%s') - ignoring.\n", type ? type : "(null)"); return; } /* All IQs must have an ID, so send an error for a set/get that doesn't */ if(!id || !*id) { if(!strcmp(type, "set") || !strcmp(type, "get")) { JabberIq *iq = jabber_iq_new(js, JABBER_IQ_ERROR); xmlnode_free(iq->node); iq->node = xmlnode_copy(packet); xmlnode_set_attrib(iq->node, "to", from); xmlnode_remove_attrib(iq->node, "from"); xmlnode_set_attrib(iq->node, "type", "error"); /* This id is clearly not useful, but we must put something there for a valid stanza */ iq->id = jabber_get_next_id(js); xmlnode_set_attrib(iq->node, "id", iq->id); error = xmlnode_new_child(iq->node, "error"); xmlnode_set_attrib(error, "type", "modify"); x = xmlnode_new_child(error, "bad-request"); xmlnode_set_namespace(x, "urn:ietf:params:xml:ns:xmpp-stanzas"); jabber_iq_send(iq); } else purple_debug_error("jabber", "IQ of type '%s' missing id - ignoring.\n", type); return; } /* First, lets see if a special callback got registered */ if(!strcmp(type, "result") || !strcmp(type, "error")) { if(id && *id && (jcd = g_hash_table_lookup(js->iq_callbacks, id))) { jcd->callback(js, packet, jcd->data); jabber_iq_remove_callback_by_id(js, id); return; } } /* Apparently not, so lets see if we have a pre-defined handler */ if(query && (xmlns = xmlnode_get_namespace(query))) { if((jih = g_hash_table_lookup(iq_handlers, xmlns))) { jih(js, packet); return; } } if(xmlnode_get_child_with_namespace(packet, "si", "http://jabber.org/protocol/si")) { jabber_si_parse(js, packet); return; } if(xmlnode_get_child_with_namespace(packet, "new-mail", "google:mail:notify")) { jabber_gmail_poke(js, packet); return; } purple_debug_info("jabber", "jabber_iq_parse\n"); if(xmlnode_get_child_with_namespace(packet, "ping", "urn:xmpp:ping")) { jabber_ping_parse(js, packet); return; } if (xmlnode_get_child_with_namespace(packet, "data", XEP_0231_NAMESPACE)) { jabber_data_parse(js, packet); return; } /* If we get here, send the default error reply mandated by XMPP-CORE */ if(!strcmp(type, "set") || !strcmp(type, "get")) { JabberIq *iq = jabber_iq_new(js, JABBER_IQ_ERROR); xmlnode_free(iq->node); iq->node = xmlnode_copy(packet); xmlnode_set_attrib(iq->node, "to", from); xmlnode_remove_attrib(iq->node, "from"); xmlnode_set_attrib(iq->node, "type", "error"); error = xmlnode_new_child(iq->node, "error"); xmlnode_set_attrib(error, "type", "cancel"); xmlnode_set_attrib(error, "code", "501"); x = xmlnode_new_child(error, "feature-not-implemented"); xmlnode_set_namespace(x, "urn:ietf:params:xml:ns:xmpp-stanzas"); jabber_iq_send(iq); } }