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; }
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; }
gint fetion_message_parse_sysmsg(const gchar *sipmsg, gchar **content, gchar **url) { gchar *pos; xmlnode *root; xmlnode *node; if (!(pos = strstr(sipmsg, "\r\n\r\n"))) { goto sysmsg_error; } if (!(root = xmlnode_root(pos, strlen(pos)))) { goto sysmsg_error; } if (!(node = xmlnode_find(root, "content"))) { xmlnode_free(root); goto sysmsg_error; } *content = xmlnode_content(node); if ((node = xmlnode_find(root, "url"))) { *url = xmlnode_content(node); } else { *url = NULL; } xmlnode_free(root); return HYBRID_OK; sysmsg_error: hybrid_debug_error("fetion", "invalid system message"); return HYBRID_ERROR; }
/** * 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; }
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 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); }
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; } }
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; }
/** * 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); }
/** * 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; }