/** * Parse the ssi authentication response string. then we can * get the following information: sipuri/mobileno/sid/ssic. */ static gint parse_ssi_response(fetion_account *ac, const gchar *response) { gchar *prop; xmlnode *node; xmlnode *root = xmlnode_root(response, strlen(response)); if (!root) { goto ssi_term; } prop = xmlnode_prop(root, "status-code"); if (g_strcmp0(prop, "200") != 0) { g_free(prop); goto ssi_term; } g_free(prop); node = xmlnode_find(root, "user"); prop = xmlnode_prop(node, "uri"); fetion_account_set_sipuri(ac, prop); g_free(prop); if (!ac->sid || *(ac->sid) == '\0') { g_free(ac->sid); ac->sid = get_sid_from_sipuri(ac->sipuri); fetion_sip_set_from(ac->sip, ac->sid); } prop = xmlnode_prop(node, "mobile-no"); fetion_account_set_mobileno(ac, prop); g_free(prop); prop = xmlnode_prop(node, "user-id"); fetion_account_set_userid(ac, prop); g_free(prop); #if 0 node = xmlnode_find(root, "credential"); prop = xmlnode_prop(node, "c"); fetion_account_set_ssic(ac, prop); g_free(prop); #endif return HYBRID_OK; ssi_term: hybrid_account_error_reason(ac->account, _("ssi authencation")); xmlnode_free(root); return HYBRID_ERROR; }
/** * Process the synchronization message, when the contact list or the personal info * changed, the server will push this message to tell the client to update its * local cache file, well, we will not update the local cache file, we keep the * old version numbers, and reload it after the next logining. */ static void process_sync_info(fetion_account *ac, const gchar *sipmsg) { GSList *list; gchar *sid; fetion_buddy *buddy; HybridBuddy *hb; hybrid_debug_info("fetion", "sync info,recv:\n%s", sipmsg); if (!(list = sip_parse_sync(ac, sipmsg))) { return; } while (list) { buddy = (fetion_buddy*)list->data; list = g_slist_remove(list, buddy); if (buddy->status == 0) { continue; } if (!(hb = hybrid_blist_find_buddy(ac->account, buddy->userid))) { continue; } if (buddy->status == 1) { hybrid_blist_set_buddy_status(hb, TRUE); } else { hybrid_blist_set_buddy_status(hb, FALSE); } sid = get_sid_from_sipuri(buddy->sipuri); hybrid_message_box_show(HYBRID_MESSAGE_INFO, _("Buddy <b>%s</b> has %s your add-buddy request."), buddy->localname && *(buddy->localname) != '\0' ? buddy->localname : sid, buddy->status == 1 ? _("accepted") : _("declined")); } }
gint fetion_process_invite(fetion_account *account, const gchar *sipmsg) { gchar *from; gchar *auth; gchar *ip; gchar *credential; gchar *sid; gint port; gchar *sip_text; fetion_account *new_account; fetion_buddy *buddy; invite_conn_data *data; g_return_val_if_fail(account != NULL, HYBRID_ERROR); g_return_val_if_fail(sipmsg != NULL, HYBRID_ERROR); from = sip_header_get_attr(sipmsg, "F"); auth = sip_header_get_attr(sipmsg, "A"); sip_header_get_auth(auth, &ip, &port, &credential); g_free(auth); sip_text = g_strdup_printf("SIP-C/4.0 200 OK\r\n" "F: %s\r\n" "I: 61\r\n" "Q: 200002 I\r\n\r\n", from); hybrid_debug_info("fetion", "invite, send back:\n%s", sip_text); if (send(account->sk, sip_text, strlen(sip_text), 0) == -1) { hybrid_debug_error("fetion", "process an invitation error."); g_free(from); g_free(ip); g_free(credential); g_free(sip_text); return HYBRID_ERROR; } g_free(sip_text); sid = get_sid_from_sipuri(from); if (!(buddy = fetion_buddy_find_by_sid(account, sid))) { hybrid_debug_error("fetion", "can't find buddy %s", from); g_free(from); g_free(ip); g_free(credential); g_free(sid); return HYBRID_ERROR; } g_free(sid); new_account = fetion_account_clone(account); fetion_account_set_who(new_account, buddy->userid); data = g_new0(invite_conn_data, 1); data->account = new_account; data->credential = credential; hybrid_proxy_connect(ip, port, process_invite_conn_cb, data); g_free(from); g_free(ip); return HYBRID_OK; }
gint fetion_process_message(fetion_account *account, const gchar *sipmsg) { gchar *from; gchar *sid; gchar *callid; gchar *sequence; gchar *sendtime; gchar *text; gchar *sip_text; fetion_buddy *buddy; g_return_val_if_fail(account != NULL, HYBRID_ERROR); g_return_val_if_fail(sipmsg != NULL, HYBRID_ERROR); if (!(text = strstr(sipmsg, "\r\n\r\n"))) { hybrid_debug_error("fetion", "invalid message received\n"); return HYBRID_ERROR; } text += 4; from = sip_header_get_attr(sipmsg, "F"); callid = sip_header_get_attr(sipmsg, "I"); sendtime = sip_header_get_attr(sipmsg, "D"); sequence = sip_header_get_attr(sipmsg, "Q"); sip_text = g_strdup_printf( "SIP-C/4.0 200 OK\r\n" "I: %s\r\n" "Q: %s\r\n" "F: %s\r\n\r\n", callid, sequence, from); g_free(callid); g_free(sendtime); g_free(sequence); hybrid_debug_info("fetion", "message response, send:\n%s", sip_text); if (send(account->sk, sip_text, strlen(sip_text), 0) == -1) { g_free(sip_text); g_free(from); return HYBRID_ERROR; } g_free(sip_text); sid = get_sid_from_sipuri(from); g_free(from); if (!(buddy = fetion_buddy_find_by_sid(account, sid))) { hybrid_debug_error("fetion", "invalid message received\n"); g_free(sid); return HYBRID_ERROR; } hybrid_conv_got_message(account->account, buddy->userid, text, time(NULL)); g_free(sid); return HYBRID_OK; }
/** * Get the contact list from the xmlnode with name 'contact-list', * note that this node can either be a child node of the sipc * response xml message , or a child node of the local xml file. */ static void get_contact_list(fetion_account *ac, xmlnode *contact_node) { gchar *temp; gchar *temp1; xmlnode *node; fetion_group *group; fetion_buddy *buddy; gboolean has_ungroup = FALSE; g_return_if_fail(ac != NULL); g_return_if_fail(contact_node != NULL); /* group list */ node = xmlnode_find(contact_node, "buddy-lists"); node = xmlnode_child(node); while (node) { temp = xmlnode_prop(node, "name"); temp1 = xmlnode_prop(node, "id"); group = fetion_group_create(atoi(temp1), temp); ac->groups = g_slist_append(ac->groups, group); g_free(temp); g_free(temp1); node = node->next; } /* contact list */ node = xmlnode_find(contact_node, "buddies"); node = xmlnode_child(node); while (node) { buddy = fetion_buddy_create(); buddy->userid = xmlnode_prop(node, "i"); buddy->sipuri = xmlnode_prop(node, "u"); buddy->localname = xmlnode_prop(node, "n"); buddy->groups = xmlnode_prop(node, "l"); buddy->sid = get_sid_from_sipuri(buddy->sipuri); if (xmlnode_has_prop(node, "r")) { temp = xmlnode_prop(node, "r"); buddy->status = atoi(temp); g_free(temp); } else { buddy->status = 0; } ac->buddies = g_slist_append(ac->buddies, buddy); /* ungrouped */ if (*(buddy->groups) == '\0' || buddy->groups[0] == '0') { g_free(buddy->groups); buddy->groups = g_strdup("0"); if (!has_ungroup) { /**< add an "ungroup" group */ group = fetion_group_create(0, _("Ungrouped")); ac->groups = g_slist_append(ac->groups, group); has_ungroup = TRUE; } } node = node->next; } }
static gint handle_request_cb(fetion_account *account, const gchar *sipmsg, fetion_transaction *trans) { gchar *pos; gchar *value; fetion_buddy *buddy; xmlnode *root; xmlnode *node; HybridGroup *group; HybridBuddy *bd; gchar *name; if (!(pos = strstr(sipmsg, "\r\n\r\n"))) { return HYBRID_ERROR; } pos += 4; if (!(root = xmlnode_root(pos, strlen(pos)))) { return HYBRID_ERROR; } if (!(node = xmlnode_find(root, "buddy"))) { return HYBRID_ERROR; } if (!xmlnode_has_prop(node, "uri") || !xmlnode_has_prop(node, "user-id")) { return HYBRID_ERROR; } buddy = fetion_buddy_create(); buddy->sipuri = xmlnode_prop(node, "uri"); buddy->userid = xmlnode_prop(node, "user-id"); buddy->sid = get_sid_from_sipuri(buddy->sipuri); account->buddies = g_slist_append(account->buddies, buddy); if (xmlnode_has_prop(node, "local-name")) { buddy->localname = xmlnode_prop(node, "localname"); } if (xmlnode_has_prop(node, "buddy-lists")) { buddy->groups = xmlnode_prop(node, "buddy-lists"); } else { buddy->groups = "0"; } if (xmlnode_has_prop(node, "relation-status")) { value = xmlnode_prop(node, "relation-status"); buddy->status = atoi(value); g_free(value); } else { buddy->status = 0; } if (!(group = hybrid_blist_find_group(account->account, buddy->groups))) { account->buddies = g_slist_remove(account->buddies, buddy); fetion_buddy_destroy(buddy); return HYBRID_ERROR; } if (buddy->localname && *(buddy->localname) == '\0') { name = get_sid_from_sipuri(buddy->sipuri); } else { name = g_strdup(buddy->localname); } bd = hybrid_blist_add_buddy(account->account, group, buddy->userid, name); hybrid_blist_set_buddy_status(bd, buddy->status == 1 ? TRUE: FALSE); g_free(name); return HYBRID_OK; }
static gint buddy_add_cb(fetion_account *account, const gchar *sipmsg, fetion_transaction *trans) { gint code; gchar *pos; gchar *value; gchar *name; fetion_buddy *buddy; HybridGroup *group; HybridBuddy *bd; xmlnode *root; xmlnode *node; hybrid_debug_info("fetion", "add buddy, recv:\n%s", sipmsg); if ((code = fetion_sip_get_code(sipmsg)) != 200) { hybrid_message_box_show(HYBRID_MESSAGE_WARNING, "Add buddy error. Server response with %d", code); return HYBRID_ERROR; } if (!(pos = strstr(sipmsg, "\r\n\r\n"))) { goto add_buddy_unknown_err; } pos += 4; if (!(root = xmlnode_root(pos, strlen(pos)))) { goto add_buddy_unknown_err; } if (!(node = xmlnode_find(root, "buddy"))) { xmlnode_free(root); goto add_buddy_unknown_err; } if (xmlnode_has_prop(node, "status-code")) { value = xmlnode_prop(node, "status-code"); code = atoi(value); g_free(value); if (code == 200) { goto add_buddy_ok; } xmlnode_free(node); if (code == 521) { hybrid_message_box_show(HYBRID_MESSAGE_WARNING, "The buddy has already been in your buddy list,\n" "Please don't add it duplicately."); return HYBRID_ERROR; } if (code == 404) { hybrid_message_box_show(HYBRID_MESSAGE_WARNING, "The buddy you try to add doesn't exist."); return HYBRID_ERROR; } if (code == 486) { hybrid_message_box_show(HYBRID_MESSAGE_WARNING, "You have reached the daily limit of adding buddies,\n" "please try another day."); return HYBRID_ERROR; } goto add_buddy_unknown_err; } add_buddy_ok: if (!xmlnode_has_prop(node, "user-id") || !xmlnode_has_prop(node, "local-name") || !xmlnode_has_prop(node, "uri") || !xmlnode_has_prop(node, "buddy-lists")) { xmlnode_free(root); goto add_buddy_unknown_err; } buddy = fetion_buddy_create(); buddy->userid = xmlnode_prop(node, "user-id"); buddy->localname = xmlnode_prop(node, "local-name"); buddy->sipuri = xmlnode_prop(node, "uri"); buddy->groups = xmlnode_prop(node, "buddy-lists"); xmlnode_free(root); account->buddies = g_slist_append(account->buddies, buddy); if (!(group = hybrid_blist_find_group(account->account, buddy->groups))) { fetion_buddy_destroy(buddy); account->buddies = g_slist_remove(account->buddies, buddy); goto add_buddy_unknown_err; } if (buddy->localname && *(buddy->localname) == '\0') { name = get_sid_from_sipuri(buddy->sipuri); } else { name = g_strdup(buddy->localname); } bd = hybrid_blist_add_buddy(account->account, group, buddy->userid, name); hybrid_blist_set_buddy_status(bd, FALSE); g_free(name); return HYBRID_OK; add_buddy_unknown_err: hybrid_message_box_show(HYBRID_MESSAGE_WARNING, "Add buddy error. Unknown reason."); return HYBRID_ERROR; }