/* * Get the personal information from the xmlnode with name 'personal', * 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_personal(fetion_account *ac, xmlnode *node) { gchar *pos; gchar *temp; gchar *stop; g_return_if_fail(ac != NULL); g_return_if_fail(node != NULL); ac->nickname = xmlnode_prop(node, "nickname"); ac->mood_phrase = xmlnode_prop(node, "impresa"); ac->portrait_crc = xmlnode_prop(node, "portrait-crc"); temp = xmlnode_prop(node, "carrier-region"); /* region */ if (temp) { for (stop = temp, pos = temp; *stop && *stop != '.'; stop ++); ac->country = g_strndup(pos, stop - pos); for (pos = stop + 1, stop ++; *stop && *stop != '.'; stop ++); ac->province = g_strndup(pos, stop - pos); for (pos = stop + 1, stop ++; *stop && *stop != '.'; stop ++); ac->city = g_strndup(pos, stop - pos); } g_free(temp); }
/** * Process the iq messages. */ static void xmpp_stream_process_iq(XmppStream *stream, xmlnode *node) { gchar *id; gint id_int; GSList *pos; IqTransaction *trans; gchar *value; g_return_if_fail(stream != NULL); g_return_if_fail(node != NULL); if (!xmlnode_has_prop(node, "type") || !xmlnode_has_prop(node, "id")) { hybrid_debug_error("xmpp", "invalid iq message."); return; } value = xmlnode_prop(node, "type"); /* response to a get or set request. */ if (g_strcmp0(value, "result") == 0 || g_strcmp0(value, "error") == 0) { id = xmlnode_prop(node, "id"); id_int = atoi(id); g_free(id); for (pos = stream->pending_trans; pos; pos = pos->next) { trans = (IqTransaction*)pos->data; if (trans->iq_id == id_int) { if (trans->callback) { trans->callback(stream, node, trans->user_data); } iq_transaction_remove(stream, trans); } } /* * An entity that receives an IQ request of type "get" or "set" MUST reply with an IQ response of type "result" or "error". */ } else if (g_strcmp0(value, "get") == 0) { /* process later. */ } else if (g_strcmp0(value, "set") == 0) { xmpp_stream_process_iq_set(stream, node); } g_free(value); }
/** * 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 roster set request. */ static void xmpp_stream_process_set_roster(XmppStream *stream, xmlnode *query) { xmlnode *node; gchar *value; XmppBuddy *buddy; g_return_if_fail(stream != NULL); g_return_if_fail(query != NULL); if (!(node = xmlnode_child(query))) { return; } while (node) { if (g_strcmp0(node->name, "item") != 0) { node = node->next; continue; } if (!xmlnode_has_prop(node, "jid")) { node = node->next; continue; } value = xmlnode_prop(node, "jid"); if (!(buddy = xmpp_buddy_find(stream->account, value))) { g_free(value); node = node->next; continue; } g_free(value); if (xmlnode_has_prop(node, "subscription")) { value = xmlnode_prop(node, "subscription"); xmpp_buddy_set_subscription(buddy, value); g_free(value); } if (xmlnode_has_prop(node, "name")) { value = xmlnode_prop(node, "name"); xmpp_buddy_set_name(buddy, value); g_free(value); } node = node->next; } }
gchar* hybrid_pref_get_string(const gchar *name) { xmlnode *node; gchar *type; gchar *value; g_return_val_if_fail(hybrid_pref != NULL, FALSE); g_return_val_if_fail(hybrid_pref->root != NULL, FALSE); if (!(node = xmlnode_find(hybrid_pref->root, name))) { return NULL; } if (!xmlnode_has_prop(node, "type")) { hybrid_debug_info("pref", "invalid pref node."); return NULL; } type = xmlnode_prop(node, "type"); if (g_strcmp0(type, "string") != 0) { hybrid_debug_error("pref", "string pref node with a type which is not string."); return NULL; } value = xmlnode_content(node); return value; }
/** * Process the iq set request. */ static void xmpp_stream_process_iq_set(XmppStream *stream, xmlnode *root) { gchar *id; gchar *value; xmlnode *node; gint count = 0; g_return_if_fail(stream != NULL); g_return_if_fail(root != NULL); node = xmlnode_child(root); for (; node; node = node->next, count ++); /* * An IQ stanza of type "get" or "set" MUST contain exactly one * child element, which specifies the semantics of the particular * request. */ if (count != 1) { /* TODO send error stanza. */ return; } node = xmlnode_child(root); if (g_strcmp0(node->name, "query") == 0) { value = xmlnode_get_namespace(node); if (g_strcmp0(value, NS_IQ_ROSTER) == 0) { xmpp_stream_process_set_roster(stream, node); } g_free(value); } /* send a result response. */ IqRequest *iq; iq = iq_request_create(stream, IQ_TYPE_RESULT); xmlnode_new_prop(iq->node, "from", stream->jid); if (xmlnode_has_prop(root, "id")) { id = xmlnode_prop(root, "id"); xmlnode_set_prop(iq->node, "id", id); g_free(id); } iq_request_send(iq); iq_request_destroy(iq); }
static gint parse_ssi_fail_resp(fetion_account *ac, const gchar *response) { xmlnode *root; xmlnode *node; Verification *ver; gchar *pos; ver = fetion_verification_create(); if (!(pos = strstr(response, "\r\n\r\n"))) { return HYBRID_ERROR; } pos += 4; root = xmlnode_root(pos, strlen(pos)); if (!(node = xmlnode_find(root, "results"))) { return HYBRID_ERROR; } if (xmlnode_has_prop(node, "desc")) { ver->desc = xmlnode_prop(node, "desc"); } if (!(node = xmlnode_find(root, "verification"))) { return HYBRID_ERROR; } if (xmlnode_has_prop(node, "algorithm")) { ver->algorithm = xmlnode_prop(node, "algorithm"); } ac->verification = ver; return HYBRID_OK; }
GSList* hybrid_logs_read(HybridAccount *account, const gchar *id, const gchar *logname) { gchar *log_path = NULL; gchar *log_name = NULL; gchar *tmp; GSList *list = NULL; xmlnode *root = NULL, *node, *child; HybridLogEntry *entry; log_path = hybrid_logs_get_path(account, id); log_name = g_strdup_printf("%s/%s", log_path, logname); root = xmlnode_root_from_file(log_name); if (!root) { hybrid_debug_error("log", "log %s read error.\n", log_name); goto out; } node = xmlnode_child(root); while (node) { if (!xmlnode_has_prop(node, "type")) goto next; entry = g_new0(HybridLogEntry, 1); tmp = xmlnode_prop(node, "type"); if (g_strcmp0(tmp, "o")) { entry->is_send = 1; } else { entry->is_send = 0; } g_free(tmp); child = xmlnode_find(node, "t"); entry->time = xmlnode_content(child); child = xmlnode_find(node, "n"); entry->name = xmlnode_content(child); child = xmlnode_find(node, "c"); entry->content = xmlnode_content(child); list = g_slist_append(list, entry); next: node = xmlnode_next(node); } out: free(log_path); free(log_name); xmlnode_free(root); return list; }
/** * Callback function for the resource bind request to process the response. */ static gboolean resource_bind_cb(XmppStream *stream, xmlnode *root, gpointer user_data) { gchar *type; gchar *jid; xmlnode *node; type = xmlnode_prop(root, "type"); if (g_strcmp0(type, "result")) { hybrid_account_error_reason(stream->account->account, _("resource bind error.")); return FALSE; } if (!(node = xmlnode_find(root, "jid"))) { hybrid_account_error_reason(stream->account->account, _("resource bind error: no jabber id returned.")); return FALSE; } jid = xmlnode_content(node); xmpp_stream_set_jid(stream, jid); g_free(jid); /* request to start a session. */ IqRequest *iq; iq = iq_request_create(stream, IQ_TYPE_SET); node = xmlnode_new_child(iq->node, "session"); xmlnode_new_namespace(node, NULL, NS_XMPP_SESSION); iq_request_set_callback(iq, start_session_cb, NULL); if (iq_request_send(iq) != HYBRID_OK) { hybrid_account_error_reason(stream->account->account, _("start session error.")); iq_request_destroy(iq); return TRUE; } iq_request_destroy(iq); return TRUE; }
gint sip_parse_appbuddy(const gchar *sipmsg, gchar **userid, gchar **sipuri, gchar **desc) { gchar *pos; xmlnode *root; xmlnode *node; 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, "application"))) { return HYBRID_ERROR; } if (xmlnode_has_prop(node, "uri") && sipuri != NULL) { *sipuri = xmlnode_prop(node, "uri"); } if (xmlnode_has_prop(node, "user-id") && userid != NULL) { *userid = xmlnode_prop(node, "user-id"); } if (xmlnode_has_prop(node, "desc") && desc != NULL) { *desc = xmlnode_prop(node, "desc"); } return HYBRID_OK; }
gchar* get_province_name(const gchar *province) { xmlnode *root; xmlnode *node; gchar *name; gchar *value; g_return_val_if_fail(province != NULL, NULL); if (!(root = xmlnode_root_from_file(FETION_RES_DIR"province.xml"))) { return NULL; } if (!(node = xmlnode_child(root)) || g_strcmp0(node->name, "Province")) { hybrid_debug_error("fetion", "get full province name"); return NULL; } for (; node; node = xmlnode_next(node)) { if (!xmlnode_has_prop(node, "id")) { continue; } value = xmlnode_prop(node, "id"); if (g_strcmp0(value, province) == 0) { name = xmlnode_content(node); /* found, do cleanup. */ g_free(value); xmlnode_free(root); return name; } g_free(value); } xmlnode_free(root); return NULL; }
gboolean hybrid_pref_get_boolean(const gchar *name) { xmlnode *node; gchar *type; gchar *value; g_return_val_if_fail(hybrid_pref != NULL, FALSE); g_return_val_if_fail(hybrid_pref->root != NULL, FALSE); if (!(node = xmlnode_find(hybrid_pref->root, name))) { return FALSE; } if (!xmlnode_has_prop(node, "type")) { hybrid_debug_info("pref", "invalid pref node."); return FALSE; } type = xmlnode_prop(node, "type"); if (g_strcmp0(type, "bool") != 0) { hybrid_debug_error("pref", "bool pref node with a type which is not bool."); return FALSE; } value = xmlnode_content(node); if (g_strcmp0(value, "0") == 0) { g_free(value); return FALSE; } else { g_free(value); return TRUE; } }
/** * Callback function to process the buddy's get-info response. */ static gboolean buddy_get_info_cb(XmppStream *stream, xmlnode *root, XmppBuddy *buddy) { xmlnode *node; gchar *type; gchar *photo_bin; guchar *photo; gint photo_len; if (xmlnode_has_prop(root, "type")) { type = xmlnode_prop(root, "type"); if (g_strcmp0(type, "result") != 0) { hybrid_debug_error("xmpp", "get buddy info error."); g_free(type); return FALSE; } g_free(type); } if ((node = xmlnode_find(root, "PHOTO"))) { if ((node = xmlnode_find(root, "BINVAL"))) { photo_bin = xmlnode_content(node); /* decode the base64-encoded photo string. */ photo = hybrid_base64_decode(photo_bin, &photo_len); /* set icon for the buddy. */ hybrid_blist_set_buddy_icon(buddy->buddy, photo, photo_len, buddy->photo); g_free(photo_bin); g_free(photo); } } return TRUE; }
gint hybrid_pref_get_int(const gchar *name) { xmlnode *node; gchar *type; gchar *value; gint value_int; g_return_val_if_fail(hybrid_pref != NULL, FALSE); g_return_val_if_fail(hybrid_pref->root != NULL, FALSE); if (!(node = xmlnode_find(hybrid_pref->root, name))) { return -1; } if (!xmlnode_has_prop(node, "type")) { hybrid_debug_info("pref", "invalid pref node."); return -1; } type = xmlnode_prop(node, "type"); if (g_strcmp0(type, "int") != 0) { hybrid_debug_error("pref", "integer pref node with a type which is not int."); return -1; } value = xmlnode_content(node); value_int = atoi(value); g_free(value); return value_int; }
static gboolean ping_cb(XmppStream *stream, xmlnode *node, gpointer user_data) { gchar *value; if (xmlnode_has_prop(node, "type")) { value = xmlnode_prop(node, "type"); if (g_strcmp0(value, "result") != 0) { hybrid_debug_error("xmpp", "ping xmpp server refused."); hybrid_account_error_reason(stream->account->account, _("Connection Closed.")); } } if (stream->keepalive_source) { g_source_remove(stream->keepalive_source); stream->keepalive_source = 0; } return FALSE; }
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 void xmpp_stream_process_message(XmppStream *stream, xmlnode *root) { gchar *value; gchar *bare_jid; xmlnode *node; HybridAccount *account; g_return_if_fail(stream != NULL); g_return_if_fail(root != NULL); account = stream->account->account; if (!xmlnode_has_prop(root, "type")) { hybrid_debug_error("xmpp", "invalid message received without a type property."); return; } value = xmlnode_prop(root, "type"); if (g_strcmp0(value, "chat") != 0) { hybrid_debug_error("xmpp", "unsupported message type."); g_free(value); return; } g_free(value); if (!xmlnode_has_prop(root, "from")) { hybrid_debug_error("xmpp", "invalid message without a from property."); return; } value = xmlnode_prop(root, "from"); bare_jid = get_bare_jid(value); g_free(value); if ((node = xmlnode_find(root, "composing"))) { hybrid_conv_got_inputing(account, bare_jid, FALSE); } if ((node = xmlnode_find(root, "active"))) { hybrid_conv_clear_inputing(account, bare_jid); } if ((node = xmlnode_find(root, "paused"))) { hybrid_conv_stop_inputing(account, bare_jid); } if ((node = xmlnode_find(root, "body"))) { value = xmlnode_content(node); hybrid_conv_got_message(account, bare_jid, value, time(NULL)); g_free(value); return; } }
static gboolean pic_read_cb(gint sk, gpointer user_data) { gint n, len; gchar sipmsg[BUF_LENGTH]; gchar *code, *pos; guchar *pic; gint piclen; xmlnode *root; xmlnode *node; fetion_account *ac = (fetion_account*)user_data; len = ac->buffer ? strlen(ac->buffer) : 0; if((n = recv(sk, sipmsg, strlen(sipmsg), 0)) == -1) { return -1; } sipmsg[n] = 0; if(n == 0) { g_source_remove(ac->source); ac->source = 0; close(sk); if(! ac->buffer) { return 0; } hybrid_debug_info("fetion", "read message resp:\n%s", ac->buffer); if (200 != hybrid_get_http_code(ac->buffer)) { goto read_pic_err; } if(!(pos = strstr(ac->buffer, "\r\n\r\n"))) { goto read_pic_err; } pos += 4; if (!(root = xmlnode_root(pos, strlen(pos)))) { goto read_pic_err; } if (!(node = xmlnode_find(root, "pic-certificate"))) { xmlnode_free(root); goto read_pic_err; } if (!xmlnode_has_prop(node, "id") || !xmlnode_has_prop(node, "pic")) { xmlnode_free(root); goto read_pic_err; } ac->verification->guid = xmlnode_prop(node, "id"); code = xmlnode_prop(node, "pic"); pic = hybrid_base64_decode(code, &piclen); hybrid_confirm_window_create(ac->account, pic, piclen, pic_code_ok_cb, pic_code_cancel_cb, ac); g_free(code); g_free(pic); xmlnode_free(root); g_free(ac->buffer); ac->buffer = (gchar*)0; return FALSE; } ac->buffer = (gchar*)realloc(ac->buffer, len + n + 1); memcpy(ac->buffer + len, sipmsg, n + 1); return TRUE; read_pic_err: hybrid_debug_error("fetion", "read pic code error."); g_free(ac->buffer); ac->buffer = (gchar *)0; hybrid_account_error_reason(ac->account, _("read pic code error.")); return FALSE; }
GSList* sip_parse_presence(fetion_account *ac, const gchar *sipmsg) { gchar *pos; gchar *temp; xmlnode *root; xmlnode *node; xmlnode *pnode; GSList *list = NULL; fetion_buddy *buddy; if (!(pos = strstr(sipmsg, "\r\n\r\n"))) { return list; } pos += 4; root = xmlnode_root(pos, strlen(pos)); node = xmlnode_find(root, "contacts"); node = xmlnode_child(node); while (node) { temp = xmlnode_prop(node, "id"); if (!(buddy = fetion_buddy_find_by_userid(ac, temp))) { /* Maybe yourself's presence, we just ignore it. */ g_free(temp); node = node->next; continue; } g_free(temp); list = g_slist_append(list, buddy); if ((pnode = xmlnode_find(node, "p"))) { if (xmlnode_has_prop(pnode, "m")) { temp = xmlnode_prop(pnode, "m"); g_free(buddy->mobileno); buddy->mobileno = g_strdup(temp); g_free(temp); } if (xmlnode_has_prop(pnode, "n")) { temp = xmlnode_prop(pnode, "n"); g_free(buddy->nickname); buddy->nickname = g_strdup(temp); g_free(temp); } if (xmlnode_has_prop(pnode, "i")) { temp = xmlnode_prop(pnode, "i"); g_free(buddy->mood_phrase); buddy->mood_phrase = g_strdup(temp); g_free(temp); } if (xmlnode_has_prop(pnode, "c")) { temp = xmlnode_prop(pnode, "c"); g_free(buddy->carrier); buddy->carrier = g_strdup(temp); g_free(temp); } if (xmlnode_has_prop(pnode, "p")) { temp = xmlnode_prop(pnode, "p"); g_free(buddy->portrait_crc); if (*temp == '\0') { g_free(temp); temp = g_strdup("0"); } buddy->portrait_crc = temp; } else { g_free(buddy->portrait_crc); buddy->portrait_crc = g_strdup("0"); } if (xmlnode_has_prop(pnode, "cs")) { temp = xmlnode_prop(pnode, "cs"); buddy->carrier_status = atoi(temp); g_free(temp); } } if ((pnode = xmlnode_find(node, "pr"))) { if (xmlnode_has_prop(pnode, "b")) { temp = xmlnode_prop(pnode, "b"); buddy->state = atoi(temp); g_free(temp); } } node = node->next; } xmlnode_free(root); return list; }
fetion_buddy* fetion_buddy_parse_info(fetion_account *ac, const gchar *userid, const gchar *sipmsg) { xmlnode *root; xmlnode *node; gchar *pos; gchar *temp; gchar *value; fetion_buddy *buddy; gint code; code = fetion_sip_get_code(sipmsg); if (code != 200) { hybrid_debug_error("fetion", "get information with code:%d", code); return NULL; } if (!(pos = strstr(sipmsg, "\r\n\r\n"))) { goto get_info_error; } pos += 4; if (!(root = xmlnode_root(pos, strlen(pos)))) { goto get_info_error; } if (!(node = xmlnode_find(root, "contact"))) { xmlnode_free(root); goto get_info_error; } if (!(buddy = fetion_buddy_find_by_userid(ac, userid))) { xmlnode_free(root); goto get_info_error; } if (xmlnode_has_prop(node, "sid")) { value = xmlnode_prop(node, "sid"); g_free(buddy->sid); buddy->sid = g_strdup(value); g_free(value); } if (xmlnode_has_prop(node, "mobile-no")) { value = xmlnode_prop(node, "mobile-no"); g_free(buddy->mobileno); buddy->mobileno = g_strdup(value); g_free(value); } if (xmlnode_has_prop(node, "impresa")) { value = xmlnode_prop(node, "impresa"); g_free(buddy->mood_phrase); buddy->mood_phrase = g_strdup(value); g_free(value); } if (xmlnode_has_prop(node, "nickname")) { value = xmlnode_prop(node, "nickname"); g_free(buddy->nickname); buddy->nickname = g_strdup(value); g_free(value); } if (xmlnode_has_prop(node, "gender")) { value = xmlnode_prop(node, "gender"); buddy->gender = atoi(value); g_free(value); } if (xmlnode_has_prop(node, "carrier-region")) { value = xmlnode_prop(node, "carrier-region"); for (pos = value; *pos && *pos != '.'; pos ++); g_free(buddy->country); buddy->country = g_strndup(value, pos - value); for (pos ++, temp = pos; *pos && *pos != '.'; pos ++); g_free(buddy->province); buddy->province = g_strndup(temp, pos - temp); for (pos ++, temp = pos; *pos && *pos != '.'; pos ++); g_free(buddy->city); buddy->city = g_strndup(temp, pos - temp); } xmlnode_free(node); return buddy; get_info_error: hybrid_debug_error("fetion", "invalid get-info response"); return NULL; }
gchar* get_city_name(const gchar *province, const gchar *city) { xmlnode *root; xmlnode *node; gchar *name; gchar *value; if (!(root = xmlnode_root_from_file(FETION_RES_DIR"city.xml"))) { return NULL; } if (!(node = xmlnode_child(root)) || g_strcmp0(node->name, "Province")) { hybrid_debug_error("fetion", "get full city name"); return NULL; } for (; node; node = xmlnode_next(node)) { if (!xmlnode_has_prop(node, "id")) { continue; } value = xmlnode_prop(node, "id"); if (g_strcmp0(value, province) == 0) { /* found, do cleanup. */ g_free(value); goto province_found; } g_free(value); } xmlnode_free(root); return NULL; province_found: if (!(node = xmlnode_child(node)) || g_strcmp0(node->name, "City")) { hybrid_debug_error("fetion", "get full city name"); xmlnode_free(root); return NULL; } for (; node; node = xmlnode_next(node)) { if (!xmlnode_has_prop(node, "id")) { continue; } value = xmlnode_prop(node, "id"); if (g_strcmp0(value, city) == 0) { name= xmlnode_content(node); /* found, do cleanup. */ g_free(value); xmlnode_free(root); return name; } g_free(value); } xmlnode_free(root); return NULL; }
/** * 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 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; }
/** * Parse the configuration information. We will get: * sipc-proxy,get-url, servers-version, parameters-version, * and hints-version */ static gint parse_configuration(fetion_account *ac, const gchar *cfg) { xmlnode *node; xmlnode *root; gchar *value; gchar *version; gchar *pos, *pos1; g_return_val_if_fail(cfg != NULL, 0); root = xmlnode_root(cfg, strlen(cfg)); if (!root) { goto cfg_parse_err; } if ((node = xmlnode_find(root, "servers"))) { version = xmlnode_prop(node, "version"); if (g_strcmp0(version, ac->cfg_server_version) != 0) { g_free(ac->cfg_server_version); ac->cfg_server_version = version; if (!(node = xmlnode_find(root, "sipc-proxy"))) { goto cfg_parse_err; } value = xmlnode_content(node); for (pos = value; *pos && *pos != ':'; pos ++ ); if (*pos == '\0') { g_free(value); goto cfg_parse_err; } ac->sipc_proxy_ip = g_strndup(value, pos - value); ac->sipc_proxy_port = atoi(pos + 1); g_free(value); if (!(node = xmlnode_find(root, "get-uri"))) { goto cfg_parse_err; } value = xmlnode_content(node); for (pos1 = value; *pos1 && *pos1 != '/'; pos1 ++); if (*pos1 == '\0' || *(pos1 + 1) != '/') { goto cfg_parse_err; } pos1 += 2; for (pos = pos1; *pos && *pos != '/'; pos ++); if (*pos == '\0') { goto cfg_parse_err; } ac->portrait_host_name = g_strndup(pos1, pos - pos1); pos1 = pos + 1; for (pos = pos1; *pos && *pos != '/'; pos ++); if (*pos == '\0') { goto cfg_parse_err; } ac->portrait_host_path = g_strndup(pos1, pos - pos1); } else { g_free(version); } } if ((node = xmlnode_find(root, "parameters"))) { g_free(ac->cfg_param_version); ac->cfg_param_version = xmlnode_prop(node, "version"); } if ((node = xmlnode_find(root, "hints"))) { g_free(ac->cfg_hint_version); ac->cfg_hint_version = xmlnode_prop(node, "version"); } if ((node = xmlnode_find(root, "client"))) { g_free(ac->cfg_client_version); ac->cfg_client_version = xmlnode_prop(node, "version"); } xmlnode_free(root); return HYBRID_OK; cfg_parse_err: xmlnode_free(root); hybrid_debug_error("fetion", "parse cfg body"); return HYBRID_ERROR; }
void sip_parse_notify(const gchar *sipmsg, gint *notify_type, gint *event_type) { gchar *attr; gchar *pos; gchar *event; xmlnode *root = NULL; xmlnode *node; g_return_if_fail(sipmsg != NULL); if (!(attr = sip_header_get_attr(sipmsg, "N"))) { *notify_type = NOTIFICATION_TYPE_UNKNOWN; *event_type = NOTIFICATION_EVENT_UNKNOWN; return; } if (g_strcmp0(attr, "PresenceV4") == 0) { *notify_type = NOTIFICATION_TYPE_PRESENCE; } else if (g_strcmp0(attr, "Conversation") == 0) { *notify_type = NOTIFICATION_TYPE_CONVERSATION; } else if (g_strcmp0(attr, "contact") == 0) { *notify_type = NOTIFICATION_TYPE_CONTACT; } else if (g_strcmp0(attr, "registration") == 0) { *notify_type = NOTIFICATION_TYPE_REGISTRATION; } else if (g_strcmp0(attr, "SyncUserInfoV4") == 0) { *notify_type = NOTIFICATION_TYPE_SYNCUSERINFO; } else if (g_strcmp0(attr, "PGGroup") == 0) { *notify_type = NOTIFICATION_TYPE_PGGROUP; } else { *notify_type = NOTIFICATION_TYPE_UNKNOWN; } g_free(attr); if (!(pos = strstr(sipmsg, "\r\n\r\n"))) { goto notify_err; } pos += 4; if (!(root = xmlnode_root(pos, strlen(pos)))) { goto notify_err; } if (!(node = xmlnode_find(root, "event"))) { goto notify_err; } if (!(event = xmlnode_prop(node, "type"))) { goto notify_err; } if (g_strcmp0(event, "Support") == 0) { if (!(node = xmlnode_next(node))) { goto notify_err; } if (g_strcmp0(node->name, "event") != 0) { goto notify_err; } if (!(event = xmlnode_prop(node, "type"))) { goto notify_err; } } if (g_strcmp0(event, "PresenceChanged") == 0) { *event_type = NOTIFICATION_EVENT_PRESENCECHANGED; } else if (g_strcmp0(event, "UserEntered") == 0) { *event_type = NOTIFICATION_EVENT_USERENTER; } else if (g_strcmp0(event, "UserLeft") == 0) { *event_type = NOTIFICATION_EVENT_USERLEFT; } else if (g_strcmp0(event, "deregistered") == 0) { *event_type = NOTIFICATION_EVENT_DEREGISTRATION; } else if (g_strcmp0(event, "SyncUserInfo") == 0) { *event_type = NOTIFICATION_EVENT_SYNCUSERINFO; } else if (g_strcmp0(event, "AddBuddyApplication") == 0) { *event_type = NOTIFICATION_EVENT_ADDBUDDYAPPLICATION; } else if (g_strcmp0(event, "PGGetGroupInfo") == 0) { *event_type = NOTIFICATION_EVENT_PGGETGROUPINFO; } else { *event_type = NOTIFICATION_EVENT_UNKNOWN; } xmlnode_free(root); return; notify_err: xmlnode_free(root); *event_type = NOTIFICATION_EVENT_UNKNOWN; return; }
/** * parse the sipc authentication response, we can get the basic * information and the contact list of this account. */ static void parse_sipc_resp(fetion_account *ac, const gchar *body, gint len) { xmlnode *root; xmlnode *node; gchar *version; g_return_if_fail(ac != NULL); g_return_if_fail(body != NULL); g_return_if_fail(len != 0); root = xmlnode_root(body, len); /* login info */ node = xmlnode_find(root, "client"); ac->last_login_ip = xmlnode_prop(root, "last-login-ip"); ac->public_ip = xmlnode_prop(root, "public-ip"); ac->last_login_time = xmlnode_prop(root, "last-login-time"); /* personal info */ node = xmlnode_find(root, "personal"); version = xmlnode_prop(node, "version"); if (g_strcmp0(version, ac->personal_version) == 0) { /* load from disk. */ g_free(version); xmlnode *personal_root; xmlnode *personal_node; if (!(personal_root = fetion_config_load_personal(ac))) { hybrid_debug_error("fetion", "invalid personal.xml"); xmlnode_free(root); return; } if (!(personal_node = xmlnode_find(personal_root, "personal"))) { hybrid_debug_error("fetion", "invalid personal.xml"); xmlnode_free(personal_root); xmlnode_free(root); return; } get_personal(ac, personal_node); xmlnode_free(personal_root); } else { /* update the version */ g_free(ac->personal_version); ac->personal_version = version; /* get the personal information */ get_personal(ac, node); /* save the personal information */ fetion_config_save_personal(ac, node); } /* contact list version */ node = xmlnode_find(root, "contact-list"); version = xmlnode_prop(node, "version"); if (g_strcmp0(version, ac->contact_list_version) == 0) { /* load from disk. */ g_free(version); xmlnode *contact_root; xmlnode *contact_node; if (!(contact_root = fetion_config_load_buddies(ac))) { hybrid_debug_error("fetion", "invalid buddies.xml"); xmlnode_free(root); return; } if (!(contact_node = xmlnode_find(contact_root, "contact-list"))) { hybrid_debug_error("fetion", "invalid buddies.xml"); xmlnode_free(contact_root); xmlnode_free(root); return; } get_contact_list(ac, contact_node); xmlnode_free(contact_root); } else { /* the cache is out-of-data, drop it. */ hybrid_account_clear_buddy(ac->account); /* update the version */ g_free(ac->contact_list_version); ac->contact_list_version = version; /* get the contact list */ get_contact_list(ac, node); /* save the contact list */ fetion_config_save_buddies(ac, node); } /* custom config */ node = xmlnode_find(root, "custom-config"); version = xmlnode_prop(node, "version"); if (g_strcmp0(version, ac->custom_config_version) != 0) { g_free(ac->custom_config); g_free(ac->custom_config_version); ac->custom_config = xmlnode_content(node); ac->custom_config_version = version; } xmlnode_free(root); /* * OK, now we need to save the account's version information, so * next time we can use it to register to sipc server. */ fetion_config_save_account(ac); }
static void xmpp_stream_process_presence(XmppStream *stream, xmlnode *root) { xmlnode *node; XmppBuddy *buddy; gchar *value; gchar *full_jid; gchar *bare_jid; gchar *show; gchar *status; gchar *photo; if (!xmlnode_has_prop(root, "from")) { hybrid_debug_error("xmpp", "invalid presence."); return; } full_jid = xmlnode_prop(root, "from"); bare_jid = get_bare_jid(full_jid); if (xmlnode_has_prop(root, "type")) { value = xmlnode_prop(root, "type"); if (g_strcmp0(value, "unavailable") == 0) { if (!(buddy = xmpp_buddy_find(stream->account, bare_jid))) { goto presence_over; } xmpp_buddy_set_show(buddy, full_jid, value); g_free(value); goto presence_over; } else if (g_strcmp0(value, "subscribed") == 0) { hybrid_message_box_show(HYBRID_MESSAGE_INFO, "(<b>%s</b>) has accepted your request.", bare_jid); g_free(value); goto presence_over; } else if (g_strcmp0(value, "subscribe") == 0) { hybrid_buddy_request_window_create(stream->account->account, full_jid, NULL); g_free(value); goto presence_over; } g_free(value); } if (!(buddy = xmpp_buddy_find(stream->account, bare_jid))) { goto presence_over; } /* * If the presence message doesn't have a <show> label, * then it means the current status of the buddy is 'avaiable'. */ if ((node = xmlnode_find(root, "show"))) { show = xmlnode_content(node); xmpp_buddy_set_show(buddy, full_jid, show); g_free(show); } else { xmpp_buddy_set_show(buddy, full_jid, "avaiable"); } if ((node = xmlnode_find(root, "status"))) { status = xmlnode_content(node); xmpp_buddy_set_status(buddy, full_jid, status); g_free(status); } /* * Check whether it has a photo label, then we can * determine whether to fetch the buddy's photo. */ if ((node = xmlnode_find(root, "photo"))) { photo = xmlnode_content(node); if (g_strcmp0(photo, buddy->photo) != 0) { xmpp_buddy_set_photo(buddy, photo); xmpp_buddy_get_info(stream, buddy->jid, (trans_callback)buddy_get_info_cb, buddy); } g_free(photo); } presence_over: g_free(full_jid); g_free(bare_jid); }
GSList* sip_parse_sync(fetion_account *account, const gchar *sipmsg) { gchar *pos; gchar *action; gchar *userid; gchar *status; xmlnode *root; xmlnode *node; fetion_buddy *buddy; GSList *list = NULL; if (!(pos = strstr(sipmsg, "\r\n\r\n"))) { goto sync_info_err; } pos += 4; if (!(root = xmlnode_root(pos, strlen(pos)))) { goto sync_info_err; } if (!(node = xmlnode_find(root, "buddies"))) { xmlnode_free(root); return list; } node = xmlnode_child(node); while (node) { if (!xmlnode_has_prop(node, "action")) { goto next; } action = xmlnode_prop(node, "action"); if (g_strcmp0(action, "update") == 0) { if (!xmlnode_has_prop(node, "user-id") || !xmlnode_has_prop(node, "relation-status")) { g_free(action); goto next; } userid = xmlnode_prop(node, "user-id"); status = xmlnode_prop(node, "relation-status"); if (!(buddy = fetion_buddy_find_by_userid(account, userid))) { g_free(action); g_free(userid); g_free(status); goto next; } buddy->status = atoi(status); list = g_slist_append(list, buddy); g_free(status); g_free(userid); } g_free(action); next: node = xmlnode_next(node); } return list; sync_info_err: hybrid_debug_error("fetion", "invalid sync info"); return list; }