void flist_profile_load(PurpleConnection *pc) { FListAccount *fla = pc->proto_data; FListProfiles *flp; GSList *priority = NULL; fla->flist_profiles = g_new0(FListProfiles, 1); flp = _flist_profiles(fla); flp->global_profile_request = flist_web_request(JSON_INFO_LIST, NULL, NULL, TRUE, fla->secure, flist_global_profile_cb, fla); FListProfileField *field; //TODO: this is really, really ugly field = g_new0(FListProfileField, 1); field->name = g_strdup("Orientation"); field->fieldid = g_strdup("2"); priority = g_slist_prepend(priority, field); field = g_new0(FListProfileField, 1); field->name = g_strdup("Species"); field->fieldid = g_strdup("9"); priority = g_slist_prepend(priority, field); field = g_new0(FListProfileField, 1); field->name = g_strdup("Dom/Sub Role"); field->fieldid = g_strdup("15"); priority = g_slist_prepend(priority, field); field = g_new0(FListProfileField, 1); field->name = g_strdup("Position"); field->fieldid = g_strdup("41"); priority = g_slist_prepend(priority, field); priority = g_slist_reverse(priority); flp->priority_profile_fields = priority; }
void flist_get_profile(PurpleConnection *pc, const char *who) { FListAccount *fla; FListProfiles *flp; GString *link_str; gchar *link; FListCharacter *character; g_return_if_fail((fla = pc->proto_data)); flp = _flist_profiles(fla); if(flp->character) g_free(flp->character); flp->character = NULL; if(flp->profile_info) purple_notify_user_info_destroy(flp->profile_info); flp->profile_info = NULL; if(flp->table) g_hash_table_destroy(flp->table); flp->table = NULL; if(flp->profile_request) { flist_web_request_cancel(flp->profile_request); flp->profile_request = NULL; } flp->character = g_strdup(who); flp->profile_info = purple_notify_user_info_new(); link_str = g_string_new(NULL); g_string_append_printf(link_str, "http://www.f-list.net/c/%s", purple_url_encode(who)); link = g_string_free(link_str, FALSE); character = flist_get_character(fla, who); if(!character) { purple_notify_user_info_add_pair(flp->profile_info, "Status", "Offline"); } else { gchar *clean_message = flist_html_unescape_utf8(character->status_message); gchar *parsed_message = flist_bbcode_to_html(fla, NULL, clean_message); purple_notify_user_info_add_pair(flp->profile_info, "Status", flist_format_status(character->status)); purple_notify_user_info_add_pair(flp->profile_info, "Gender", flist_format_gender(character->gender)); purple_notify_user_info_add_pair(flp->profile_info, "Message", parsed_message); g_free(parsed_message); g_free(clean_message); } purple_notify_user_info_add_pair(flp->profile_info, "Link", link); purple_notify_userinfo(pc, flp->character, flp->profile_info, NULL, NULL); if(!character) { //The character is offline. There's nothing more we should do. g_free(flp->character); flp->character = NULL; purple_notify_user_info_destroy(flp->profile_info); flp->profile_info = NULL; } else if(flp->category_table) { /* Try to get the profile through the website API first. */ GHashTable *args = flist_web_request_args(fla); g_hash_table_insert(args, "name", g_strdup(flp->character)); flp->profile_request = flist_web_request(JSON_CHARACTER_INFO, args, NULL, TRUE, fla->secure, flist_get_profile_cb, fla); g_hash_table_destroy(args); } else { /* Try to get the profile through F-Chat. */ JsonObject *json = json_object_new(); json_object_set_string_member(json, "character", flp->character); flist_request(pc, "PRO", json); json_object_unref(json); } g_free(link); }
static void flist_get_profile_cb(FListWebRequestData *req_data, gpointer user_data, JsonObject *root, const gchar *error_message) { FListAccount *fla = user_data; FListProfiles *flp = _flist_profiles(fla); gboolean success; flp->profile_request = NULL; if(!root) { purple_debug_warning(FLIST_DEBUG, "We requested a profile from the Web API, but failed. Error Message: %s\n", error_message); success = FALSE; } else { success = flist_process_profile(fla, root); } if(success) { g_free(flp->character); flp->character = NULL; purple_notify_user_info_destroy(flp->profile_info); flp->profile_info = NULL; } else { JsonObject *json = json_object_new(); json_object_set_string_member(json, "character", flp->character); flist_request(fla->pc, "PRO", json); json_object_unref(json); } }
void flist_profile_process_flood(FListAccount *fla, const gchar *message) { FListProfiles *flp = _flist_profiles(fla); if(flp->profile_info && flp->character) { purple_notify_user_info_add_pair(flp->profile_info, "Error", message); purple_notify_userinfo(fla->pc, flp->character, flp->profile_info, NULL, NULL); g_free(flp->character); flp->character = NULL; purple_notify_user_info_destroy(flp->profile_info); flp->profile_info = NULL; } }
static gboolean flist_process_profile(FListAccount *fla, JsonObject *root) { FListProfiles *flp = _flist_profiles(fla); JsonObject *info; GList *categories, *cur; GHashTable *profile; const gchar *error; error = json_object_get_string_member(root, "error"); if(error && strlen(error) > 0) { purple_debug_info(FLIST_DEBUG, "We requested a profile from the Web API, but it returned an error. Error Message: %s\n", error); return FALSE; //user probably opted out of API access } profile = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL); info = json_object_get_object_member(root, "info"); categories = json_object_get_members(info); cur = categories; while(cur) { JsonObject *field_group; JsonArray *field_array; guint i, len; field_group = json_object_get_object_member(info, cur->data); field_array = json_object_get_array_member(field_group, "items"); len = json_array_get_length(field_array); for(i = 0; i < len; i++) { JsonObject *field_object = json_array_get_object_element(field_array, i); const gchar *field_name = json_object_get_string_member(field_object, "name"); gchar *unescaped = flist_html_unescape_utf8(json_object_get_string_member(field_object, "value")); gchar *field_value = purple_markup_escape_text(unescaped, strlen(unescaped)); g_hash_table_insert(profile, (gpointer) field_name, (gpointer) field_value); g_free(unescaped); } cur = cur->next; } g_list_free(categories); flist_show_profile(fla->pc, flp->character, profile, FALSE, flp->profile_info); g_hash_table_destroy(profile); return TRUE; }
void flist_profile_unload(PurpleConnection *pc) { FListAccount *fla = pc->proto_data; FListProfiles *flp = _flist_profiles(fla); if(flp->global_profile_request) { flist_web_request_cancel(flp->global_profile_request); flp->global_profile_request = NULL; } if(flp->priority_profile_fields) { g_slist_free(flp->priority_profile_fields); flp->priority_profile_fields = NULL; } if(flp->category_list) { g_slist_free(flp->category_list); flp->category_list = NULL; } if(flp->category_table) { g_hash_table_destroy(flp->category_table); flp->category_table = NULL; } if(flp->profile_request) { flist_web_request_cancel(flp->profile_request); flp->profile_request = NULL; } if(flp->character) { g_free(flp->character); flp->character = NULL; } if(flp->profile_info) { purple_notify_user_info_destroy(flp->profile_info); flp->profile_info = NULL; } if(flp->table) { g_hash_table_destroy(flp->table); flp->table = NULL; } if(flp->profile_request) flp->profile_request = NULL; g_free(flp); //TODO: lots of memory leaks here to cleanup? }
gboolean flist_process_PRD(PurpleConnection *pc, JsonObject *root) { FListAccount *fla = pc->proto_data; FListProfiles *flp = _flist_profiles(fla); const gchar *type; const gchar *key; gchar *value, *unescaped; if(!flp->character) { purple_debug_error(FLIST_DEBUG, "Profile information received, but we are not expecting profile information.\n"); return TRUE; } type = json_object_get_string_member(root, "type"); if(!g_strcmp0(type, "start")) { /* we don't care! */ if(flp->table) g_hash_table_destroy(flp->table); flp->table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); return TRUE; } if(!g_strcmp0(type, "end")) { flist_show_profile(pc, flp->character, flp->table, FALSE, flp->profile_info); g_free(flp->character); flp->character = NULL; if(flp->table) { g_hash_table_destroy(flp->table); flp->table = NULL; } purple_notify_user_info_destroy(flp->profile_info); flp->profile_info = NULL; return TRUE; } if(!flp->table) { return TRUE; //this should never happen } key = json_object_get_string_member(root, "key"); unescaped = flist_html_unescape_utf8(json_object_get_string_member(root, "value")); value = purple_markup_escape_text(unescaped, strlen(unescaped)); g_hash_table_replace(flp->table, g_strdup(key), value); purple_debug_info(FLIST_DEBUG, "Profile information received for %s. Key: %s. Value: %s.\n", flp->character, key, value); g_free(unescaped); return TRUE; }
static void flist_show_profile(PurpleConnection *pc, const gchar *character, GHashTable *profile, gboolean by_id, PurpleNotifyUserInfo *info) { FListAccount *fla = pc->proto_data; FListProfiles *flp = _flist_profiles(fla); GSList *priority = flp->priority_profile_fields; GSList *category_list = flp->category_list; GList *remaining; //Add a section break after the main info. purple_notify_user_info_add_section_break(info); while(priority) { FListProfileField *field = priority->data; const gchar *key = !by_id ? field->name : field->fieldid; const gchar *value = g_hash_table_lookup(profile, key); if(value) { purple_notify_user_info_add_pair(info, field->name, value); g_hash_table_remove(profile, key); } else { purple_notify_user_info_add_pair(info, field->name, FLIST_PROFILE_DEFAULT_VALUE); } priority = g_slist_next(priority); } //Now, add by category. while(category_list) { FListProfileFieldCategory *category = category_list->data; GSList *field_list = category->fields; gboolean first = TRUE; while(field_list) { FListProfileField *field = field_list->data; const gchar *key = !by_id ? field->name : field->fieldid; const gchar *value = g_hash_table_lookup(profile, key); if(value) { if(first) { purple_notify_user_info_add_section_break(info); //purple_notify_user_info_add_section_header(info, category->name); } purple_notify_user_info_add_pair(info, field->name, value); first = FALSE; g_hash_table_remove(profile, key); } field_list = g_slist_next(field_list); } category_list = g_slist_next(category_list); } //Now, add everything that we missed. //(Ideally, we should do nothing.) remaining = g_hash_table_get_keys(profile); if(remaining) { GList *cur; remaining = g_list_sort(remaining, (GCompareFunc) purple_utf8_strcasecmp); cur = remaining; purple_notify_user_info_add_section_break(info); //purple_notify_user_info_add_section_header(info, FLIST_PROFILE_DEFAULT_CATEGORY); while(cur) { const gchar *field = cur->data; const gchar *value = g_hash_table_lookup(profile, field); purple_notify_user_info_add_pair(info, field, value); g_hash_table_remove(profile, field); cur = g_list_next(cur); } g_list_free(remaining); } purple_notify_userinfo(pc, character, info, NULL, NULL); }
static void flist_global_profile_cb(FListWebRequestData *req_data, gpointer user_data, JsonObject *root, const gchar *error_message) { FListAccount *fla = user_data; FListProfiles *flp = _flist_profiles(fla); JsonObject *info; GList *categories, *cur; flp->global_profile_request = NULL; if(!root) { purple_debug_warning(FLIST_DEBUG, "Failed to obtain the global list of profile fields. Error Message: %s\n", error_message); return; } info = json_object_get_object_member(root, "info"); if(!info) { purple_debug_warning(FLIST_DEBUG, "We received the global list of profile fields, but it was empty.\n"); return; } purple_debug_info(FLIST_DEBUG, "Processing global profile fields...\n"); flp->category_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, flist_profile_field_category_free); categories = json_object_get_members(info); cur = categories; while(cur) { const gchar *group_name; JsonObject *field_group; JsonArray *field_array; FListProfileFieldCategory *category; guint i, len; field_group = json_object_get_object_member(info, cur->data); group_name = json_object_get_string_member(field_group, "group"); field_array = json_object_get_array_member(field_group, "items"); category = g_new0(FListProfileFieldCategory, 1); category->name = g_strdup(group_name); len = json_array_get_length(field_array); for(i = 0; i < len; i++) { JsonObject *field_object = json_array_get_object_element(field_array, i); FListProfileField *field = g_new0(FListProfileField, 1); field->category = category; field->fieldid = g_strdup_printf("%d", (gint) json_object_get_int_member(field_object, "id")); field->name = g_strdup(json_object_get_string_member(field_object, "name")); category->fields = g_slist_prepend(category->fields, field); if(fla->debug_mode) { purple_debug_info(FLIST_DEBUG, "Global profile field processed. (ID: %s) (Category: %s) (Name: %s)\n", field->fieldid, field->category->name, field->name); } } category->fields = g_slist_sort(category->fields, (GCompareFunc) flist_profile_field_cmp); flp->category_list = g_slist_append(flp->category_list, category); g_hash_table_insert(flp->category_table, g_strdup(category->name), category); cur = g_list_next(cur); } g_list_free(categories); purple_debug_info(FLIST_DEBUG, "Global profile fields processed. (Categories: %d)\n", g_hash_table_size(flp->category_table)); }