# HG changeset patch # User Yoshiki Yazawa # Date 1314588529 -32400 # Node ID ac6353ffa129c429701596c9d5608213d038d0d6 # Parent 9aee8493db7ff8812d4dc698353f4fbf57c40cb6# Parent 50cdd401274a77f5e108a35d5eb9790063bff1a6 merge to upstream diff -r 9aee8493db7f -r ac6353ffa129 ChangeLog --- a/ChangeLog Mon Aug 22 11:20:05 2011 +0900 +++ b/ChangeLog Mon Aug 29 12:28:49 2011 +0900 @@ -6,6 +6,14 @@ * Don't try to format ICQ usernames entered as email addresses. Gets rid of an "Unable to format username" error at login. (#13883) + MXit: + * Remove all reference to Hidden Number. + * Fix decoding of font-size changes in the markup of received messages. + * Ignore new invites to join a GroupChat if you're already joined, or + still have a pending invite. + * The buddy's name was not centered vertically in the buddy-list if they + did not have a status-message or mood set. + version 2.10.0 (08/18/2011): Pidgin: * Make the max size of incoming smileys a pref instead of hardcoding it. diff -r 9aee8493db7f -r ac6353ffa129 ChangeLog.API --- a/ChangeLog.API Mon Aug 22 11:20:05 2011 +0900 +++ b/ChangeLog.API Mon Aug 29 12:28:49 2011 +0900 @@ -5,18 +5,55 @@ Added: * purple_notify_searchresult_column_set_visible * purple_notify_searchresult_column_is_visible + * purple_notify_user_info_prepend_pair_plaintext * purple_request_field_set_tooltip * purple_request_field_get_tooltip + * purple_roomlist_get_account + * purple_roomlist_get_proto_data + * purple_roomlist_get_ui_data + * purple_roomlist_room_get_expanded_once + * purple_roomlist_room_set_expanded_once + * purple_roomlist_set_proto_data + * purple_roomlist_set_ui_data + * purple_xfer_get_protocol_data + * purple_xfer_set_protocol_data + * purple_xfer_get_ui_data + * purple_xfer_set_ui_data + * purple_conversation_get_ui_data + * purple_conversation_set_ui_data Changed: + * purple_connection_error now takes a PurpleConnectionError + as the second parameter + * purple_notify_user_info_add_pair renamed to + purple_notify_user_info_add_pair_html + * purple_notify_user_info_get_entries returns a GQueue instead of + a GList + * purple_notify_user_info_prepend_pair renamed to + purple_notify_user_info_prepend_pair_html * purple_util_fetch_url_request_len now takes a PurpleAccount as the first parameter * PurpleConnectionUiOps.report_disconnect now passes a PurpleConnectionError as the second parameter - * purple_connection_error now takes a PurpleConnectionError - as the second parameter Removed: + * _GntFileType + * _GntKeyPressMode + * _GntMouseEvent + * _GntParamFlags + * _GntProgressBarOrientation + * _GntTreeColumnFlag + * _GntWidgetFlags + * _PurpleCipherBatchMode + * _PurpleCipherCaps + * _PurpleCmdFlag + * _PurpleCmdPriority + * _PurpleCmdRet + * _PurpleCmdStatus + * _PurplePrefType + * _PurplePrivacyType + * _PurpleSoundEventID + * _XMLNodeType * GtkIMHtml.clipboard_html_string * GtkIMHtml.clipboard_text_string * pidgin_blist_update_account_error_state @@ -40,6 +77,11 @@ purple_util_fetch_url_request_len, insetad. * PurpleConnectionUiOps.report_disconnect_reason * struct _GtkIMHtmlFontDetail + * struct _PurplePounce + * struct _PurpleRequestField + * struct _PurpleRoomlist + * struct _PurpleRoomlistField + * struct _PurpleRoomlistRoom version 2.10.0: libpurple: diff -r 9aee8493db7f -r ac6353ffa129 configure.ac --- a/configure.ac Mon Aug 22 11:20:05 2011 +0900 +++ b/configure.ac Mon Aug 29 12:28:49 2011 +0900 @@ -941,25 +941,6 @@ ], [ have_silc="no" ]) - if test "x$have_silc" = "xno"; then - PKG_CHECK_MODULES(SILC, silcclient, [ - have_silc="yes" - silc10includes="yes" - silc10client="yes" - ], [ - have_silc="no" - ]) - dnl If silcclient.pc wasn't found, check for just silc.pc - if test "x$have_silc" = "xno"; then - PKG_CHECK_MODULES(SILC, silc, [ - have_silc="yes" - silc10includes="yes" - silc10client="yes" - ], [ - have_silc="no" - ]) - fi - fi else if test "$ac_silc_includes" != "no"; then SILC_CFLAGS="-I$ac_silc_includes" @@ -977,17 +958,6 @@ if test "x$silcincludes" = "xyes" -a "x$silcclient" = "xyes"; then have_silc="yes" - else - CPPFLAGS_save="$CPPFLAGS" - CPPFLAGS="$CPPFLAGS $SILC_CFLAGS" - AC_CHECK_HEADER(silcincludes.h, [silc10includes=yes]) - CPPFLAGS="$CPPFLAGS_save" - - SILC_LIBS="$SILC_LIBS -lsilc -lsilcclient -lpthread $LIBDL" - AC_CHECK_LIB(silcclient, silc_client_init, [silc10client=yes], , $SILC_LIBS) - if test "x$silc10includes" = "xyes" -a "x$silc10client" = "xyes"; then - have_silc="yes" - fi fi fi AC_SUBST(SILC_LIBS) @@ -995,20 +965,6 @@ dnl SILC Toolkit >= 1.0.1 has a new MIME API if test "x$silcclient" = "xyes"; then AC_DEFINE(HAVE_SILCMIME_H, 1, [Define if we have silcmime.h]) -elif test "x$silc10client" = "xyes"; then - CPPFLAGS_save="$CPPFLAGS" - CPPFLAGS="$CPPFLAGS $SILC_CFLAGS" - AC_MSG_CHECKING(for silcmime.h) - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ -#include -#include - ]], [[]])], [ - AC_MSG_RESULT(yes) - AC_DEFINE(HAVE_SILCMIME_H, 1, [Define if we have silcmime.h]) - ], [ - AC_MSG_RESULT(no) - ]) - CPPFLAGS="$CPPFLAGS_save" fi dnl ####################################################################### @@ -1123,10 +1079,7 @@ STATIC_PRPLS=`echo $STATIC_PRPLS | $sedpath 's/bonjour//'` fi if test "x$silcincludes" != "xyes" -o "x$silcclient" != "xyes"; then - STATIC_PRPLS=`echo $STATIC_PRPLS | $sedpath 's/silc/silc10/'` -fi -if test "x$silc10includes" != "xyes" -o "x$silc10client" != "xyes"; then - STATIC_PRPLS=`echo $STATIC_PRPLS | $sedpath 's/silc10//'` + STATIC_PRPLS=`echo $STATIC_PRPLS | $sedpath 's/silc//'` fi AC_SUBST(STATIC_PRPLS) STATIC_LINK_LIBS= @@ -1150,8 +1103,6 @@ else if test "x$i" = "xsilc"; then STATIC_LINK_LIBS="$STATIC_LINK_LIBS \$(top_builddir)/libpurple/protocols/$i/lib${i}purple.la" - elif test "x$i" = "xsilc10"; then - STATIC_LINK_LIBS="$STATIC_LINK_LIBS \$(top_builddir)/libpurple/protocols/$i/libsilcpurple.la" else STATIC_LINK_LIBS="$STATIC_LINK_LIBS \$(top_builddir)/libpurple/protocols/$i/lib$i.la" fi @@ -1172,7 +1123,6 @@ icq) static_oscar=yes ;; sametime) static_sametime=yes ;; silc) static_silc=yes ;; - silc10) static_silc=yes ;; simple) static_simple=yes ;; yahoo) static_yahoo=yes ;; zephyr) static_zephyr=yes ;; @@ -1208,10 +1158,7 @@ DYNAMIC_PRPLS=`echo $DYNAMIC_PRPLS | $sedpath 's/bonjour//'` fi if test "x$silcincludes" != "xyes" -o "x$silcclient" != "xyes"; then - DYNAMIC_PRPLS=`echo $DYNAMIC_PRPLS | $sedpath 's/silc/silc10/'` -fi -if test "x$silc10includes" != "xyes" -o "x$silc10client" != "xyes"; then - DYNAMIC_PRPLS=`echo $DYNAMIC_PRPLS | $sedpath 's/silc10//'` + DYNAMIC_PRPLS=`echo $DYNAMIC_PRPLS | $sedpath 's/silc//'` fi AC_SUBST(DYNAMIC_PRPLS) for i in $DYNAMIC_PRPLS ; do @@ -1230,7 +1177,6 @@ icq) dynamic_oscar=yes ;; sametime) dynamic_sametime=yes ;; silc) dynamic_silc=yes ;; - silc10) dynamic_silc=yes ;; simple) dynamic_simple=yes ;; yahoo) dynamic_yahoo=yes ;; zephyr) dynamic_zephyr=yes ;; @@ -2575,7 +2521,6 @@ libpurple/protocols/oscar/Makefile libpurple/protocols/sametime/Makefile libpurple/protocols/silc/Makefile - libpurple/protocols/silc10/Makefile libpurple/protocols/simple/Makefile libpurple/protocols/yahoo/Makefile libpurple/protocols/zephyr/Makefile diff -r 9aee8493db7f -r ac6353ffa129 finch/gntblist.c --- a/finch/gntblist.c Mon Aug 22 11:20:05 2011 +0900 +++ b/finch/gntblist.c Mon Aug 29 12:28:49 2011 +0900 @@ -1060,7 +1060,7 @@ purple_buddy_get_account(buddy), purple_buddy_get_name(buddy)); } else { - FinchConv *ggconv = FINCH_GET_DATA(conv); + FinchConv *ggconv = FINCH_CONV(conv); gnt_window_present(ggconv->window); } finch_conversation_set_active(conv); @@ -1268,7 +1268,7 @@ { PurpleNotifyUserInfo *info = purple_notify_user_info_new(); gpointer uihandle; - purple_notify_user_info_add_pair(info, _("Information"), _("Retrieving...")); + purple_notify_user_info_add_pair_plaintext(info, _("Information"), _("Retrieving...")); uihandle = purple_notify_userinfo(conn, name, info, NULL, NULL); purple_notify_user_info_destroy(info); @@ -1783,15 +1783,13 @@ presence = purple_buddy_get_presence(buddy); if (!full || g_utf8_collate(purple_buddy_get_name(buddy), alias)) { - char *esc = g_markup_escape_text(alias, -1); - purple_notify_user_info_add_pair(user_info, _("Nickname"), esc); - g_free(esc); + purple_notify_user_info_add_pair_plaintext(user_info, _("Nickname"), alias); } tmp = g_strdup_printf("%s (%s)", purple_account_get_username(account), purple_account_get_protocol_name(account)); - purple_notify_user_info_add_pair(user_info, _("Account"), tmp); + purple_notify_user_info_add_pair_plaintext(user_info, _("Account"), tmp); g_free(tmp); prpl = purple_find_prpl(purple_account_get_protocol_id(account)); @@ -1806,7 +1804,7 @@ time_t idle = purple_presence_get_idle_time(pre); if (idle > 0) { char *st = purple_str_seconds_to_string(time(NULL) - idle); - purple_notify_user_info_add_pair(user_info, _("Idle"), st); + purple_notify_user_info_add_pair_plaintext(user_info, _("Idle"), st); g_free(st); } } diff -r 9aee8493db7f -r ac6353ffa129 finch/gntconv.c --- a/finch/gntconv.c Mon Aug 22 11:20:05 2011 +0900 +++ b/finch/gntconv.c Mon Aug 29 12:28:49 2011 +0900 @@ -282,7 +282,7 @@ return; im = PURPLE_CONV_IM(conv); - ggc = FINCH_GET_DATA(conv); + ggc = FINCH_CONV(conv); if (purple_conv_im_get_typing_state(im) == PURPLE_TYPING) { int scroll; @@ -321,7 +321,7 @@ PurpleConversation *conv = find_conv_with_contact(purple_buddy_get_account(buddy), purple_buddy_get_name(buddy)); if (conv == NULL) return; - generate_send_to_menu(FINCH_GET_DATA(conv)); + generate_send_to_menu(FINCH_CONV(conv)); } static void @@ -333,7 +333,7 @@ PurpleConversation *cc = find_conv_with_contact( purple_conversation_get_account(conv), purple_conversation_get_name(conv)); if (cc) - generate_send_to_menu(FINCH_GET_DATA(cc)); + generate_send_to_menu(FINCH_CONV(cc)); list = list->next; } @@ -398,7 +398,7 @@ static void cleared_message_history_cb(PurpleConversation *conv, gpointer data) { - FinchConv *ggc = FINCH_GET_DATA(conv); + FinchConv *ggc = FINCH_CONV(conv); if (ggc) gnt_text_view_clear(GNT_TEXT_VIEW(ggc->tv)); } @@ -749,7 +749,7 @@ static void finch_create_conversation(PurpleConversation *conv) { - FinchConv *ggc = FINCH_GET_DATA(conv); + FinchConv *ggc = FINCH_CONV(conv); char *title; PurpleConversationType type; PurpleConversation *cc; @@ -763,8 +763,8 @@ account = purple_conversation_get_account(conv); cc = find_conv_with_contact(account, purple_conversation_get_name(conv)); - if (cc && FINCH_GET_DATA(cc)) - ggc = FINCH_GET_DATA(cc); + if (cc && FINCH_CONV(cc)) + ggc = FINCH_CONV(cc); else ggc = g_new0(FinchConv, 1); @@ -776,9 +776,9 @@ ggc->list = g_list_prepend(ggc->list, conv); ggc->active_conv = conv; - FINCH_SET_DATA(conv, ggc); + purple_conversation_set_ui_data(conv, ggc); - if (cc && FINCH_GET_DATA(cc) && cc != conv) { + if (cc && FINCH_CONV(cc) && cc != conv) { finch_conversation_set_active(conv); return; } @@ -885,7 +885,7 @@ finch_destroy_conversation(PurpleConversation *conv) { /* do stuff here */ - FinchConv *ggc = FINCH_GET_DATA(conv); + FinchConv *ggc = FINCH_CONV(conv); ggc->list = g_list_remove(ggc->list, conv); if (ggc->list && conv == ggc->active_conv) { ggc->active_conv = ggc->list->data; @@ -905,7 +905,7 @@ finch_write_common(PurpleConversation *conv, const char *who, const char *message, PurpleMessageFlags flags, time_t mtime) { - FinchConv *ggconv = FINCH_GET_DATA(conv); + FinchConv *ggconv = FINCH_CONV(conv); char *strip, *newline; GntTextFormatFlags fl = 0; int pos; @@ -1069,7 +1069,7 @@ static void finch_chat_add_users(PurpleConversation *conv, GList *users, gboolean new_arrivals) { - FinchConv *ggc = FINCH_GET_DATA(conv); + FinchConv *ggc = FINCH_CONV(conv); GntEntry *entry = GNT_ENTRY(ggc->entry); if (!new_arrivals) @@ -1111,7 +1111,7 @@ finch_chat_rename_user(PurpleConversation *conv, const char *old, const char *new_n, const char *new_a) { /* Update the name for string completion */ - FinchConv *ggc = FINCH_GET_DATA(conv); + FinchConv *ggc = FINCH_CONV(conv); GntEntry *entry = GNT_ENTRY(ggc->entry); GntTree *tree = GNT_TREE(ggc->u.chat->userlist); PurpleConvChatBuddy *cb = purple_conv_chat_cb_find(PURPLE_CONV_CHAT(conv), new_n); @@ -1129,7 +1129,7 @@ finch_chat_remove_users(PurpleConversation *conv, GList *list) { /* Remove the name from string completion */ - FinchConv *ggc = FINCH_GET_DATA(conv); + FinchConv *ggc = FINCH_CONV(conv); GntEntry *entry = GNT_ENTRY(ggc->entry); for (; list; list = list->next) { GntTree *tree = GNT_TREE(ggc->u.chat->userlist); @@ -1142,7 +1142,7 @@ finch_chat_update_user(PurpleConversation *conv, const char *user) { PurpleConvChatBuddy *cb = purple_conv_chat_cb_find(PURPLE_CONV_CHAT(conv), user); - FinchConv *ggc = FINCH_GET_DATA(conv); + FinchConv *ggc = FINCH_CONV(conv); gnt_tree_change_text(GNT_TREE(ggc->u.chat->userlist), (gpointer)user, 0, chat_flag_text(cb->flags)); } @@ -1368,7 +1368,7 @@ static PurpleCmdRet users_command_cb(PurpleConversation *conv, const char *cmd, char **args, char **error, gpointer data) { - FinchConv *fc = FINCH_GET_DATA(conv); + FinchConv *fc = FINCH_CONV(conv); FinchConvChat *ch; if (!fc) return PURPLE_CMD_RET_FAILED; @@ -1494,7 +1494,7 @@ void finch_conversation_set_active(PurpleConversation *conv) { - FinchConv *ggconv = FINCH_GET_DATA(conv); + FinchConv *ggconv = FINCH_CONV(conv); PurpleAccount *account; char *title; @@ -1513,7 +1513,7 @@ void finch_conversation_set_info_widget(PurpleConversation *conv, GntWidget *widget) { - FinchConv *fc = FINCH_GET_DATA(conv); + FinchConv *fc = FINCH_CONV(conv); int height, width; gnt_box_remove_all(GNT_BOX(fc->info)); diff -r 9aee8493db7f -r ac6353ffa129 finch/gntconv.h --- a/finch/gntconv.h Mon Aug 22 11:20:05 2011 +0900 +++ b/finch/gntconv.h Mon Aug 29 12:28:49 2011 +0900 @@ -33,7 +33,7 @@ #include "conversation.h" /* Grabs the conv out of a PurpleConverstation */ -#define FINCH_CONV(conv) ((FinchConv *)(conv)->ui_data) +#define FINCH_CONV(conv) ((FinchConv *)purple_conversation_get_ui_data(conv)) /*************************************************************************** * @name GNT Conversations API diff -r 9aee8493db7f -r ac6353ffa129 finch/gntft.c --- a/finch/gntft.c Mon Aug 22 11:20:05 2011 +0900 +++ b/finch/gntft.c Mon Aug 29 12:28:49 2011 +0900 @@ -42,9 +42,6 @@ #include "gntft.h" #include "prefs.h" -#define FINCHXFER(xfer) \ - (PurpleGntXferUiData *)FINCH_GET_DATA(xfer) - typedef struct { gboolean keep_open; @@ -262,7 +259,7 @@ for (iter = purple_xfers_get_all(); iter; iter = iter->next) { PurpleXfer *xfer = (PurpleXfer *)iter->data; - PurpleGntXferUiData *data = FINCHXFER(xfer); + PurpleGntXferUiData *data = purple_xfer_get_ui_data(xfer); if (data->in_list) { finch_xfer_dialog_add_xfer(xfer); finch_xfer_dialog_update_xfer(xfer); @@ -302,7 +299,7 @@ purple_xfer_ref(xfer); - data = FINCHXFER(xfer); + data = purple_xfer_get_ui_data(xfer); data->in_list = TRUE; finch_xfer_dialog_show(); @@ -340,7 +337,7 @@ g_return_if_fail(xfer_dialog != NULL); g_return_if_fail(xfer != NULL); - data = FINCHXFER(xfer); + data = purple_xfer_get_ui_data(xfer); if (data == NULL) return; @@ -370,7 +367,7 @@ g_return_if_fail(xfer_dialog != NULL); g_return_if_fail(xfer != NULL); - data = FINCHXFER(xfer); + data = purple_xfer_get_ui_data(xfer); if (data == NULL) return; @@ -416,7 +413,7 @@ g_return_if_fail(xfer_dialog != NULL); g_return_if_fail(xfer != NULL); - if ((data = FINCHXFER(xfer)) == NULL) + if ((data = purple_xfer_get_ui_data(xfer)) == NULL) return; if (data->in_list == FALSE || data->notified) @@ -471,9 +468,9 @@ { PurpleGntXferUiData *data; - /* This is where we're setting xfer->ui_data for the first time. */ + /* This is where we're setting xfer's "ui_data" for the first time. */ data = g_new0(PurpleGntXferUiData, 1); - FINCH_SET_DATA(xfer, data); + purple_xfer_set_ui_data(xfer, data); } static void @@ -481,11 +478,11 @@ { PurpleGntXferUiData *data; - data = FINCHXFER(xfer); + data = purple_xfer_get_ui_data(xfer); if (data) { g_free(data->name); g_free(data); - FINCH_SET_DATA(xfer, NULL); + purple_xfer_set_ui_data(xfer, NULL); } } diff -r 9aee8493db7f -r ac6353ffa129 finch/gntnotify.c --- a/finch/gntnotify.c Mon Aug 22 11:20:05 2011 +0900 +++ b/finch/gntnotify.c Mon Aug 29 12:28:49 2011 +0900 @@ -290,7 +290,7 @@ text = g_string_new(""); - for (l = purple_notify_user_info_get_entries(user_info); l != NULL; + for (l = purple_notify_user_info_get_entries(user_info)->head; l != NULL; l = l->next) { PurpleNotifyUserInfoEntry *user_info_entry = l->data; PurpleNotifyUserInfoEntryType type = purple_notify_user_info_entry_get_type(user_info_entry); diff -r 9aee8493db7f -r ac6353ffa129 finch/gntrequest.c --- a/finch/gntrequest.c Mon Aug 22 11:20:05 2011 +0900 +++ b/finch/gntrequest.c Mon Aug 29 12:28:49 2011 +0900 @@ -41,12 +41,6 @@ #include "debug.h" #include "util.h" -/* XXX: Until gobjectification ... */ -#undef FINCH_GET_DATA -#undef FINCH_SET_DATA -#define FINCH_GET_DATA(obj) purple_request_field_get_ui_data(obj) -#define FINCH_SET_DATA(obj, data) purple_request_field_set_ui_data(obj, data) - typedef struct { void *user_data; @@ -323,26 +317,26 @@ continue; if (type == PURPLE_REQUEST_FIELD_BOOLEAN) { - GntWidget *check = FINCH_GET_DATA(field); + GntWidget *check = purple_request_field_get_ui_data(field); gboolean value = gnt_check_box_get_checked(GNT_CHECK_BOX(check)); purple_request_field_bool_set_value(field, value); } else if (type == PURPLE_REQUEST_FIELD_STRING) { - GntWidget *entry = FINCH_GET_DATA(field); + GntWidget *entry = purple_request_field_get_ui_data(field); const char *text = gnt_entry_get_text(GNT_ENTRY(entry)); purple_request_field_string_set_value(field, (text && *text) ? text : NULL); } else if (type == PURPLE_REQUEST_FIELD_INTEGER) { - GntWidget *entry = FINCH_GET_DATA(field); + GntWidget *entry = purple_request_field_get_ui_data(field); const char *text = gnt_entry_get_text(GNT_ENTRY(entry)); int value = (text && *text) ? atoi(text) : 0; purple_request_field_int_set_value(field, value); } else if (type == PURPLE_REQUEST_FIELD_CHOICE) { - GntWidget *combo = FINCH_GET_DATA(field); + GntWidget *combo = purple_request_field_get_ui_data(field); int id; id = GPOINTER_TO_INT(gnt_combo_box_get_selected_data(GNT_COMBO_BOX(combo))); purple_request_field_choice_set_value(field, id); @@ -352,7 +346,7 @@ GList *list = NULL, *iter; if (purple_request_field_list_get_multi_select(field)) { - GntWidget *tree = FINCH_GET_DATA(field); + GntWidget *tree = purple_request_field_get_ui_data(field); iter = purple_request_field_list_get_items(field); for (; iter; iter = iter->next) @@ -365,7 +359,7 @@ } else { - GntWidget *combo = FINCH_GET_DATA(field); + GntWidget *combo = purple_request_field_get_ui_data(field); gpointer data = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(combo)); iter = purple_request_field_list_get_items(field); @@ -384,7 +378,7 @@ } else if (type == PURPLE_REQUEST_FIELD_ACCOUNT) { - GntWidget *combo = FINCH_GET_DATA(field); + GntWidget *combo = purple_request_field_get_ui_data(field); PurpleAccount *acc = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(combo)); purple_request_field_account_set_value(field, acc); } @@ -633,36 +627,36 @@ if (type == PURPLE_REQUEST_FIELD_BOOLEAN) { - FINCH_SET_DATA(field, create_boolean_field(field)); + purple_request_field_set_ui_data(field, create_boolean_field(field)); } else if (type == PURPLE_REQUEST_FIELD_STRING) { - FINCH_SET_DATA(field, create_string_field(field, &username)); + purple_request_field_set_ui_data(field, create_string_field(field, &username)); } else if (type == PURPLE_REQUEST_FIELD_INTEGER) { - FINCH_SET_DATA(field, create_integer_field(field)); + purple_request_field_set_ui_data(field, create_integer_field(field)); } else if (type == PURPLE_REQUEST_FIELD_CHOICE) { - FINCH_SET_DATA(field, create_choice_field(field)); + purple_request_field_set_ui_data(field, create_choice_field(field)); } else if (type == PURPLE_REQUEST_FIELD_LIST) { - FINCH_SET_DATA(field, create_list_field(field)); + purple_request_field_set_ui_data(field, create_list_field(field)); } else if (type == PURPLE_REQUEST_FIELD_ACCOUNT) { accountlist = create_account_field(field); - FINCH_SET_DATA(field, accountlist); + purple_request_field_set_ui_data(field, accountlist); } else { - FINCH_SET_DATA(field, gnt_label_new_with_format(_("Not implemented yet."), + purple_request_field_set_ui_data(field, gnt_label_new_with_format(_("Not implemented yet."), GNT_TEXT_FLAG_BOLD)); } gnt_box_set_alignment(GNT_BOX(hbox), GNT_ALIGN_MID); - gnt_box_add_widget(GNT_BOX(hbox), GNT_WIDGET(FINCH_GET_DATA(field))); + gnt_box_add_widget(GNT_BOX(hbox), GNT_WIDGET(purple_request_field_get_ui_data(field))); } if (grlist->next) gnt_box_add_widget(GNT_BOX(box), gnt_hline_new()); diff -r 9aee8493db7f -r ac6353ffa129 finch/gntroomlist.c --- a/finch/gntroomlist.c Mon Aug 22 11:20:05 2011 +0900 +++ b/finch/gntroomlist.c Mon Aug 29 12:28:49 2011 +0900 @@ -41,6 +41,7 @@ #define PREF_ROOT "/finch/roomlist" + /* Yes, just one roomlist at a time. Let's not get greedy. Aight? */ struct _FinchRoomlist { @@ -146,9 +147,9 @@ purple_roomlist_room_join(froomlist.roomlist, room); break; case PURPLE_ROOMLIST_ROOMTYPE_CATEGORY: - if (!room->expanded_once) { + if (!purple_roomlist_room_get_expanded_once(room)) { purple_roomlist_expand_category(froomlist.roomlist, room); - room->expanded_once = TRUE; + purple_roomlist_room_set_expanded_once(room, TRUE); } break; } @@ -343,7 +344,7 @@ static void fl_create(PurpleRoomlist *list) { - FINCH_SET_DATA(list, &froomlist); + purple_roomlist_set_ui_data(list, &froomlist); setup_roomlist(NULL); update_roomlist(list); } diff -r 9aee8493db7f -r ac6353ffa129 finch/libgnt/gntfilesel.h --- a/finch/libgnt/gntfilesel.h Mon Aug 22 11:20:05 2011 +0900 +++ b/finch/libgnt/gntfilesel.h Mon Aug 29 12:28:49 2011 +0900 @@ -81,7 +81,7 @@ void (*gnt_reserved4)(void); }; -typedef enum _GntFileType +typedef enum { GNT_FILE_REGULAR, GNT_FILE_DIR diff -r 9aee8493db7f -r ac6353ffa129 finch/libgnt/gntprogressbar.h --- a/finch/libgnt/gntprogressbar.h Mon Aug 22 11:20:05 2011 +0900 +++ b/finch/libgnt/gntprogressbar.h Mon Aug 29 12:28:49 2011 +0900 @@ -37,7 +37,7 @@ #define GNT_IS_PROGRESS_BAR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GNT_TYPE_PROGRESS_BAR)) #define GNT_PROGRESS_BAR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GNT_TYPE_PROGRESS_BAR, GntProgressBarClass)) -typedef enum _GntProgressBarOrientation +typedef enum { GNT_PROGRESS_LEFT_TO_RIGHT, GNT_PROGRESS_RIGHT_TO_LEFT, diff -r 9aee8493db7f -r ac6353ffa129 finch/libgnt/gnttree.h --- a/finch/libgnt/gnttree.h Mon Aug 22 11:20:05 2011 +0900 +++ b/finch/libgnt/gnttree.h Mon Aug 29 12:28:49 2011 +0900 @@ -47,7 +47,7 @@ typedef struct _GntTreeRow GntTreeRow; typedef struct _GntTreeCol GntTreeCol; -typedef enum _GntTreeColumnFlag { +typedef enum { GNT_TREE_COLUMN_INVISIBLE = 1 << 0, GNT_TREE_COLUMN_FIXED_SIZE = 1 << 1, GNT_TREE_COLUMN_BINARY_DATA = 1 << 2, diff -r 9aee8493db7f -r ac6353ffa129 finch/libgnt/gntwidget.h --- a/finch/libgnt/gntwidget.h Mon Aug 22 11:20:05 2011 +0900 +++ b/finch/libgnt/gntwidget.h Mon Aug 29 12:28:49 2011 +0900 @@ -49,7 +49,7 @@ typedef struct _GntWidgetPriv GntWidgetPriv; typedef struct _GntWidgetClass GntWidgetClass; -typedef enum _GntWidgetFlags +typedef enum { GNT_WIDGET_DESTROYING = 1 << 0, GNT_WIDGET_CAN_TAKE_FOCUS = 1 << 1, @@ -69,7 +69,7 @@ } GntWidgetFlags; /* XXX: This will probably move elsewhere */ -typedef enum _GntMouseEvent +typedef enum { GNT_LEFT_MOUSE_DOWN = 1, GNT_RIGHT_MOUSE_DOWN, @@ -80,7 +80,7 @@ } GntMouseEvent; /* XXX: I'll have to ask grim what he's using this for in guifications. */ -typedef enum _GntParamFlags +typedef enum { GNT_PARAM_SERIALIZABLE = 1 << G_PARAM_USER_SHIFT } GntParamFlags; diff -r 9aee8493db7f -r ac6353ffa129 finch/libgnt/gntwm.h --- a/finch/libgnt/gntwm.h Mon Aug 22 11:20:05 2011 +0900 +++ b/finch/libgnt/gntwm.h Mon Aug 29 12:28:49 2011 +0900 @@ -41,7 +41,7 @@ #define GNT_IS_WM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GNT_TYPE_WM)) #define GNT_WM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GNT_TYPE_WM, GntWMClass)) -typedef enum _GntKeyPressMode +typedef enum { GNT_KP_MODE_NORMAL, GNT_KP_MODE_RESIZE, diff -r 9aee8493db7f -r ac6353ffa129 finch/plugins/gntgf.c --- a/finch/plugins/gntgf.c Mon Aug 22 11:20:05 2011 +0900 +++ b/finch/plugins/gntgf.c Mon Aug 29 12:28:49 2011 +0900 @@ -168,7 +168,7 @@ beep(); if (conv != NULL) { - FinchConv *fc = conv->ui_data; + FinchConv *fc = FINCH_CONV(conv); if (gnt_widget_has_focus(fc->window)) return; } diff -r 9aee8493db7f -r ac6353ffa129 finch/plugins/lastlog.c --- a/finch/plugins/lastlog.c Mon Aug 22 11:20:05 2011 +0900 +++ b/finch/plugins/lastlog.c Mon Aug 29 12:28:49 2011 +0900 @@ -60,7 +60,7 @@ static PurpleCmdRet lastlog_cb(PurpleConversation *conv, const char *cmd, char **args, char **error, gpointer null) { - FinchConv *ggconv = conv->ui_data; + FinchConv *ggconv = FINCH_CONV(conv); char **strings = g_strsplit(GNT_TEXT_VIEW(ggconv->tv)->string->str, "\n", 0); GntWidget *win, *tv; int i, j; diff -r 9aee8493db7f -r ac6353ffa129 libpurple/cipher.h --- a/libpurple/cipher.h Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/cipher.h Mon Aug 29 12:28:49 2011 +0900 @@ -41,7 +41,7 @@ /** * Modes for batch encrypters */ -typedef enum _PurpleCipherBatchMode { +typedef enum { PURPLE_CIPHER_BATCH_MODE_ECB, PURPLE_CIPHER_BATCH_MODE_CBC } PurpleCipherBatchMode; @@ -49,7 +49,7 @@ /** * The operation flags for a cipher */ -typedef enum _PurpleCipherCaps { +typedef enum { PURPLE_CIPHER_CAPS_SET_OPT = 1 << 1, /**< Set option flag */ PURPLE_CIPHER_CAPS_GET_OPT = 1 << 2, /**< Get option flag */ PURPLE_CIPHER_CAPS_INIT = 1 << 3, /**< Init flag */ diff -r 9aee8493db7f -r ac6353ffa129 libpurple/cmds.h --- a/libpurple/cmds.h Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/cmds.h Mon Aug 29 12:28:49 2011 +0900 @@ -32,7 +32,7 @@ /*@{*/ /** The possible results of running a command with purple_cmd_do_command(). */ -typedef enum _PurpleCmdStatus { +typedef enum { PURPLE_CMD_STATUS_OK, PURPLE_CMD_STATUS_FAILED, PURPLE_CMD_STATUS_NOT_FOUND, @@ -48,7 +48,7 @@ * #PURPLE_CMD_RET_CONTINUE to cause the core to fall through to other * commands with the same name. */ -typedef enum _PurpleCmdRet { +typedef enum { PURPLE_CMD_RET_OK, /**< Everything's okay; Don't look for another command to call. */ PURPLE_CMD_RET_FAILED, /**< The command failed, but stop looking.*/ PURPLE_CMD_RET_CONTINUE /**< Continue, looking for other commands with the same name to call. */ @@ -68,7 +68,7 @@ */ typedef guint PurpleCmdId; -typedef enum _PurpleCmdPriority { +typedef enum { PURPLE_CMD_P_VERY_LOW = -1000, PURPLE_CMD_P_LOW = 0, PURPLE_CMD_P_DEFAULT = 1000, @@ -85,7 +85,7 @@ * * @see purple_cmd_register */ -typedef enum _PurpleCmdFlag { +typedef enum { /** Command is usable in IMs. */ PURPLE_CMD_FLAG_IM = 0x01, /** Command is usable in multi-user chats. */ diff -r 9aee8493db7f -r ac6353ffa129 libpurple/conversation.c --- a/libpurple/conversation.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/conversation.c Mon Aug 29 12:28:49 2011 +0900 @@ -2337,6 +2337,21 @@ return msg->when; } +void purple_conversation_set_ui_data(PurpleConversation *conv, gpointer ui_data) +{ + g_return_if_fail(conv != NULL); + + conv->ui_data = ui_data; +} + +gpointer purple_conversation_get_ui_data(const PurpleConversation *conv) +{ + g_return_val_if_fail(conv != NULL, NULL); + + return conv->ui_data; +} + + gboolean purple_conversation_do_command(PurpleConversation *conv, const gchar *cmdline, const gchar *markup, gchar **error) diff -r 9aee8493db7f -r ac6353ffa129 libpurple/conversation.h --- a/libpurple/conversation.h Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/conversation.h Mon Aug 29 12:28:49 2011 +0900 @@ -802,6 +802,25 @@ */ time_t purple_conversation_message_get_timestamp(PurpleConvMessage *msg); +/** + * Set the UI data associated with this conversation. + * + * @param conv The conversation. + * @param ui_data A pointer to associate with this conversation. + */ +void purple_conversation_set_ui_data(PurpleConversation *conv, gpointer ui_data); + +/** + * Get the UI data associated with this conversation. + * + * @param conv The conversation. + * + * @return The UI data associated with this conversation. This is a + * convenience field provided to the UIs--it is not + * used by the libpurple core. + */ +gpointer purple_conversation_get_ui_data(const PurpleConversation *conv); + /*@}*/ diff -r 9aee8493db7f -r ac6353ffa129 libpurple/dbus-server.c --- a/libpurple/dbus-server.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/dbus-server.c Mon Aug 29 12:28:49 2011 +0900 @@ -711,7 +711,7 @@ g_return_val_if_fail(ptr, TRUE); } - switch (purple_values[i]->type) + switch (purple_value_get_type(purple_values[i])) { case PURPLE_TYPE_INT: case PURPLE_TYPE_ENUM: diff -r 9aee8493db7f -r ac6353ffa129 libpurple/dnsquery.c --- a/libpurple/dnsquery.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/dnsquery.c Mon Aug 29 12:28:49 2011 +0900 @@ -297,6 +297,10 @@ } rc = read(child_in, &dns_params, sizeof(dns_params_t)); if (rc < 0) { + if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) { + /* Try again */ + continue; + } fprintf(stderr, "dns[%d]: Error: Could not read dns_params: " "%s\n", getpid(), strerror(errno)); break; diff -r 9aee8493db7f -r ac6353ffa129 libpurple/ft.c --- a/libpurple/ft.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/ft.c Mon Aug 29 12:28:49 2011 +0900 @@ -1701,6 +1701,37 @@ } } +void +purple_xfer_set_protocol_data(PurpleXfer *xfer, gpointer proto_data) +{ + g_return_if_fail(xfer != NULL); + + xfer->proto_data = proto_data; +} + +gpointer +purple_xfer_get_protocol_data(const PurpleXfer *xfer) +{ + g_return_val_if_fail(xfer != NULL, NULL); + + return xfer->proto_data; +} + +void purple_xfer_set_ui_data(PurpleXfer *xfer, gpointer ui_data) +{ + g_return_if_fail(xfer != NULL); + + xfer->ui_data = ui_data; +} + +gpointer purple_xfer_get_ui_data(const PurpleXfer *xfer) +{ + g_return_val_if_fail(xfer != NULL, NULL); + + return xfer->ui_data; +} + + /************************************************************************** * File Transfer Subsystem API **************************************************************************/ diff -r 9aee8493db7f -r ac6353ffa129 libpurple/ft.h --- a/libpurple/ft.h Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/ft.h Mon Aug 29 12:28:49 2011 +0900 @@ -185,7 +185,7 @@ PurpleXferUiOps *ui_ops; /**< UI-specific operations. */ void *ui_data; /**< UI-specific data. */ - void *data; /**< prpl-specific data. */ + void *proto_data; /**< prpl-specific data. */ }; #ifdef __cplusplus @@ -737,6 +737,45 @@ */ void purple_xfer_prepare_thumbnail(PurpleXfer *xfer, const gchar *formats); +/** + * Sets the protocol data for a file transfer. + * + * @param xfer The file transfer. + * @param protol_data The protocol data to set for the file transfer. + * + * @since 3.0.0 + */ +void purple_xfer_set_protocol_data(PurpleXfer *xfer, gpointer proto_data); + +/** + * Gets the protocol data for a file transfer. + * + * @param xfer The file transfer. + * + * @return The protocol data for the file transfer. + * + * @since 3.0.0 + */ +gpointer purple_xfer_get_protocol_data(const PurpleXfer *xfer); + +/** + * Set the UI data associated with this file transfer. + * + * @param xfer The file transfer. + * @param ui_data A pointer to associate with this file transfer. + */ +void purple_xfer_set_ui_data(PurpleXfer *xfer, gpointer ui_data); + +/** + * Get the UI data associated with this file transfer. + * + * @param xfer The file transfer. + * + * @return The UI data associated with this file transfer. This is a + * convenience field provided to the UIs--it is not + * used by the libpurple core. + */ +gpointer purple_xfer_get_ui_data(const PurpleXfer *xfer); /*@}*/ diff -r 9aee8493db7f -r ac6353ffa129 libpurple/notify.c --- a/libpurple/notify.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/notify.c Mon Aug 29 12:28:49 2011 +0900 @@ -53,7 +53,7 @@ struct _PurpleNotifyUserInfo { - GList *user_info_entries; + GQueue entries; }; void * @@ -457,7 +457,7 @@ user_info = g_new0(PurpleNotifyUserInfo, 1); PURPLE_DBUS_REGISTER_POINTER(user_info, PurpleNotifyUserInfo); - user_info->user_info_entries = NULL; + g_queue_init(&user_info->entries); return user_info; } @@ -467,23 +467,23 @@ { GList *l; - for (l = user_info->user_info_entries; l != NULL; l = l->next) { + for (l = user_info->entries.head; l != NULL; l = l->next) { PurpleNotifyUserInfoEntry *user_info_entry = l->data; purple_notify_user_info_entry_destroy(user_info_entry); } - g_list_free(user_info->user_info_entries); + g_queue_clear(&user_info->entries); PURPLE_DBUS_UNREGISTER_POINTER(user_info); g_free(user_info); } -GList * +GQueue * purple_notify_user_info_get_entries(PurpleNotifyUserInfo *user_info) { g_return_val_if_fail(user_info != NULL, NULL); - return user_info->user_info_entries; + return &user_info->entries; } char * @@ -494,7 +494,7 @@ text = g_string_new(""); - for (l = user_info->user_info_entries; l != NULL; l = l->next) { + for (l = user_info->entries.head; l != NULL; l = l->next) { PurpleNotifyUserInfoEntry *user_info_entry = l->data; /* Add a newline before a section header */ if (user_info_entry->type == PURPLE_NOTIFY_USER_INFO_ENTRY_SECTION_HEADER) @@ -578,33 +578,41 @@ } void -purple_notify_user_info_add_pair(PurpleNotifyUserInfo *user_info, const char *label, const char *value) +purple_notify_user_info_add_pair_html(PurpleNotifyUserInfo *user_info, const char *label, const char *value) { PurpleNotifyUserInfoEntry *entry; entry = purple_notify_user_info_entry_new(label, value); - user_info->user_info_entries = g_list_append(user_info->user_info_entries, entry); + g_queue_push_tail(&user_info->entries, entry); } void purple_notify_user_info_add_pair_plaintext(PurpleNotifyUserInfo *user_info, const char *label, const char *value) { gchar *escaped; - PurpleNotifyUserInfoEntry *entry; escaped = g_markup_escape_text(value, -1); - entry = purple_notify_user_info_entry_new(label, escaped); + purple_notify_user_info_add_pair_html(user_info, label, escaped); g_free(escaped); - user_info->user_info_entries = g_list_append(user_info->user_info_entries, entry); } void -purple_notify_user_info_prepend_pair(PurpleNotifyUserInfo *user_info, const char *label, const char *value) +purple_notify_user_info_prepend_pair_html(PurpleNotifyUserInfo *user_info, const char *label, const char *value) { PurpleNotifyUserInfoEntry *entry; entry = purple_notify_user_info_entry_new(label, value); - user_info->user_info_entries = g_list_prepend(user_info->user_info_entries, entry); + g_queue_push_head(&user_info->entries, entry); +} + +void +purple_notify_user_info_prepend_pair_plaintext(PurpleNotifyUserInfo *user_info, const char *label, const char *value) +{ + gchar *escaped; + + escaped = g_markup_escape_text(value, -1); + purple_notify_user_info_prepend_pair_html(user_info, label, escaped); + g_free(escaped); } void @@ -613,7 +621,7 @@ g_return_if_fail(user_info != NULL); g_return_if_fail(entry != NULL); - user_info->user_info_entries = g_list_remove(user_info->user_info_entries, entry); + g_queue_remove(&user_info->entries, entry); } void @@ -624,7 +632,7 @@ entry = purple_notify_user_info_entry_new(label, NULL); entry->type = PURPLE_NOTIFY_USER_INFO_ENTRY_SECTION_HEADER; - user_info->user_info_entries = g_list_append(user_info->user_info_entries, entry); + g_queue_push_tail(&user_info->entries, entry); } void @@ -635,7 +643,7 @@ entry = purple_notify_user_info_entry_new(label, NULL); entry->type = PURPLE_NOTIFY_USER_INFO_ENTRY_SECTION_HEADER; - user_info->user_info_entries = g_list_prepend(user_info->user_info_entries, entry); + g_queue_push_head(&user_info->entries, entry); } void @@ -646,7 +654,7 @@ entry = purple_notify_user_info_entry_new(NULL, NULL); entry->type = PURPLE_NOTIFY_USER_INFO_ENTRY_SECTION_BREAK; - user_info->user_info_entries = g_list_append(user_info->user_info_entries, entry); + g_queue_push_tail(&user_info->entries, entry); } void @@ -657,17 +665,17 @@ entry = purple_notify_user_info_entry_new(NULL, NULL); entry->type = PURPLE_NOTIFY_USER_INFO_ENTRY_SECTION_BREAK; - user_info->user_info_entries = g_list_prepend(user_info->user_info_entries, entry); + g_queue_push_head(&user_info->entries, entry); } void purple_notify_user_info_remove_last_item(PurpleNotifyUserInfo *user_info) { - GList *last = g_list_last(user_info->user_info_entries); - if (last) { - purple_notify_user_info_entry_destroy(last->data); - user_info->user_info_entries = g_list_delete_link(user_info->user_info_entries, last); - } + PurpleNotifyUserInfoEntry *entry; + + entry = g_queue_pop_tail(&user_info->entries); + if (entry) + purple_notify_user_info_entry_destroy(entry); } void * diff -r 9aee8493db7f -r ac6353ffa129 libpurple/notify.h --- a/libpurple/notify.h Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/notify.h Mon Aug 29 12:28:49 2011 +0900 @@ -439,20 +439,20 @@ * Retrieve the array of PurpleNotifyUserInfoEntry objects from a * PurpleNotifyUserInfo * - * This GList may be manipulated directly with normal GList functions such - * as g_list_insert(). Only PurpleNotifyUserInfoEntry are allowed in the - * list. If a PurpleNotifyUserInfoEntry item is added to the list, it - * should not be g_free()'d by the caller; PurpleNotifyUserInfo will g_free - * it when destroyed. + * This GQueue may be manipulated directly with normal GQueue functions such + * as g_queue_push_tail(). Only PurpleNotifyUserInfoEntry are allowed in the + * queue. If a PurpleNotifyUserInfoEntry item is added to the queue, it + * should not be freed by the caller; PurpleNotifyUserInfo will free it when + * destroyed. * * To remove a PurpleNotifyUserInfoEntry, use - * purple_notify_user_info_remove_entry(). Do not use the GList directly. + * purple_notify_user_info_remove_entry(). Do not use the GQueue directly. * * @param user_info The PurpleNotifyUserInfo * - * @constreturn A GList of PurpleNotifyUserInfoEntry objects + * @constreturn A GQueue of PurpleNotifyUserInfoEntry objects. */ -GList *purple_notify_user_info_get_entries(PurpleNotifyUserInfo *user_info); +GQueue *purple_notify_user_info_get_entries(PurpleNotifyUserInfo *user_info); /** * Create a textual representation of a PurpleNotifyUserInfo, separating @@ -480,34 +480,25 @@ * the UI should treat label as independent and not * include a colon if it would otherwise. */ -/* - * TODO: In 3.0.0 this function should be renamed to - * purple_notify_user_info_add_pair_html(). And optionally - * purple_notify_user_info_add_pair_plaintext() could be renamed to - * purple_notify_user_info_add_pair(). - */ -void purple_notify_user_info_add_pair(PurpleNotifyUserInfo *user_info, const char *label, const char *value); +void purple_notify_user_info_add_pair_html(PurpleNotifyUserInfo *user_info, const char *label, const char *value); /** - * Like purple_notify_user_info_add_pair, but value should be plaintext + * Like purple_notify_user_info_add_pair_html, but value should be plaintext * and will be escaped using g_markup_escape_text(). */ void purple_notify_user_info_add_pair_plaintext(PurpleNotifyUserInfo *user_info, const char *label, const char *value); /** - * Prepend a label/value pair to a PurpleNotifyUserInfo object - * - * @param user_info The PurpleNotifyUserInfo - * @param label A label, which for example might be displayed by a - * UI with a colon after it ("Status:"). Do not include - * a colon. If NULL, value will be displayed without a - * label. - * @param value The value, which might be displayed by a UI after - * the label. If NULL, label will still be displayed; - * the UI should then treat label as independent and not - * include a colon if it would otherwise. + * Like purple_notify_user_info_add_pair_html, but the pair is inserted + * at the beginning of the list. */ -void purple_notify_user_info_prepend_pair(PurpleNotifyUserInfo *user_info, const char *label, const char *value); +void purple_notify_user_info_prepend_pair_html(PurpleNotifyUserInfo *user_info, const char *label, const char *value); + +/** + * Like purple_notify_user_info_prepend_pair_html, but value should be plaintext + * and will be escaped using g_markup_escape_text(). + */ +void purple_notify_user_info_prepend_pair_plaintext(PurpleNotifyUserInfo *user_info, const char *label, const char *value); #if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_NOTIFY_C_) /** @@ -530,9 +521,11 @@ * * If added to a PurpleNotifyUserInfo object, this should not be free()'d, * as PurpleNotifyUserInfo will do so when destroyed. - * purple_notify_user_info_add_pair() and - * purple_notify_user_info_prepend_pair() are convenience methods for - * creating entries and adding them to a PurpleNotifyUserInfo. + * purple_notify_user_info_add_pair_html(), + * purple_notify_user_info_add_pair_plaintext(), + * purple_notify_user_info_prepend_pair_html() and + * purple_notify_user_info_prepend_pair_plaintext() are convenience + * methods for creating entries and adding them to a PurpleNotifyUserInfo. * * @param label A label, which for example might be displayed by a UI * with a colon after it ("Status:"). Do not include a diff -r 9aee8493db7f -r ac6353ffa129 libpurple/plugins/log_reader.c --- a/libpurple/plugins/log_reader.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/plugins/log_reader.c Mon Aug 29 12:28:49 2011 +0900 @@ -92,7 +92,7 @@ prpl_name = g_ascii_strup(prpl_info->list_icon(account, NULL), -1); - temp = g_strdup_printf("%s.%s", prpl_name, account->username); + temp = g_strdup_printf("%s.%s", prpl_name, purple_account_get_username(account)); path = g_build_filename(logdir, temp, sn, NULL); g_free(temp); @@ -635,7 +635,7 @@ g_return_val_if_fail(sn != NULL, NULL); g_return_val_if_fail(account != NULL, NULL); - if (strcmp(account->protocol_id, "prpl-msn")) + if (strcmp(purple_account_get_protocol_id(account), "prpl-msn")) return NULL; logdir = purple_prefs_get_string("/plugins/core/log_reader/msn/log_directory"); @@ -658,7 +658,7 @@ return list; } } else { - username = g_strdup(purple_normalize(account, account->username)); + username = g_strdup(purple_normalize(account, purple_account_get_username(account))); } if (buddy) { @@ -974,7 +974,7 @@ their_name = from_name; if (from_name && purple_prefs_get_bool("/plugins/core/log_reader/use_name_heuristics")) { - const char *friendly_name = purple_connection_get_display_name(log->account->gc); + const char *friendly_name = purple_connection_get_display_name(purple_account_get_connection(log->account)); if (friendly_name != NULL) { int friendly_name_length = strlen(friendly_name); @@ -987,13 +987,10 @@ if (buddy) their_name = purple_buddy_get_alias(buddy); - if (log->account->alias) - { - alias = log->account->alias; + alias = purple_account_get_alias(log->account); + if (alias) { alias_length = strlen(alias); - } - else - { + } else { alias = ""; alias_length = 0; } @@ -1115,10 +1112,10 @@ text = g_string_append(text, ""); if (name_guessed == NAME_GUESS_ME) { - if (log->account->alias) - text = g_string_append(text, log->account->alias); + if (purple_account_get_alias(log->account)) + text = g_string_append(text, purple_account_get_alias(log->account)); else - text = g_string_append(text, log->account->username); + text = g_string_append(text, purple_account_get_username(log->account)); } else if (name_guessed == NAME_GUESS_THEM) text = g_string_append(text, their_name); @@ -1781,7 +1778,7 @@ g_return_val_if_fail(account != NULL, NULL); /* QIP only supports ICQ. */ - if (strcmp(account->protocol_id, "prpl-icq")) + if (strcmp(purple_account_get_protocol_id(account), "prpl-icq")) return NULL; logdir = purple_prefs_get_string("/plugins/core/log_reader/qip/log_directory"); @@ -1798,7 +1795,7 @@ if (!prpl_info->list_icon) return NULL; - username = g_strdup(purple_normalize(account, account->username)); + username = g_strdup(purple_normalize(account, purple_account_get_username(account))); filename = g_strdup_printf("%s.txt", purple_normalize(account, sn)); path = g_build_filename(logdir, username, "History", filename, NULL); g_free(username); @@ -2241,10 +2238,10 @@ return NULL; /* aMSN only works with MSN/WLM */ - if (strcmp(account->protocol_id, "prpl-msn")) + if (strcmp(purple_account_get_protocol_id(account), "prpl-msn")) return NULL; - username = g_strdup(purple_normalize(account, account->username)); + username = g_strdup(purple_normalize(account, purple_account_get_username(account))); buddy_log = g_strdup_printf("%s.log", purple_normalize(account, sn)); log_path = g_build_filename(logdir, username, "logs", NULL); diff -r 9aee8493db7f -r ac6353ffa129 libpurple/plugins/perl/common/Notify.xs --- a/libpurple/plugins/perl/common/Notify.xs Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/plugins/perl/common/Notify.xs Mon Aug 29 12:28:49 2011 +0900 @@ -135,7 +135,7 @@ PREINIT: GList *l; PPCODE: - l = purple_notify_user_info_get_entries(user_info); + l = purple_notify_user_info_get_entries(user_info)->head; for (; l != NULL; l = l->next) { XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::NotifyUserInfoEntry"))); } @@ -145,12 +145,12 @@ Purple::NotifyUserInfo user_info const char *newline -void purple_notify_user_info_add_pair(user_info, label, value) +void purple_notify_user_info_add_pair_html(user_info, label, value) Purple::NotifyUserInfo user_info const char *label const char *value -void purple_notify_user_info_prepend_pair(user_info, label, value) +void purple_notify_user_info_prepend_pair_html(user_info, label, value) Purple::NotifyUserInfo user_info const char *label const char *value diff -r 9aee8493db7f -r ac6353ffa129 libpurple/pounce.c --- a/libpurple/pounce.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/pounce.c Mon Aug 29 12:28:49 2011 +0900 @@ -32,6 +32,31 @@ #include "pounce.h" #include "util.h" +/** + * A buddy pounce structure. + * + * Buddy pounces are actions triggered by a buddy-related event. For + * example, a sound can be played or an IM window opened when a buddy + * signs on or returns from away. Such responses are handled in the + * UI. The events themselves are done in the core. + */ +struct _PurplePounce +{ + char *ui_type; /**< The type of UI. */ + + PurplePounceEvent events; /**< The event(s) to pounce on. */ + PurplePounceOption options; /**< The pounce options */ + PurpleAccount *pouncer; /**< The user who is pouncing. */ + + char *pouncee; /**< The buddy to pounce on. */ + + GHashTable *actions; /**< The registered actions. */ + + gboolean save; /**< Whether or not the pounce should + be saved after activation. */ + void *data; /**< Pounce-specific data. */ +}; + typedef struct { GString *buffer; diff -r 9aee8493db7f -r ac6353ffa129 libpurple/pounce.h --- a/libpurple/pounce.h Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/pounce.h Mon Aug 29 12:28:49 2011 +0900 @@ -59,31 +59,6 @@ /** A pounce callback. */ typedef void (*PurplePounceCb)(PurplePounce *, PurplePounceEvent, void *); -/** - * A buddy pounce structure. - * - * Buddy pounces are actions triggered by a buddy-related event. For - * example, a sound can be played or an IM window opened when a buddy - * signs on or returns from away. Such responses are handled in the - * UI. The events themselves are done in the core. - */ -struct _PurplePounce -{ - char *ui_type; /**< The type of UI. */ - - PurplePounceEvent events; /**< The event(s) to pounce on. */ - PurplePounceOption options; /**< The pounce options */ - PurpleAccount *pouncer; /**< The user who is pouncing. */ - - char *pouncee; /**< The buddy to pounce on. */ - - GHashTable *actions; /**< The registered actions. */ - - gboolean save; /**< Whether or not the pounce should - be saved after activation. */ - void *data; /**< Pounce-specific data. */ -}; - #ifdef __cplusplus extern "C" { #endif diff -r 9aee8493db7f -r ac6353ffa129 libpurple/prefs.h --- a/libpurple/prefs.h Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/prefs.h Mon Aug 29 12:28:49 2011 +0900 @@ -32,7 +32,7 @@ /** * Preference data types. */ -typedef enum _PurplePrefType +typedef enum { PURPLE_PREF_NONE, /**< No type. */ PURPLE_PREF_BOOLEAN, /**< Boolean. */ diff -r 9aee8493db7f -r ac6353ffa129 libpurple/privacy.h --- a/libpurple/privacy.h Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/privacy.h Mon Aug 29 12:28:49 2011 +0900 @@ -29,7 +29,7 @@ /** * Privacy data types. */ -typedef enum _PurplePrivacyType +typedef enum { PURPLE_PRIVACY_ALLOW_ALL = 1, PURPLE_PRIVACY_DENY_ALL, diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/Makefile.am --- a/libpurple/protocols/Makefile.am Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/protocols/Makefile.am Mon Aug 29 12:28:49 2011 +0900 @@ -1,5 +1,5 @@ EXTRA_DIST = Makefile.mingw -DIST_SUBDIRS = bonjour gg irc jabber msn myspace mxit novell null oscar sametime silc silc10 simple yahoo zephyr +DIST_SUBDIRS = bonjour gg irc jabber msn myspace mxit novell null oscar sametime silc simple yahoo zephyr SUBDIRS = $(DYNAMIC_PRPLS) $(STATIC_PRPLS) diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/bonjour/bonjour.c --- a/libpurple/protocols/bonjour/bonjour.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/protocols/bonjour/bonjour.c Mon Aug 29 12:28:49 2011 +0900 @@ -371,9 +371,12 @@ else status_description = purple_status_get_name(status); - purple_notify_user_info_add_pair(user_info, _("Status"), status_description); - if (message != NULL) - purple_notify_user_info_add_pair(user_info, _("Message"), message); + purple_notify_user_info_add_pair_plaintext(user_info, _("Status"), status_description); + if (message != NULL) { + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("Message"), message); + } if (bb == NULL) { purple_debug_error("bonjour", "Got tooltip request for a buddy without protocol data.\n"); @@ -382,20 +385,35 @@ /* Only show first/last name if there is a nickname set (to avoid duplication) */ if (bb->nick != NULL && *bb->nick != '\0') { - if (bb->first != NULL && *bb->first != '\0') - purple_notify_user_info_add_pair(user_info, _("First name"), bb->first); - if (bb->last != NULL && *bb->last != '\0') - purple_notify_user_info_add_pair(user_info, _("Last name"), bb->last); + if (bb->first != NULL && *bb->first != '\0') { + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("First name"), bb->first); + } + if (bb->last != NULL && *bb->last != '\0') { + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("Last name"), bb->last); + } } - if (bb->email != NULL && *bb->email != '\0') - purple_notify_user_info_add_pair(user_info, _("Email"), bb->email); + if (bb->email != NULL && *bb->email != '\0') { + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("Email"), bb->email); + } - if (bb->AIM != NULL && *bb->AIM != '\0') - purple_notify_user_info_add_pair(user_info, _("AIM Account"), bb->AIM); + if (bb->AIM != NULL && *bb->AIM != '\0') { + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("AIM Account"), bb->AIM); + } - if (bb->jid != NULL && *bb->jid != '\0') - purple_notify_user_info_add_pair(user_info, _("XMPP Account"), bb->jid); + if (bb->jid != NULL && *bb->jid != '\0') { + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("XMPP Account"), bb->jid); + } } static void diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/bonjour/bonjour_ft.c --- a/libpurple/protocols/bonjour/bonjour_ft.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/protocols/bonjour/bonjour_ft.c Mon Aug 29 12:28:49 2011 +0900 @@ -90,7 +90,7 @@ static void bonjour_xfer_request_denied(PurpleXfer *xfer) { - XepXfer *xf = xfer->data; + XepXfer *xf = purple_xfer_get_protocol_data(xfer); purple_debug_info("bonjour", "Bonjour-xfer-request-denied.\n"); @@ -162,7 +162,7 @@ xfer = xfers->data; if(xfer == NULL) break; - xf = xfer->data; + xf = purple_xfer_get_protocol_data(xfer); if(xf == NULL) break; if(xf->sid && xfer->who && !strcmp(xf->sid, sid) && @@ -180,7 +180,7 @@ { xmlnode *si_node, *feature, *field, *file, *x; XepIq *iq; - XepXfer *xf = xfer->data; + XepXfer *xf = purple_xfer_get_protocol_data(xfer); BonjourData *bd = NULL; char buf[32]; @@ -249,7 +249,7 @@ if(!to || !xfer) return; - xf = xfer->data; + xf = purple_xfer_get_protocol_data(xfer); if(!xf) return; @@ -292,7 +292,7 @@ purple_debug_info("bonjour", "bonjour-free-xfer-%p.\n", xfer); - xf = (XepXfer*)xfer->data; + xf = purple_xfer_get_protocol_data(xfer); if(xf != NULL) { BonjourData *bd = (BonjourData*)xf->data; if(bd != NULL) { @@ -311,7 +311,7 @@ g_free(xf->buddy_ip); g_free(xf->sid); g_free(xf); - xfer->data = NULL; + purple_xfer_set_protocol_data(xfer, NULL); } purple_debug_info("bonjour", "Need close socket=%d.\n", xfer->fd); @@ -334,7 +334,8 @@ /* Build the file transfer handle */ xfer = purple_xfer_new(gc->account, PURPLE_XFER_SEND, who); - xfer->data = xep_xfer = g_new0(XepXfer, 1); + xep_xfer = g_new0(XepXfer, 1); + purple_xfer_set_protocol_data(xfer, xep_xfer); xep_xfer->data = bd; purple_debug_info("bonjour", "Bonjour-new-xfer bd=%p data=%p.\n", bd, xep_xfer->data); @@ -379,7 +380,7 @@ BonjourBuddy *bb; XepXfer *xf; - xf = (XepXfer*)xfer->data; + xf = purple_xfer_get_protocol_data(xfer); if(xf == NULL) return; @@ -530,7 +531,7 @@ int portnum; XepXfer *xf = NULL; - xf = (XepXfer*)xfer->data; + xf = purple_xfer_get_protocol_data(xfer); for(streamhost = xmlnode_get_child(query, "streamhost"); streamhost; streamhost = xmlnode_get_next_twin(streamhost)) { @@ -592,7 +593,8 @@ /* Build the file transfer handle */ xfer = purple_xfer_new(pc->account, PURPLE_XFER_RECEIVE, from); - xfer->data = xf = g_new0(XepXfer, 1); + xf = g_new0(XepXfer, 1); + purple_xfer_set_protocol_data(xfer, xf); xf->data = bd; purple_xfer_set_filename(xfer, filename); xf->iq_id = g_strdup(id); @@ -614,7 +616,7 @@ bonjour_sock5_request_cb(gpointer data, gint source, PurpleInputCondition cond) { PurpleXfer *xfer = data; - XepXfer *xf = xfer->data; + XepXfer *xf = purple_xfer_get_protocol_data(xfer); int acceptfd; int len = 0; @@ -759,7 +761,7 @@ xfer->watcher = purple_input_add(sock, PURPLE_INPUT_READ, bonjour_sock5_request_cb, xfer); - xf = (XepXfer*)xfer->data; + xf = purple_xfer_get_protocol_data(xfer); xf->listen_data = NULL; bd = xf->data; @@ -797,7 +799,7 @@ return; purple_debug_info("bonjour", "Bonjour-bytestreams-init.\n"); - xf = xfer->data; + xf = purple_xfer_get_protocol_data(xfer); purple_network_listen_map_external(FALSE); xf->listen_data = purple_network_listen_range(0, 0, SOCK_STREAM, @@ -813,7 +815,7 @@ bonjour_bytestreams_connect_cb(gpointer data, gint source, const gchar *error_message) { PurpleXfer *xfer = data; - XepXfer *xf = xfer->data; + XepXfer *xf = purple_xfer_get_protocol_data(xfer); XepIq *iq; xmlnode *q_node, *tmp_node; BonjourData *bd; @@ -862,7 +864,7 @@ purple_debug_info("bonjour", "bonjour-bytestreams-connect.\n"); - xf = (XepXfer*)xfer->data; + xf = purple_xfer_get_protocol_data(xfer); if(!xf) return; diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/bonjour/jabber.c --- a/libpurple/protocols/bonjour/jabber.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/protocols/bonjour/jabber.c Mon Aug 29 12:28:49 2011 +0900 @@ -929,7 +929,8 @@ while(tmp) { ip = tmp->data; if (ip != NULL && g_ascii_strcasecmp(ip, bconv->ip) == 0) { - BonjourJabber *jdata = ((BonjourData*) bconv->account->gc->proto_data)->jabber_data; + PurpleConnection *pc = purple_account_get_connection(bconv->account); + BonjourJabber *jdata = ((BonjourData *)pc->proto_data)->jabber_data; purple_debug_info("bonjour", "Matched buddy %s to incoming conversation \"from\" attrib and IP (%s)\n", purple_buddy_get_name(pb), bconv->ip); @@ -962,7 +963,8 @@ void bonjour_jabber_conv_match_by_ip(BonjourJabberConversation *bconv) { - BonjourJabber *jdata = ((BonjourData*) bconv->account->gc->proto_data)->jabber_data; + PurpleConnection *pc = purple_account_get_connection(bconv->account); + BonjourJabber *jdata = ((BonjourData *)pc->proto_data)->jabber_data; struct _match_buddies_by_address_t *mbba; GSList *buddies; @@ -1122,7 +1124,8 @@ void async_bonjour_jabber_close_conversation(BonjourJabberConversation *bconv) { - BonjourJabber *jdata = ((BonjourData*) bconv->account->gc->proto_data)->jabber_data; + PurpleConnection *pc = purple_account_get_connection(bconv->account); + BonjourJabber *jdata = ((BonjourData *)pc->proto_data)->jabber_data; jdata->pending_conversations = g_slist_remove(jdata->pending_conversations, bconv); @@ -1142,8 +1145,9 @@ if (bconv != NULL) { BonjourData *bd = NULL; - if(PURPLE_CONNECTION_IS_VALID(bconv->account->gc)) { - bd = bconv->account->gc->proto_data; + PurpleConnection *pc = purple_account_get_connection(bconv->account); + if (PURPLE_CONNECTION_IS_VALID(pc)) { + bd = pc->proto_data; bd->jabber_data->pending_conversations = g_slist_remove(bd->jabber_data->pending_conversations, bconv); } @@ -1215,7 +1219,7 @@ purple_input_remove(jdata->watcher_id6); /* Close all the conversation sockets and remove all the watchers after sending end streams */ - if (jdata->account->gc != NULL) { + if (!purple_account_is_disconnected(jdata->account)) { GSList *buddies, *l; buddies = purple_find_buddies(jdata->account, NULL); diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/bonjour/mdns_types.h --- a/libpurple/protocols/bonjour/mdns_types.h Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/protocols/bonjour/mdns_types.h Mon Aug 29 12:28:49 2011 +0900 @@ -37,7 +37,7 @@ gchar *msg; } BonjourDnsSd; -typedef enum _PublishType { +typedef enum { PUBLISH_START, PUBLISH_UPDATE } PublishType; diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/gg/buddylist.c --- a/libpurple/protocols/gg/buddylist.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/protocols/gg/buddylist.c Mon Aug 29 12:28:49 2011 +0900 @@ -90,7 +90,7 @@ gchar **data_tbl; gchar *name, *show, *g; - if (strlen(users_tbl[i]) == 0) + if (!*users_tbl[i]) continue; data_tbl = g_strsplit(users_tbl[i], ";", 8); diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/gg/gg.c --- a/libpurple/protocols/gg/gg.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/protocols/gg/gg.c Mon Aug 29 12:28:49 2011 +0900 @@ -1194,27 +1194,37 @@ val = ggp_search_get_result(req, 0, GG_PUBDIR50_STATUS); /* XXX: Use of ggp_str_to_uin() is an ugly hack! */ - purple_notify_user_info_add_pair(user_info, _("Status"), ggp_status_by_id(ggp_str_to_uin(val))); + purple_notify_user_info_add_pair_plaintext(user_info, _("Status"), ggp_status_by_id(ggp_str_to_uin(val))); g_free(val); who = ggp_search_get_result(req, 0, GG_PUBDIR50_UIN); - purple_notify_user_info_add_pair(user_info, _("UIN"), who); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("UIN"), who); val = ggp_search_get_result(req, 0, GG_PUBDIR50_FIRSTNAME); - purple_notify_user_info_add_pair(user_info, _("First Name"), val); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("First Name"), val); g_free(val); val = ggp_search_get_result(req, 0, GG_PUBDIR50_NICKNAME); - purple_notify_user_info_add_pair(user_info, _("Nickname"), val); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("Nickname"), val); g_free(val); val = ggp_search_get_result(req, 0, GG_PUBDIR50_CITY); - purple_notify_user_info_add_pair(user_info, _("City"), val); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("City"), val); g_free(val); val = ggp_search_get_result(req, 0, GG_PUBDIR50_BIRTHYEAR); if (strncmp(val, "0", 1)) { - purple_notify_user_info_add_pair(user_info, _("Birth Year"), val); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("Birth Year"), val); } g_free(val); @@ -1225,15 +1235,12 @@ if (NULL != buddy) { PurpleStatus *status; const char *msg; - char *text; status = purple_presence_get_active_status(purple_buddy_get_presence(buddy)); msg = purple_status_get_attr_string(status, "message"); if (msg != NULL) { - text = g_markup_escape_text(msg, -1); - purple_notify_user_info_add_pair(user_info, _("Message"), text); - g_free(text); + purple_notify_user_info_add_pair_plaintext(user_info, _("Message"), msg); } } @@ -1975,7 +1982,7 @@ static void ggp_tooltip_text(PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboolean full) { PurpleStatus *status; - char *text, *tmp; + char *tmp; const char *msg, *name, *alias; g_return_if_fail(b != NULL); @@ -1985,21 +1992,19 @@ name = purple_status_get_name(status); alias = purple_buddy_get_alias(b); - purple_notify_user_info_add_pair (user_info, _("Alias"), alias); + purple_notify_user_info_add_pair_plaintext(user_info, _("Alias"), alias); if (msg != NULL) { - text = g_markup_escape_text(msg, -1); if (PURPLE_BUDDY_IS_ONLINE(b)) { - tmp = g_strdup_printf("%s: %s", name, text); - purple_notify_user_info_add_pair(user_info, _("Status"), tmp); + tmp = g_strdup_printf("%s: %s", name, msg); + purple_notify_user_info_add_pair_plaintext(user_info, _("Status"), tmp); g_free(tmp); } else { - purple_notify_user_info_add_pair(user_info, _("Message"), text); + purple_notify_user_info_add_pair_plaintext(user_info, _("Message"), msg); } - g_free(text); /* We don't want to duplicate 'Status: Offline'. */ } else if (PURPLE_BUDDY_IS_ONLINE(b)) { - purple_notify_user_info_add_pair(user_info, _("Status"), name); + purple_notify_user_info_add_pair_plaintext(user_info, _("Status"), name); } } @@ -2030,7 +2035,7 @@ NULL); types = g_list_append(types, type); - /* + /* * New statuses for GG 8.0 like PoGGadaj ze mna (not yet because * libpurple can't support Chatty status) and Nie przeszkadzac */ diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/irc/dcc_send.c --- a/libpurple/protocols/irc/dcc_send.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/protocols/irc/dcc_send.c Mon Aug 29 12:28:49 2011 +0900 @@ -38,7 +38,7 @@ static void irc_dccsend_recv_destroy(PurpleXfer *xfer) { - struct irc_xfer_rx_data *xd = xfer->data; + struct irc_xfer_rx_data *xd = purple_xfer_get_protocol_data(xfer); g_free(xd->ip); g_free(xd); @@ -62,7 +62,7 @@ } static void irc_dccsend_recv_init(PurpleXfer *xfer) { - struct irc_xfer_rx_data *xd = xfer->data; + struct irc_xfer_rx_data *xd = purple_xfer_get_protocol_data(xfer); purple_xfer_start(xfer, -1, xd->ip, xfer->remote_port); g_free(xd->ip); @@ -114,7 +114,7 @@ if (xfer) { xd = g_new0(struct irc_xfer_rx_data, 1); - xfer->data = xd; + purple_xfer_set_protocol_data(xfer, xd); purple_xfer_set_filename(xfer, filename->str); xfer->remote_port = atoi(token[i+1]); @@ -157,7 +157,7 @@ static void irc_dccsend_send_destroy(PurpleXfer *xfer) { - struct irc_xfer_send_data *xd = xfer->data; + struct irc_xfer_send_data *xd = purple_xfer_get_protocol_data(xfer); if (xd == NULL) return; @@ -178,7 +178,7 @@ static void irc_dccsend_send_read(gpointer data, int source, PurpleInputCondition cond) { PurpleXfer *xfer = data; - struct irc_xfer_send_data *xd = xfer->data; + struct irc_xfer_send_data *xd = purple_xfer_get_protocol_data(xfer); char buffer[64]; int len; @@ -244,7 +244,7 @@ static void irc_dccsend_send_connected(gpointer data, int source, PurpleInputCondition cond) { PurpleXfer *xfer = (PurpleXfer *) data; - struct irc_xfer_send_data *xd = xfer->data; + struct irc_xfer_send_data *xd = purple_xfer_get_protocol_data(xfer); int conn, flags; conn = accept(xd->fd, NULL, 0); @@ -285,7 +285,7 @@ struct in_addr addr; unsigned short int port; - xd = xfer->data; + xd = purple_xfer_get_protocol_data(xfer); xd->listen_data = NULL; if (purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_CANCEL_LOCAL @@ -294,7 +294,7 @@ return; } - xd = xfer->data; + xd = purple_xfer_get_protocol_data(xfer); gc = purple_account_get_connection(purple_xfer_get_account(xfer)); irc = gc->proto_data; @@ -331,7 +331,7 @@ */ static void irc_dccsend_send_init(PurpleXfer *xfer) { PurpleConnection *gc = purple_account_get_connection(purple_xfer_get_account(xfer)); - struct irc_xfer_send_data *xd = xfer->data; + struct irc_xfer_send_data *xd = purple_xfer_get_protocol_data(xfer); xfer->filename = g_path_get_basename(xfer->local_filename); @@ -359,7 +359,7 @@ { xd = g_new0(struct irc_xfer_send_data, 1); xd->fd = -1; - xfer->data = xd; + purple_xfer_set_protocol_data(xfer, xd); /* Setup our I/O op functions */ purple_xfer_set_init_fnc(xfer, irc_dccsend_send_init); diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/irc/irc.c --- a/libpurple/protocols/irc/irc.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/protocols/irc/irc.c Mon Aug 29 12:28:49 2011 +0900 @@ -890,7 +890,8 @@ static void irc_roomlist_cancel(PurpleRoomlist *list) { - PurpleConnection *gc = purple_account_get_connection(list->account); + PurpleAccount *account = purple_roomlist_get_account(list); + PurpleConnection *gc = purple_account_get_connection(account); struct irc_conn *irc; if (gc == NULL) diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/irc/msgs.c --- a/libpurple/protocols/irc/msgs.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/protocols/irc/msgs.c Mon Aug 29 12:28:49 2011 +0900 @@ -352,7 +352,7 @@ tmp = g_strdup_printf("%s%s%s", tmp2, (irc->whois.ircop ? _(" (ircop)") : ""), (irc->whois.identified ? _(" (identified)") : "")); - purple_notify_user_info_add_pair(user_info, _("Nick"), tmp); + purple_notify_user_info_add_pair_html(user_info, _("Nick"), tmp); g_free(tmp2); g_free(tmp); diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/jabber/buddy.c --- a/libpurple/protocols/jabber/buddy.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/protocols/jabber/buddy.c Mon Aug 29 12:28:49 2011 +0900 @@ -731,11 +731,16 @@ g_strdup_printf("%s%s%s", jbr->client.name, (jbr->client.version ? " " : ""), (jbr->client.version ? jbr->client.version : "")); - purple_notify_user_info_prepend_pair(user_info, _("Client"), tmp); + /* TODO: Check whether it's correct to call prepend_pair_html, + or if we should be using prepend_pair_plaintext */ + purple_notify_user_info_prepend_pair_html(user_info, _("Client"), tmp); g_free(tmp); - if (jbr->client.os) - purple_notify_user_info_prepend_pair(user_info, _("Operating System"), jbr->client.os); + if (jbr->client.os) { + /* TODO: Check whether it's correct to call prepend_pair_html, + or if we should be using prepend_pair_plaintext */ + purple_notify_user_info_prepend_pair_html(user_info, _("Operating System"), jbr->client.os); + } } if (jbr && jbr->tz_off != PURPLE_NO_TZ_OFF) { @@ -751,13 +756,13 @@ jbr->tz_off < 0 ? '-' : '+', abs(jbr->tz_off / (60*60)), abs((jbr->tz_off % (60*60)) / 60)); - purple_notify_user_info_prepend_pair(user_info, _("Local Time"), timestamp); + purple_notify_user_info_prepend_pair_plaintext(user_info, _("Local Time"), timestamp); g_free(timestamp); } if (jbir && jbir->idle_seconds > 0) { char *idle = purple_str_seconds_to_string(jbir->idle_seconds); - purple_notify_user_info_prepend_pair(user_info, _("Idle"), idle); + purple_notify_user_info_prepend_pair_plaintext(user_info, _("Idle"), idle); g_free(idle); } @@ -779,15 +784,15 @@ tmp = g_strdup_printf("%s%s%s", (status_name ? status_name : ""), ((status_name && purdy) ? ": " : ""), (purdy ? purdy : "")); - purple_notify_user_info_prepend_pair(user_info, _("Status"), tmp); + purple_notify_user_info_prepend_pair_html(user_info, _("Status"), tmp); g_snprintf(priority, sizeof(priority), "%d", jbr->priority); - purple_notify_user_info_prepend_pair(user_info, _("Priority"), priority); + purple_notify_user_info_prepend_pair_plaintext(user_info, _("Priority"), priority); g_free(tmp); g_free(purdy); } else { - purple_notify_user_info_prepend_pair(user_info, _("Status"), _("Unknown")); + purple_notify_user_info_prepend_pair_plaintext(user_info, _("Status"), _("Unknown")); } } @@ -806,7 +811,7 @@ resource_name = jabber_get_resource(jbi->jid); /* If we have one or more pairs from the vcard, put a section break above it */ - if (purple_notify_user_info_get_entries(user_info)) + if (g_queue_get_length(purple_notify_user_info_get_entries(user_info))) purple_notify_user_info_prepend_section_break(user_info); /* Add the information about the user's resource(s) */ @@ -827,8 +832,11 @@ add_jbr_info(jbi, jbr->name, jbr); - if (jbr->name) - purple_notify_user_info_prepend_pair(user_info, _("Resource"), jbr->name); + if (jbr->name) { + /* TODO: Check whether it's correct to call prepend_pair_html, + or if we should be using prepend_pair_plaintext */ + purple_notify_user_info_prepend_pair_html(user_info, _("Resource"), jbr->name); + } } } @@ -848,7 +856,7 @@ title = _("Logged Off"); message = g_strdup_printf(_("%s ago"), last); } - purple_notify_user_info_prepend_pair(user_info, title, message); + purple_notify_user_info_prepend_pair_plaintext(user_info, title, message); g_free(last); g_free(message); } @@ -858,7 +866,9 @@ g_strdup_printf("%s%s%s", _("Offline"), jbi->last_message ? ": " : "", jbi->last_message ? jbi->last_message : ""); - purple_notify_user_info_prepend_pair(user_info, _("Status"), status); + /* TODO: Check whether it's correct to call prepend_pair_html, + or if we should be using prepend_pair_plaintext */ + purple_notify_user_info_prepend_pair_html(user_info, _("Status"), status); g_free(status); } } @@ -1136,7 +1146,7 @@ char *mailto; escaped = g_markup_escape_text(userid, -1); mailto = g_strdup_printf("%s", escaped, escaped); - purple_notify_user_info_add_pair(user_info, _("Email"), mailto); + purple_notify_user_info_add_pair_html(user_info, _("Email"), mailto); g_free(mailto); g_free(escaped); @@ -1149,7 +1159,7 @@ escaped = g_markup_escape_text(userid, -1); mailto = g_strdup_printf("%s", escaped, escaped); - purple_notify_user_info_add_pair(user_info, _("Email"), mailto); + purple_notify_user_info_add_pair_html(user_info, _("Email"), mailto); g_free(mailto); g_free(escaped); @@ -1196,7 +1206,7 @@ jbi->vcard_imgids = g_slist_prepend(jbi->vcard_imgids, GINT_TO_POINTER(purple_imgstore_add_with_id(g_memdup(data, size), size, "logo.png"))); img_text = g_strdup_printf("", GPOINTER_TO_INT(jbi->vcard_imgids->data)); - purple_notify_user_info_add_pair(user_info, (photo ? _("Photo") : _("Logo")), img_text); + purple_notify_user_info_add_pair_html(user_info, (photo ? _("Photo") : _("Logo")), img_text); hash = jabber_calculate_data_hash(data, size, "sha1"); purple_buddy_icons_set_for_user(account, bare_jid, data, size, hash); diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/jabber/chat.c --- a/libpurple/protocols/jabber/chat.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/protocols/jabber/chat.c Mon Aug 29 12:28:49 2011 +0900 @@ -887,8 +887,8 @@ char *jabber_roomlist_room_serialize(PurpleRoomlistRoom *room) { - - return g_strdup_printf("%s@%s", (char*)room->fields->data, (char*)room->fields->next->data); + GList *fields = purple_roomlist_room_get_fields(room); + return g_strdup_printf("%s@%s", (char*)fields->data, (char*)fields->next->data); } PurpleRoomlist *jabber_roomlist_get_list(PurpleConnection *gc) @@ -928,10 +928,12 @@ void jabber_roomlist_cancel(PurpleRoomlist *list) { + PurpleAccount *account; PurpleConnection *gc; JabberStream *js; - gc = purple_account_get_connection(list->account); + account = purple_roomlist_get_account(list); + gc = purple_account_get_connection(account); js = gc->proto_data; purple_roomlist_set_in_progress(list, FALSE); diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/jabber/jabber.c --- a/libpurple/protocols/jabber/jabber.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/protocols/jabber/jabber.c Mon Aug 29 12:28:49 2011 +0900 @@ -2227,7 +2227,7 @@ label = g_strdup_printf("%s%s", _("Status"), (res ? res : "")); value = g_strdup_printf("%s%s%s", state, (text ? ": " : ""), (text ? text : "")); - purple_notify_user_info_add_pair(user_info, label, value); + purple_notify_user_info_add_pair_html(user_info, label, value); g_free(label); g_free(value); g_free(text); @@ -2312,10 +2312,10 @@ char *moodplustext = g_strdup_printf("%s (%s)", description ? _(description) : mood, moodtext); - purple_notify_user_info_add_pair(user_info, _("Mood"), moodplustext); + purple_notify_user_info_add_pair_html(user_info, _("Mood"), moodplustext); g_free(moodplustext); } else - purple_notify_user_info_add_pair(user_info, _("Mood"), + purple_notify_user_info_add_pair_html(user_info, _("Mood"), description ? _(description) : mood); } if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_TUNE)) { @@ -2326,7 +2326,7 @@ char *playing = purple_util_format_song_info(title, artist, album, NULL); if (playing) { - purple_notify_user_info_add_pair(user_info, _("Now Listening"), playing); + purple_notify_user_info_add_pair_html(user_info, _("Now Listening"), playing); g_free(playing); } } @@ -2347,12 +2347,12 @@ sub = _("None"); } - purple_notify_user_info_add_pair(user_info, _("Subscription"), sub); + purple_notify_user_info_add_pair_html(user_info, _("Subscription"), sub); } if(!PURPLE_BUDDY_IS_ONLINE(b) && jb->error_msg) { - purple_notify_user_info_add_pair(user_info, _("Error"), jb->error_msg); + purple_notify_user_info_add_pair_html(user_info, _("Error"), jb->error_msg); } } } diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/jabber/oob.c --- a/libpurple/protocols/jabber/oob.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/protocols/jabber/oob.c Mon Aug 29 12:28:49 2011 +0900 @@ -48,13 +48,13 @@ static void jabber_oob_xfer_init(PurpleXfer *xfer) { - JabberOOBXfer *jox = xfer->data; + JabberOOBXfer *jox = purple_xfer_get_protocol_data(xfer); purple_xfer_start(xfer, -1, jox->address, jox->port); } static void jabber_oob_xfer_free(PurpleXfer *xfer) { - JabberOOBXfer *jox = xfer->data; + JabberOOBXfer *jox = purple_xfer_get_protocol_data(xfer); jox->js->oob_file_transfers = g_list_remove(jox->js->oob_file_transfers, xfer); @@ -67,12 +67,12 @@ purple_input_remove(jox->writeh); g_free(jox); - xfer->data = NULL; + purple_xfer_set_protocol_data(xfer, NULL); } static void jabber_oob_xfer_end(PurpleXfer *xfer) { - JabberOOBXfer *jox = xfer->data; + JabberOOBXfer *jox = purple_xfer_get_protocol_data(xfer); JabberIq *iq; iq = jabber_iq_new(jox->js, JABBER_IQ_RESULT); @@ -86,7 +86,7 @@ static void jabber_oob_xfer_request_send(gpointer data, gint source, PurpleInputCondition cond) { PurpleXfer *xfer = data; - JabberOOBXfer *jox = xfer->data; + JabberOOBXfer *jox = purple_xfer_get_protocol_data(xfer); int len, total_len = strlen(jox->write_buffer); len = write(xfer->fd, jox->write_buffer + jox->written_len, @@ -110,7 +110,7 @@ static void jabber_oob_xfer_start(PurpleXfer *xfer) { - JabberOOBXfer *jox = xfer->data; + JabberOOBXfer *jox = purple_xfer_get_protocol_data(xfer); if(jox->write_buffer == NULL) { jox->write_buffer = g_strdup_printf( @@ -126,7 +126,7 @@ } static gssize jabber_oob_xfer_read(guchar **buffer, PurpleXfer *xfer) { - JabberOOBXfer *jox = xfer->data; + JabberOOBXfer *jox = purple_xfer_get_protocol_data(xfer); char test[2048]; char *tmp, *lenstr; int len; @@ -158,7 +158,7 @@ } static void jabber_oob_xfer_recv_error(PurpleXfer *xfer, const char *code) { - JabberOOBXfer *jox = xfer->data; + JabberOOBXfer *jox = purple_xfer_get_protocol_data(xfer); JabberIq *iq; xmlnode *y, *z; @@ -221,7 +221,7 @@ xfer = purple_xfer_new(js->gc->account, PURPLE_XFER_RECEIVE, from); if (xfer) { - xfer->data = jox; + purple_xfer_set_protocol_data(xfer, jox); if(!(filename = g_strdup(g_strrstr(jox->page, "/")))) filename = g_strdup(jox->page); diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/jabber/si.c --- a/libpurple/protocols/jabber/si.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/protocols/jabber/si.c Mon Aug 29 12:28:49 2011 +0900 @@ -89,7 +89,7 @@ for(xfers = js->file_transfers; xfers; xfers = xfers->next) { PurpleXfer *xfer = xfers->data; - JabberSIXfer *jsx = xfer->data; + JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer); if(jsx->stream_id && xfer->who && !strcmp(jsx->stream_id, sid) && !strcmp(xfer->who, from)) return xfer; @@ -120,7 +120,7 @@ jabber_si_bytestreams_connect_cb(gpointer data, gint source, const gchar *error_message) { PurpleXfer *xfer = data; - JabberSIXfer *jsx = xfer->data; + JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer); JabberIq *iq; xmlnode *query, *su; JabberBytestreamsStreamhost *streamhost = jsx->streamhosts->data; @@ -176,7 +176,7 @@ connect_timeout_cb(gpointer data) { PurpleXfer *xfer = data; - JabberSIXfer *jsx = xfer->data; + JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer); purple_debug_info("jabber", "Streamhost connection timeout of %d seconds exceeded.\n", STREAMHOST_CONNECT_TIMEOUT); @@ -205,7 +205,7 @@ jabber_si_bytestreams_ibb_timeout_cb(gpointer data) { PurpleXfer *xfer = (PurpleXfer *) data; - JabberSIXfer *jsx = xfer->data; + JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer); if (jsx && !jsx->ibb_session) { purple_debug_info("jabber", @@ -220,7 +220,7 @@ static void jabber_si_bytestreams_attempt_connect(PurpleXfer *xfer) { - JabberSIXfer *jsx = xfer->data; + JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer); JabberBytestreamsStreamhost *streamhost; JabberID *dstjid; @@ -339,7 +339,7 @@ if(!(xfer = jabber_si_xfer_find(js, sid, from))) return; - jsx = xfer->data; + jsx = purple_xfer_get_protocol_data(xfer); if(!jsx->accepted) return; @@ -377,7 +377,7 @@ PurpleInputCondition cond) { PurpleXfer *xfer = data; - JabberSIXfer *jsx = xfer->data; + JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer); int len; len = write(source, jsx->rxqueue + jsx->rxlen, jsx->rxmaxlen - jsx->rxlen); @@ -414,7 +414,7 @@ PurpleInputCondition cond) { PurpleXfer *xfer = data; - JabberSIXfer *jsx = xfer->data; + JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer); char buffer[42]; /* 40 for DST.ADDR + 2 bytes for port number*/ int len; char *dstaddr, *hash; @@ -529,7 +529,7 @@ PurpleInputCondition cond) { PurpleXfer *xfer = data; - JabberSIXfer *jsx = xfer->data; + JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer); int len; len = write(source, jsx->rxqueue + jsx->rxlen, jsx->rxmaxlen - jsx->rxlen); @@ -570,7 +570,7 @@ PurpleInputCondition cond) { PurpleXfer *xfer = data; - JabberSIXfer *jsx = xfer->data; + JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer); int i; int len; char buffer[256]; @@ -682,7 +682,7 @@ PurpleInputCondition cond) { PurpleXfer *xfer = data; - JabberSIXfer *jsx = xfer->data; + JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer); int acceptfd, flags; purple_debug_info("jabber", "in jabber_si_xfer_bytestreams_send_connected_cb\n"); @@ -729,12 +729,12 @@ return; } + jsx = purple_xfer_get_protocol_data(xfer); + /* In the case of a direct file transfer, this is expected to return */ - if(!xfer->data) + if(!jsx) return; - jsx = xfer->data; - if(type != JABBER_IQ_RESULT) { purple_debug_info("jabber", "jabber_si_xfer_connect_proxy_cb: type = error\n"); @@ -837,7 +837,7 @@ JabberBytestreamsStreamhost *sh, *sh2; int streamhost_count = 0; - jsx = xfer->data; + jsx = purple_xfer_get_protocol_data(xfer); jsx->listen_data = NULL; /* I'm not sure under which conditions this can happen @@ -971,7 +971,7 @@ purple_xfer_ref(xfer); - jsx = xfer->data; + jsx = purple_xfer_get_protocol_data(xfer); /* TODO: This should probably be done with an account option instead of * piggy-backing on the TOR proxy type. */ @@ -1019,7 +1019,7 @@ gsize size) { PurpleXfer *xfer = (PurpleXfer *) jabber_ibb_session_get_user_data(sess); - JabberSIXfer *jsx = (JabberSIXfer *) xfer->data; + JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer); if (size <= purple_xfer_get_bytes_remaining(xfer)) { purple_debug_info("jabber", "about to write %" G_GSIZE_FORMAT " bytes from IBB stream\n", @@ -1039,7 +1039,7 @@ static gssize jabber_si_xfer_ibb_read(guchar **out_buffer, PurpleXfer *xfer) { - JabberSIXfer *jsx = xfer->data; + JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer); guchar *buffer; gsize size; gsize tmp; @@ -1062,7 +1062,7 @@ const gchar *sid = xmlnode_get_attrib(open, "sid"); PurpleXfer *xfer = jabber_si_xfer_find(js, sid, who); if (xfer) { - JabberSIXfer *jsx = (JabberSIXfer *) xfer->data; + JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer); JabberIBBSession *sess = jabber_ibb_session_create_from_xmlnode(js, who, id, open, xfer); @@ -1107,7 +1107,7 @@ static gssize jabber_si_xfer_ibb_write(const guchar *buffer, size_t len, PurpleXfer *xfer) { - JabberSIXfer *jsx = (JabberSIXfer *) xfer->data; + JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer); JabberIBBSession *sess = jsx->ibb_session; gsize packet_size = len < jabber_ibb_session_get_max_data_size(sess) ? len : jabber_ibb_session_get_max_data_size(sess); @@ -1151,7 +1151,7 @@ static void jabber_si_xfer_ibb_send_init(JabberStream *js, PurpleXfer *xfer) { - JabberSIXfer *jsx = (JabberSIXfer *) xfer->data; + JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer); jsx->ibb_session = jabber_ibb_session_create(js, jsx->stream_id, purple_xfer_get_remote_user(xfer), xfer); @@ -1208,7 +1208,7 @@ for(field = xmlnode_get_child(x, "field"); field; field = xmlnode_get_next_twin(field)) { const char *var = xmlnode_get_attrib(field, "var"); - JabberSIXfer *jsx = (JabberSIXfer *) xfer->data; + JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer); if(var && !strcmp(var, "stream-method")) { if((value = xmlnode_get_child(field, "value"))) { @@ -1239,7 +1239,7 @@ static void jabber_si_xfer_send_request(PurpleXfer *xfer) { - JabberSIXfer *jsx = xfer->data; + JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer); JabberIq *iq; xmlnode *si, *file, *feature, *x, *field, *option, *value; char buf[32]; @@ -1322,7 +1322,7 @@ static void jabber_si_xfer_free(PurpleXfer *xfer) { - JabberSIXfer *jsx = xfer->data; + JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer); if (jsx) { JabberStream *js = jsx->js; @@ -1369,7 +1369,7 @@ /* XXX: free other stuff */ g_free(jsx->rxqueue); g_free(jsx); - xfer->data = NULL; + purple_xfer_set_protocol_data(xfer, NULL); } } @@ -1380,7 +1380,7 @@ */ static void jabber_si_xfer_cancel_send(PurpleXfer *xfer) { - JabberSIXfer *jsx = (JabberSIXfer *) xfer->data; + JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer); /* if there is an IBB session active, send close on that */ if (jsx->ibb_session) { @@ -1393,7 +1393,7 @@ static void jabber_si_xfer_request_denied(PurpleXfer *xfer) { - JabberSIXfer *jsx = (JabberSIXfer *) xfer->data; + JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer); JabberStream *js = jsx->js; /* @@ -1425,7 +1425,7 @@ static void jabber_si_xfer_cancel_recv(PurpleXfer *xfer) { - JabberSIXfer *jsx = (JabberSIXfer *) xfer->data; + JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer); /* if there is an IBB session active, send close */ if (jsx->ibb_session) { jabber_ibb_session_close(jsx->ibb_session); @@ -1445,7 +1445,7 @@ JabberCapabilities capabilities, gpointer data) { PurpleXfer *xfer = (PurpleXfer *) data; - JabberSIXfer *jsx = (JabberSIXfer *) xfer->data; + JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer); if (capabilities & JABBER_CAP_IBB) { purple_debug_info("jabber", @@ -1471,7 +1471,7 @@ static void do_transfer_send(PurpleXfer *xfer, const char *resource) { - JabberSIXfer *jsx = xfer->data; + JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer); char **who_v = g_strsplit(xfer->who, "/", 2); char *who; JabberBuddy *jb; @@ -1521,7 +1521,7 @@ static void jabber_si_xfer_init(PurpleXfer *xfer) { - JabberSIXfer *jsx = xfer->data; + JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer); JabberIq *iq; if(purple_xfer_get_type(xfer) == PURPLE_XFER_SEND) { JabberBuddy *jb; @@ -1654,7 +1654,8 @@ xfer = purple_xfer_new(gc->account, PURPLE_XFER_SEND, who); if (xfer) { - xfer->data = jsx = g_new0(JabberSIXfer, 1); + jsx = g_new0(JabberSIXfer, 1); + purple_xfer_set_protocol_data(xfer, jsx); jsx->js = js; jsx->local_streamhost_fd = -1; @@ -1790,7 +1791,7 @@ xfer = purple_xfer_new(js->gc->account, PURPLE_XFER_RECEIVE, from); g_return_if_fail(xfer != NULL); - xfer->data = jsx; + purple_xfer_set_protocol_data(xfer, jsx); purple_xfer_set_filename(xfer, filename); if(filesize > 0) diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/jabber/win32/posix.uname.c --- a/libpurple/protocols/jabber/win32/posix.uname.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/protocols/jabber/win32/posix.uname.c Mon Aug 29 12:28:49 2011 +0900 @@ -28,6 +28,8 @@ #include #include +#include + /* ANONYMOUS unions and structs are used from the windows header definitions. These need to be defined for them to work correctly with gcc2.95.2-mingw. */ /*#define _ANONYMOUS_STRUCT*/ diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/msn/msn.c --- a/libpurple/protocols/msn/msn.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/protocols/msn/msn.c Mon Aug 29 12:28:49 2011 +0900 @@ -896,7 +896,7 @@ static void t_msn_xfer_cancel_send(PurpleXfer *xfer) { - MsnSlpLink *slplink = xfer->data; + MsnSlpLink *slplink = purple_xfer_get_protocol_data(xfer); msn_slplink_unref(slplink); } @@ -912,7 +912,7 @@ g_return_val_if_fail(xfer != NULL, NULL); - xfer->data = msn_slplink_ref(msn_session_get_slplink(session, who)); + purple_xfer_set_protocol_data(xfer, msn_slplink_ref(msn_session_get_slplink(session, who))); purple_xfer_set_init_fnc(xfer, t_msn_xfer_init); purple_xfer_set_cancel_send_fnc(xfer, t_msn_xfer_cancel_send); @@ -1105,7 +1105,7 @@ if (psm != NULL && *psm) { purple_notify_user_info_add_pair_plaintext(user_info, tmp2, psm); } else { - purple_notify_user_info_add_pair(user_info, _("Status"), tmp2); + purple_notify_user_info_add_pair_html(user_info, _("Status"), tmp2); } g_free(tmp2); @@ -1118,17 +1118,17 @@ } } else { if (purple_presence_is_idle(presence)) { - purple_notify_user_info_add_pair(user_info, _("Status"), - _("Idle")); + purple_notify_user_info_add_pair_plaintext(user_info, + _("Status"), _("Idle")); } else { - purple_notify_user_info_add_pair(user_info, _("Status"), - purple_status_get_name(status)); + purple_notify_user_info_add_pair_plaintext(user_info, + _("Status"), purple_status_get_name(status)); } } } if (currentmedia) { - purple_notify_user_info_add_pair(user_info, mediatype, currentmedia); + purple_notify_user_info_add_pair_html(user_info, mediatype, currentmedia); g_free(currentmedia); } } @@ -1146,23 +1146,26 @@ { const char *phone; - purple_notify_user_info_add_pair(user_info, _("Has you"), + purple_notify_user_info_add_pair_plaintext(user_info, _("Has you"), ((user->list_op & (1 << MSN_LIST_RL)) ? _("Yes") : _("No"))); - purple_notify_user_info_add_pair(user_info, _("Blocked"), + purple_notify_user_info_add_pair_plaintext(user_info, _("Blocked"), ((user->list_op & (1 << MSN_LIST_BL)) ? _("Yes") : _("No"))); phone = msn_user_get_home_phone(user); - if (phone != NULL) - purple_notify_user_info_add_pair(user_info, _("Home Phone Number"), phone); + if (phone != NULL) { + purple_notify_user_info_add_pair_plaintext(user_info, _("Home Phone Number"), phone); + } phone = msn_user_get_work_phone(user); - if (phone != NULL) - purple_notify_user_info_add_pair(user_info, _("Work Phone Number"), phone); + if (phone != NULL) { + purple_notify_user_info_add_pair_plaintext(user_info, _("Work Phone Number"), phone); + } phone = msn_user_get_mobile_phone(user); - if (phone != NULL) - purple_notify_user_info_add_pair(user_info, _("Mobile Phone Number"), phone); + if (phone != NULL) { + purple_notify_user_info_add_pair_plaintext(user_info, _("Mobile Phone Number"), phone); + } } } @@ -2294,7 +2297,7 @@ { char *nicktext = g_markup_escape_text(alias, -1); tmp = g_strdup_printf("%s", nicktext); - purple_notify_user_info_add_pair(user_info, _("Nickname"), tmp); + purple_notify_user_info_add_pair_html(user_info, _("Nickname"), tmp); g_free(tmp); g_free(nicktext); } @@ -2393,7 +2396,7 @@ if (error_message != NULL || url_text == NULL || strcmp(url_text, "") == 0) { - purple_notify_user_info_add_pair(user_info, + purple_notify_user_info_add_pair_html(user_info, _("Error retrieving profile"), NULL); purple_notify_userinfo(info_data->gc, info_data->name, user_info, NULL, NULL); @@ -2712,7 +2715,7 @@ if (user_url != NULL) { tmp = g_strdup_printf("%s", user_url, user_url); - purple_notify_user_info_add_pair(user_info, _("Homepage"), tmp); + purple_notify_user_info_add_pair_html(user_info, _("Homepage"), tmp); g_free(tmp); g_free(user_url); @@ -2735,9 +2738,9 @@ char *p = strstr(url_buffer, "
gc), info_data->name); - purple_notify_user_info_add_pair(user_info, + purple_notify_user_info_add_pair_html(user_info, _("Error retrieving profile"), NULL); - purple_notify_user_info_add_pair(user_info, NULL, + purple_notify_user_info_add_pair_plaintext(user_info, NULL, ((p && b) ? _("The user has not created a public profile.") : (p ? _("MSN reported not being able to find the user's profile. " "This either means that the user does not exist, " @@ -2752,7 +2755,7 @@ purple_notify_user_info_add_section_break(user_info); tmp = g_strdup_printf("%s", PROFILE_URL, info_data->name, _("View web profile")); - purple_notify_user_info_add_pair(user_info, NULL, tmp); + purple_notify_user_info_add_pair_html(user_info, NULL, tmp); g_free(tmp); #if PHOTO_SUPPORT @@ -2833,7 +2836,7 @@ purple_debug_info("msn", "%s is %" G_GSIZE_FORMAT " bytes\n", photo_url_text, len); id = purple_imgstore_add_with_id(g_memdup(url_text, len), len, NULL); g_snprintf(buf, sizeof(buf), "
", id); - purple_notify_user_info_prepend_pair(user_info, NULL, buf); + purple_notify_user_info_prepend_pair_html(user_info, NULL, buf); } } diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/msn/sbconn.c --- a/libpurple/protocols/msn/sbconn.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/protocols/msn/sbconn.c Mon Aug 29 12:28:49 2011 +0900 @@ -121,6 +121,8 @@ } #endif } + } else { + msn_transaction_set_saveable(trans, FALSE); } trans->payload = payload; diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/msn/slp.c --- a/libpurple/protocols/msn/slp.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/protocols/msn/slp.c Mon Aug 29 12:28:49 2011 +0900 @@ -364,7 +364,7 @@ fn = purple_xfer_get_filename(xfer); fp = purple_xfer_get_local_filename(xfer); - slplink = xfer->data; + slplink = purple_xfer_get_protocol_data(xfer); g_return_if_fail(slplink != NULL); g_return_if_fail(fp != NULL); @@ -384,7 +384,7 @@ purple_xfer_set_read_fnc(xfer, msn_xfer_read); purple_xfer_set_write_fnc(xfer, msn_xfer_write); - xfer->data = slpcall; + purple_xfer_set_protocol_data(xfer, slpcall); context = gen_context(xfer, fn, fp); diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/msn/slpcall.c --- a/libpurple/protocols/msn/slpcall.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/protocols/msn/slpcall.c Mon Aug 29 12:28:49 2011 +0900 @@ -113,7 +113,7 @@ if (slpcall->xfer != NULL) { if (purple_xfer_get_type(slpcall->xfer) == PURPLE_XFER_RECEIVE) g_byte_array_free(slpcall->u.incoming_data, TRUE); - slpcall->xfer->data = NULL; + purple_xfer_set_protocol_data(slpcall->xfer, NULL); purple_xfer_unref(slpcall->xfer); } @@ -550,7 +550,7 @@ slpcall->xfer = xfer; purple_xfer_ref(slpcall->xfer); - xfer->data = slpcall; + purple_xfer_set_protocol_data(xfer, slpcall); if (file_context->preview) { purple_xfer_set_thumbnail(xfer, file_context->preview, diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/msn/slplink.c --- a/libpurple/protocols/msn/slplink.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/protocols/msn/slplink.c Mon Aug 29 12:28:49 2011 +0900 @@ -465,7 +465,7 @@ purple_xfer_ref(xfer); purple_xfer_start(xfer, -1, NULL, 0); - if (xfer->data == NULL) { + if (purple_xfer_get_protocol_data(xfer) == NULL) { purple_xfer_unref(xfer); msn_slpmsg_destroy(slpmsg); g_return_val_if_reached(NULL); diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/msn/xfer.c --- a/libpurple/protocols/msn/xfer.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/protocols/msn/xfer.c Mon Aug 29 12:28:49 2011 +0900 @@ -42,7 +42,7 @@ purple_debug_info("msn", "xfer_init\n"); - slpcall = xfer->data; + slpcall = purple_xfer_get_protocol_data(xfer); /* Send Ok */ content = g_strdup_printf("SessionID: %lu\r\n\r\n", @@ -62,9 +62,9 @@ char *content; g_return_if_fail(xfer != NULL); - g_return_if_fail(xfer->data != NULL); - slpcall = xfer->data; + slpcall = purple_xfer_get_protocol_data(xfer); + g_return_if_fail(slpcall != NULL); if (purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_CANCEL_LOCAL) { @@ -102,7 +102,7 @@ g_return_val_if_fail(purple_xfer_get_type(xfer) == PURPLE_XFER_SEND, -1); - slpcall = xfer->data; + slpcall = purple_xfer_get_protocol_data(xfer); /* Not sure I trust it'll be there */ g_return_val_if_fail(slpcall != NULL, -1); @@ -126,7 +126,7 @@ g_return_val_if_fail(purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE, -1); - slpcall = xfer->data; + slpcall = purple_xfer_get_protocol_data(xfer); /* Not sure I trust it'll be there */ g_return_val_if_fail(slpcall != NULL, -1); diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/mxit/actions.c --- a/libpurple/protocols/mxit/actions.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/protocols/mxit/actions.c Mon Aug 29 12:28:49 2011 +0900 @@ -43,7 +43,7 @@ */ static void mxit_profile_cb( PurpleConnection* gc, PurpleRequestFields* fields ) { - struct MXitSession* session = (struct MXitSession*) gc->proto_data; + struct MXitSession* session = purple_connection_get_protocol_data( gc ) ; PurpleRequestField* field = NULL; const char* name = NULL; const char* bday = NULL; @@ -84,13 +84,6 @@ g_string_append( attributes, attrib ); acount++; - /* force hidden if disabled */ - if ( profile->hidden == FALSE ) { - g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_HIDENUMBER, CP_PROFILE_TYPE_BOOL, "1" ); - g_string_append( attributes, attrib ); - acount++; - } - /* update birthday */ g_strlcpy( profile->birthday, bday, sizeof( profile->birthday ) ); g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_BIRTHDATE, CP_PROFILE_TYPE_UTF8, profile->birthday ); @@ -165,7 +158,7 @@ /* update where am i */ name = purple_request_fields_get_string( fields, "whereami" ); - if ( !name) + if ( !name ) profile->whereami[0] = '\0'; else g_strlcpy( profile->whereami, name, sizeof( profile->whereami ) ); @@ -207,7 +200,7 @@ static void mxit_profile_action( PurplePluginAction* action ) { PurpleConnection* gc = (PurpleConnection*) action->context; - struct MXitSession* session = (struct MXitSession*) gc->proto_data; + struct MXitSession* session = purple_connection_get_protocol_data( gc ); struct MXitProfile* profile = session->profile; PurpleRequestFields* fields = NULL; @@ -304,7 +297,7 @@ */ static void mxit_change_pin_cb( PurpleConnection* gc, PurpleRequestFields* fields ) { - struct MXitSession* session = (struct MXitSession*) gc->proto_data; + struct MXitSession* session = purple_connection_get_protocol_data( gc ); const char* pin = NULL; const char* pin2 = NULL; const char* err = NULL; @@ -366,7 +359,7 @@ static void mxit_change_pin_action( PurplePluginAction* action ) { PurpleConnection* gc = (PurpleConnection*) action->context; - struct MXitSession* session = (struct MXitSession*) gc->proto_data; + struct MXitSession* session = purple_connection_get_protocol_data( gc ); PurpleRequestFields* fields = NULL; PurpleRequestFieldGroup* group = NULL; @@ -375,8 +368,8 @@ purple_debug_info( MXIT_PLUGIN_ID, "mxit_change_pin_action\n" ); fields = purple_request_fields_new(); - group = purple_request_field_group_new(NULL); - purple_request_fields_add_group(fields, group); + group = purple_request_field_group_new( NULL ); + purple_request_fields_add_group( fields, group ); /* pin */ field = purple_request_field_string_new( "pin", _( "PIN" ), session->acc->password, FALSE ); @@ -402,7 +395,7 @@ static void mxit_splash_action( PurplePluginAction* action ) { PurpleConnection* gc = (PurpleConnection*) action->context; - struct MXitSession* session = (struct MXitSession*) gc->proto_data; + struct MXitSession* session = purple_connection_get_protocol_data( gc ); if ( splash_current( session ) != NULL ) splash_display( session ); @@ -439,7 +432,7 @@ static void mxit_suggested_friends_action( PurplePluginAction* action ) { PurpleConnection* gc = (PurpleConnection*) action->context; - struct MXitSession* session = (struct MXitSession*) gc->proto_data; + struct MXitSession* session = purple_connection_get_protocol_data( gc ); const char* profilelist[] = { CP_PROFILE_BIRTHDATE, CP_PROFILE_GENDER, CP_PROFILE_FULLNAME, CP_PROFILE_FIRSTNAME, CP_PROFILE_LASTNAME, CP_PROFILE_REGCOUNTRY, CP_PROFILE_STATUS, CP_PROFILE_AVATAR, @@ -456,7 +449,7 @@ */ static void mxit_user_search_cb( PurpleConnection *gc, const char *input ) { - struct MXitSession* session = (struct MXitSession*) gc->proto_data; + struct MXitSession* session = purple_connection_get_protocol_data( gc ); const char* profilelist[] = { CP_PROFILE_BIRTHDATE, CP_PROFILE_GENDER, CP_PROFILE_FULLNAME, CP_PROFILE_FIRSTNAME, CP_PROFILE_LASTNAME, CP_PROFILE_REGCOUNTRY, CP_PROFILE_STATUS, CP_PROFILE_AVATAR, @@ -479,10 +472,10 @@ _( "Search for a MXit contact" ), _( "Type search information" ), NULL, FALSE, FALSE, NULL, - _("_Search"), G_CALLBACK( mxit_user_search_cb ), - _("_Cancel"), NULL, + _( "_Search" ), G_CALLBACK( mxit_user_search_cb ), + _( "_Cancel" ), NULL, purple_connection_get_account( gc ), NULL, NULL, - gc); + gc ); } diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/mxit/cipher.c --- a/libpurple/protocols/mxit/cipher.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/protocols/mxit/cipher.c Mon Aug 29 12:28:49 2011 +0900 @@ -1,7 +1,7 @@ /* * MXit Protocol libPurple Plugin * - * -- user password encryption -- + * -- encryption -- * * Pieter Loubser * @@ -31,30 +31,69 @@ #include "aes.h" -/* password encryption */ +/* encryption */ #define INITIAL_KEY "6170383452343567" #define SECRET_HEADER "" +#define ENCRYPT_HEADER "" + + +/*------------------------------------------------------------------------ + * Add ISO10126 Padding to the data. + * + * @param data The data to pad. + */ +static void padding_add( GString* data ) +{ + unsigned int blocks = ( data->len / 16 ) + 1; + unsigned int padding = ( blocks * 16 ) - data->len; + + g_string_set_size( data, blocks * 16 ); + data->str[data->len - 1] = padding; +} /*------------------------------------------------------------------------ - * Pad the secret data using ISO10126 Padding. + * Remove ISO10126 Padding from the data. * - * @param secret The data to pad (caller must ensure buffer has enough space for padding) - * @return The total number of 128-bit blocks used + * @param data The data from which to remove padding. */ -static int pad_secret_data( char* secret ) +static void padding_remove( GString* data ) { - int blocks = 0; - int passlen; - int padding; + unsigned int padding; + + if ( data->len == 0 ) + return; + + padding = data->str[data->len - 1]; + g_string_truncate( data, data->len - padding ); +} + - passlen = strlen( secret ); - blocks = ( passlen / 16 ) + 1; - padding = ( blocks * 16 ) - passlen; - secret[passlen] = 0x50; - secret[(blocks * 16) - 1] = padding; +/*------------------------------------------------------------------------ + * Generate the Transport-Layer crypto key. + * (Note: this function is not-thread safe) + * + * @param session The MXit Session object + * @return The transport-layer crypto key. + */ +static char* transport_layer_key( struct MXitSession* session ) +{ + static char key[16 + 1]; + int passlen = strlen( session->acc->password ); - return blocks; + /* initialize with initial key */ + g_strlcpy( key, INITIAL_KEY, sizeof( key ) ); + + /* client key (8 bytes) */ + memcpy( key, session->clientkey, strlen( session->clientkey ) ); + + /* add last 8 characters of the PIN (no padding if less characters) */ + if ( passlen <= 8 ) + memcpy( key + 8, session->acc->password, passlen ); + else + memcpy( key + 8, session->acc->password + ( passlen - 8 ), 8 ); + + return key; } @@ -67,42 +106,131 @@ */ char* mxit_encrypt_password( struct MXitSession* session ) { - char key[64]; + char key[16 + 1]; char exkey[512]; - char pass[64]; + GString* pass = NULL; char encrypted[64]; char* base64; - int blocks; - int size; int i; purple_debug_info( MXIT_PLUGIN_ID, "mxit_encrypt_password\n" ); memset( encrypted, 0x00, sizeof( encrypted ) ); - memset( exkey, 0x00, sizeof( exkey ) ); - memset( pass, 0x58, sizeof( pass ) ); - pass[sizeof( pass ) - 1] = '\0'; - /* build the custom AES encryption key */ + /* build the AES encryption key */ g_strlcpy( key, INITIAL_KEY, sizeof( key ) ); memcpy( key, session->clientkey, strlen( session->clientkey ) ); ExpandKey( (unsigned char*) key, (unsigned char*) exkey ); - /* build the custom data to be encrypted */ - g_strlcpy( pass, SECRET_HEADER, sizeof( pass ) ); - strcat( pass, session->acc->password ); + /* build the secret data to be encrypted: SECRET_HEADER + password */ + pass = g_string_new( SECRET_HEADER ); + g_string_append( pass, session->acc->password ); + padding_add( pass ); /* add ISO10126 padding */ - /* pad the secret data */ - blocks = pad_secret_data( pass ); - size = blocks * 16; - - /* now encrypt the password. we encrypt each block separately (ECB mode) */ - for ( i = 0; i < size; i += 16 ) - Encrypt( (unsigned char*) pass + i, (unsigned char*) exkey, (unsigned char*) encrypted + i ); + /* now encrypt the secret. we encrypt each block separately (ECB mode) */ + for ( i = 0; i < pass->len; i += 16 ) + Encrypt( (unsigned char*) pass->str + i, (unsigned char*) exkey, (unsigned char*) encrypted + i ); /* now base64 encode the encrypted password */ - base64 = purple_base64_encode( (unsigned char*) encrypted, size ); + base64 = purple_base64_encode( (unsigned char*) encrypted, pass->len ); + + g_string_free( pass, TRUE ); return base64; } + +/*------------------------------------------------------------------------ + * Decrypt a message using transport-layer encryption. + * + * @param session The MXit session object + * @param message The encrypted message data (is base64-encoded). + * @return The decrypted message. Must be g_free'd when no longer needed. + */ +char* mxit_decrypt_message( struct MXitSession* session, char* message ) +{ + guchar* raw_message; + gsize raw_len; + char exkey[512]; + GString* decoded = NULL; + int i; + + /* remove optional header: */ + if ( strncmp( message, ENCRYPT_HEADER, strlen( ENCRYPT_HEADER ) ) == 0 ) + message += strlen( ENCRYPT_HEADER ); + + /* base64 decode the message */ + raw_message = purple_base64_decode( message, &raw_len ); + + /* build the AES key */ + ExpandKey( (unsigned char*) transport_layer_key( session ), (unsigned char*) exkey ); + + /* AES decrypt each block */ + decoded = g_string_sized_new( raw_len ); + for ( i = 0; i < raw_len; i += 16 ) { + char block[16]; + + Decrypt( (unsigned char*) raw_message + i, (unsigned char*) exkey, (unsigned char*) block ); + g_string_append_len( decoded, block, 16 ); + } + g_free( raw_message ); + + /* check that the decrypted message starts with header: */ + if ( strncmp( decoded->str, SECRET_HEADER, strlen( SECRET_HEADER ) != 0 ) ) { + g_string_free( decoded, TRUE ); + return NULL; /* message could not be decrypted */ + } + + /* remove ISO10126 padding */ + padding_remove( decoded ); + + /* remove encryption header */ + g_string_erase( decoded, 0, strlen( SECRET_HEADER ) ); + + return g_string_free( decoded, FALSE ); +} + + +/*------------------------------------------------------------------------ + * Encrypt a message using transport-layer encryption. + * + * @param session The MXit session object + * @param message The message data. + * @return The encrypted message. Must be g_free'd when no longer needed. + */ +char* mxit_encrypt_message( struct MXitSession* session, char* message ) +{ + GString* raw_message = NULL; + char exkey[512]; + GString* encoded = NULL; + gchar* base64; + int i; + + purple_debug_info( MXIT_PLUGIN_ID, "encrypt message: '%s'\n", message ); + + /* append encryption header to message data */ + raw_message = g_string_new( SECRET_HEADER ); + g_string_append( raw_message, message ); + padding_add( raw_message ); /* add ISO10126 padding */ + + /* build the AES key */ + ExpandKey( (unsigned char*) transport_layer_key( session ), (unsigned char*) exkey ); + + /* AES encrypt each block */ + encoded = g_string_sized_new( raw_message->len ); + for ( i = 0; i < raw_message->len; i += 16 ) { + char block[16]; + + Encrypt( (unsigned char*) raw_message->str + i, (unsigned char*) exkey, (unsigned char*) block ); + g_string_append_len( encoded, block, 16 ); + } + g_string_free( raw_message, TRUE ); + + /* base64 encode the encrypted message */ + base64 = purple_base64_encode( (unsigned char *) encoded->str, encoded->len ); + g_string_free( encoded, TRUE ); + + purple_debug_info( MXIT_PLUGIN_ID, "encrypted message: '%s'\n", base64 ); + + return base64; +} diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/mxit/cipher.h --- a/libpurple/protocols/mxit/cipher.h Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/protocols/mxit/cipher.h Mon Aug 29 12:28:49 2011 +0900 @@ -1,7 +1,7 @@ /* * MXit Protocol libPurple Plugin * - * -- user password encryption -- + * -- encryption -- * * Pieter Loubser * @@ -32,5 +32,7 @@ char* mxit_encrypt_password( struct MXitSession* session ); +char* mxit_decrypt_message( struct MXitSession* session, char* message ); +char* mxit_encrypt_message( struct MXitSession* session, char* message ); #endif /* _MXIT_CIPHER_H_ */ diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/mxit/filexfer.c --- a/libpurple/protocols/mxit/filexfer.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/protocols/mxit/filexfer.c Mon Aug 29 12:28:49 2011 +0900 @@ -97,11 +97,11 @@ */ static void mxit_xfer_free( PurpleXfer* xfer ) { - struct mxitxfer* mx = (struct mxitxfer*) xfer->data;; + struct mxitxfer* mx = purple_xfer_get_protocol_data( xfer ); if ( mx ) { + purple_xfer_set_protocol_data( xfer, NULL ); g_free( mx ); - xfer->data = NULL; } } @@ -117,7 +117,7 @@ */ static void mxit_xfer_init( PurpleXfer* xfer ) { - struct mxitxfer* mx = (struct mxitxfer*) xfer->data; + struct mxitxfer* mx = purple_xfer_get_protocol_data( xfer ); purple_debug_info( MXIT_PLUGIN_ID, "mxit_xfer_init\n" ); @@ -126,7 +126,7 @@ if ( purple_xfer_get_size( xfer ) > CP_MAX_FILESIZE ) { /* the file is too big */ - purple_xfer_error( xfer->type, xfer->account, xfer->who, _( "The file you are trying to send is too large!" ) ); + purple_xfer_error( purple_xfer_get_type( xfer ), purple_xfer_get_account( xfer ), purple_xfer_get_remote_user( xfer ), _( "The file you are trying to send is too large!" ) ); purple_xfer_cancel_local( xfer ); return; } @@ -151,6 +151,7 @@ */ static void mxit_xfer_start( PurpleXfer* xfer ) { + size_t filesize; unsigned char* buffer; int size; int wrote; @@ -163,10 +164,12 @@ * a buffer and copy the file data into memory and then we can send it to * the contact. we will send the whole file with one go. */ - buffer = g_malloc( xfer->bytes_remaining ); - size = fread( buffer, xfer->bytes_remaining, 1, xfer->dest_fp ); + filesize = purple_xfer_get_bytes_remaining( xfer ); + buffer = g_malloc( filesize ); + size = fread( buffer, filesize, 1, xfer->dest_fp ); + // TODO: If (size != 1) -> file read error - wrote = purple_xfer_write( xfer, buffer, xfer->bytes_remaining ); + wrote = purple_xfer_write( xfer, buffer, filesize ); if ( wrote > 0 ) purple_xfer_set_bytes_sent( xfer, wrote ); @@ -215,7 +218,7 @@ */ static gssize mxit_xfer_write( const guchar* buffer, size_t size, PurpleXfer* xfer ) { - struct mxitxfer* mx = (struct mxitxfer*) xfer->data; + struct mxitxfer* mx = purple_xfer_get_protocol_data( xfer ); purple_debug_info( MXIT_PLUGIN_ID, "mxit_xfer_write\n" ); @@ -245,7 +248,7 @@ */ static void mxit_xfer_request_denied( PurpleXfer* xfer ) { - struct mxitxfer* mx = (struct mxitxfer*) xfer->data; + struct mxitxfer* mx = purple_xfer_get_protocol_data( xfer ); purple_debug_info( MXIT_PLUGIN_ID, "mxit_xfer_request_denied\n" ); @@ -295,7 +298,7 @@ */ PurpleXfer* mxit_xfer_new( PurpleConnection* gc, const char* who ) { - struct MXitSession* session = (struct MXitSession*) gc->proto_data; + struct MXitSession* session = purple_connection_get_protocol_data( gc ); PurpleXfer* xfer = NULL; struct mxitxfer* mx = NULL; @@ -305,7 +308,7 @@ /* create file info and attach it to the file transfer */ mx = g_new0( struct mxitxfer, 1 ); mx->session = session; - xfer->data = mx; + purple_xfer_set_protocol_data( xfer, mx ); /* configure callbacks (reference: "libpurple/ft.h") */ purple_xfer_set_init_fnc( xfer, mxit_xfer_init ); @@ -362,7 +365,7 @@ mx = g_new0( struct mxitxfer, 1 ); mx->session = session; memcpy( mx->fileid, fileid, MXIT_CHUNK_FILEID_LEN ); - xfer->data = mx; + purple_xfer_set_protocol_data( xfer, mx ); purple_xfer_set_filename( xfer, filename ); if( filesize > 0 ) @@ -395,9 +398,9 @@ while ( item ) { xfer = item->data; - if ( xfer->account == session->acc ) { + if ( purple_xfer_get_account( xfer ) == session->acc ) { /* transfer is associated with this MXit account */ - struct mxitxfer* mx = xfer->data; + struct mxitxfer* mx = purple_xfer_get_protocol_data( xfer ); /* does the fileid match? */ if ( ( mx ) && ( memcmp( mx->fileid, fileid, MXIT_CHUNK_FILEID_LEN ) == 0 ) ) @@ -431,12 +434,13 @@ /* find the file-transfer object */ xfer = find_mxit_xfer( session, fileid ); if ( xfer ) { - mx = xfer->data; + mx = purple_xfer_get_protocol_data( xfer ); /* this is the transfer we have been looking for */ purple_xfer_ref( xfer ); purple_xfer_start( xfer, -1, NULL, 0 ); fwrite( data, datalen, 1, xfer->dest_fp ); + // TODO: Handle error from fwrite() purple_xfer_unref( xfer ); purple_xfer_set_completed( xfer, TRUE ); purple_xfer_end( xfer ); diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/mxit/formcmds.c --- a/libpurple/protocols/mxit/formcmds.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/protocols/mxit/formcmds.c Mon Aug 29 12:28:49 2011 +0900 @@ -253,8 +253,8 @@ /*------------------------------------------------------------------------ * Process a Reply MXit command. - * [::op=cmd|type=reply|replymsg=back|selmsg=b) Back|id=12345:] - * [::op=cmd|nm=rep|type=reply|replymsg=back|selmsg=b) Back|id=12345:] + * [::op=cmd|type=reply|replymsg=back|selmsg=b) Back|displaymsg=Processing|id=12345:] + * [::op=cmd|nm=rep|type=reply|replymsg=back|selmsg=b) Back|displaymsg=Processing|id=12345:] * * @param mx The received message data object * @param hash The MXit command map @@ -265,22 +265,26 @@ char* selmsg; char* nm; - selmsg = g_hash_table_lookup(hash, "selmsg"); /* find the selection message */ - replymsg = g_hash_table_lookup(hash, "replymsg"); /* find the reply message */ + selmsg = g_hash_table_lookup(hash, "selmsg"); /* selection message */ + replymsg = g_hash_table_lookup(hash, "replymsg"); /* reply message */ nm = g_hash_table_lookup(hash, "nm"); /* name parameter */ - if ((selmsg) && (replymsg) && (nm)) { + + if ((selmsg == NULL) || (replymsg == NULL)) + return; /* these parameters are required */ + + if (nm) { /* indicates response must be a structured response */ gchar* seltext = g_markup_escape_text(purple_url_decode(selmsg), -1); - gchar* replycmd = g_strdup_printf("::type=reply|nm=%s|res=%s|err=0:", nm, replymsg); + gchar* replycmd = g_strdup_printf("type=reply|nm=%s|res=%s|err=0", nm, replymsg); - mxit_add_html_link( mx, replycmd, seltext ); + mxit_add_html_link( mx, replycmd, TRUE, seltext ); g_free(seltext); g_free(replycmd); } - else if ((selmsg) && (replymsg)) { + else { gchar* seltext = g_markup_escape_text(purple_url_decode(selmsg), -1); - mxit_add_html_link( mx, purple_url_decode(replymsg), seltext ); + mxit_add_html_link( mx, purple_url_decode(replymsg), FALSE, seltext ); g_free(seltext); } @@ -317,6 +321,7 @@ /*------------------------------------------------------------------------ * Process an inline image MXit command. + * [::op=img|dat=ASDF23408asdflkj2309flkjsadf%3d%3d|algn=1|w=120|h=12|t=100|replymsg=text:] * * @param mx The received message data object * @param hash The MXit command map @@ -372,7 +377,7 @@ reply = g_hash_table_lookup(hash, "replymsg"); if (reply) { g_string_append_printf(msg, "\n"); - mxit_add_html_link(mx, reply, _( "click here" )); + mxit_add_html_link(mx, reply, FALSE, _( "click here" )); } } diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/mxit/login.c --- a/libpurple/protocols/mxit/login.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/protocols/mxit/login.c Mon Aug 29 12:28:49 2011 +0900 @@ -49,29 +49,27 @@ */ static struct MXitSession* mxit_create_object( PurpleAccount* account ) { + PurpleConnection* con = purple_account_get_connection( account ); struct MXitSession* session = NULL; - PurpleConnection* con = NULL; /* currently the wapsite does not handle a '+' in front of the username (mxitid) so we just strip it */ - if ( account->username[0] == '+' ) { - char* fixed; + { + const char* username = purple_account_get_username( account ); - /* cut off the '+' */ - fixed = g_strdup( &account->username[1] ); - purple_account_set_username( account, fixed ); - g_free( fixed ); + if ( username[0] == '+' ) { + char* fixed = g_strdup( &username[1] ); + purple_account_set_username( account, fixed ); + g_free( fixed ); + } } session = g_new0( struct MXitSession, 1 ); + session->con = con; + session->acc = account; /* configure the connection (reference: "libpurple/connection.h") */ - con = purple_account_get_connection( account ); - con->proto_data = session; + purple_connection_set_protocol_data( con, session ); con->flags |= PURPLE_CONNECTION_NO_BGCOLOR | PURPLE_CONNECTION_NO_URLDESC | PURPLE_CONNECTION_HTML | PURPLE_CONNECTION_SUPPORT_MOODS; - session->con = con; - - /* add account */ - session->acc = account; /* configure the session (reference: "libpurple/account.h") */ g_strlcpy( session->server, purple_account_get_string( account, MXIT_CONFIG_SERVER_ADDR, DEFAULT_SERVER ), sizeof( session->server ) ); @@ -221,7 +219,7 @@ */ static void mxit_cb_register_ok( PurpleConnection *gc, PurpleRequestFields *fields ) { - struct MXitSession* session = (struct MXitSession*) gc->proto_data; + struct MXitSession* session = purple_connection_get_protocol_data( gc ); struct MXitProfile* profile = session->profile; const char* str; const char* pin; @@ -303,7 +301,7 @@ purple_debug_info( MXIT_PLUGIN_ID, "mxit_cb_register_cancel\n" ); /* disconnect */ - purple_account_disconnect( gc->account ); + purple_account_disconnect( purple_connection_get_account( gc ) ); } @@ -507,7 +505,7 @@ */ static void mxit_cb_captcha_ok( PurpleConnection* gc, PurpleRequestFields* fields ) { - struct MXitSession* session = (struct MXitSession*) gc->proto_data; + struct MXitSession* session = purple_connection_get_protocol_data( gc ); PurpleUtilFetchUrlData* url_data; PurpleRequestField* field; const char* captcha_resp; @@ -571,7 +569,7 @@ */ static void mxit_cb_captcha_cancel( PurpleConnection* gc, PurpleRequestFields* fields ) { - struct MXitSession* session = (struct MXitSession*) gc->proto_data; + struct MXitSession* session = purple_connection_get_protocol_data( gc ); /* free up the login resources */ free_logindata( session->logindata ); @@ -743,7 +741,7 @@ * if we don't have any info saved from a previous login, we need to get it from the MXit WAP site. * we do cache it, so this step is only done on the very first login for each account. */ - if ( ( session->distcode == NULL ) || ( strlen( session->distcode ) == 0 ) ) { + if ( ( session->distcode == NULL ) || ( !*session->distcode ) ) { /* this must be the very first login, so we need to retrieve the user information */ get_clientinfo( session ); } diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/mxit/markup.c --- a/libpurple/protocols/mxit/markup.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/protocols/mxit/markup.c Mon Aug 29 12:28:49 2011 +0900 @@ -124,10 +124,11 @@ * Adds a link to a message * * @param mx The Markup message object - * @param linkname This is the what will be returned when the link gets clicked - * @param displayname This is the name for the link which will be displayed in the UI + * @param replydata This is the what will be returned when the link gets clicked + * @param isStructured Indicates that the reply is a structured reply + * @param displaytext This is the text for the link which will be displayed in the UI */ -void mxit_add_html_link( struct RXMsgData* mx, const char* linkname, const char* displayname ) +void mxit_add_html_link( struct RXMsgData* mx, const char* replydata, gboolean isStructured, const char* displaytext ) { #ifdef MXIT_LINK_CLICK char retstr[256]; @@ -135,15 +136,24 @@ char link[256]; int len; - len = g_snprintf( retstr, sizeof( retstr ), "%s|%s|%s|%s|%s", MXIT_LINK_KEY, purple_account_get_username( mx->session->acc ), - purple_account_get_protocol_id( mx->session->acc ), mx->from, linkname ); + /* + * The link content is encoded as follows: + * MXIT_LINK_KEY | ACCOUNT_USER | ACCOUNT_PROTO | REPLY_TO | REPLY_FORMAT | REPLY_DATA + */ + len = g_snprintf( retstr, sizeof( retstr ), "%s|%s|%s|%s|%i|%s", + MXIT_LINK_KEY, + purple_account_get_username( mx->session->acc ), + purple_account_get_protocol_id( mx->session->acc ), + mx->from, + isStructured ? 1 : 0, + replydata ); retstr64 = purple_base64_encode( (const unsigned char*) retstr, len ); g_snprintf( link, sizeof( link ), "%s%s", MXIT_LINK_PREFIX, retstr64 ); g_free( retstr64 ); - g_string_append_printf( mx->msg, "%s", link, displayname ); + g_string_append_printf( mx->msg, "%s", link, displaytext ); #else - g_string_append_printf( mx->msg, "%s", linkname ); + g_string_append_printf( mx->msg, "%s", replydata ); #endif } @@ -735,6 +745,7 @@ gboolean tag_bold = FALSE; gboolean tag_under = FALSE; gboolean tag_italic = FALSE; + int font_size = 0; #ifdef MXIT_DEBUG_MARKUP purple_debug_info( MXIT_PLUGIN_ID, "Markup RX (original): '%s'\n", message ); @@ -823,7 +834,7 @@ if ( ch ) { /* end found */ *ch = '\0'; - mxit_add_html_link( mx, &message[i + 1], &message[i + 1] ); + mxit_add_html_link( mx, &message[i + 1], FALSE, &message[i + 1] ); *ch = '$'; i += ( ch - &message[i + 1] ) + 1; } @@ -862,59 +873,54 @@ } break; case '.' : - if ( !( msgflags & CP_MSG_EMOTICON ) ) { - g_string_append_c( mx->msg, message[i] ); - break; - } - else if ( i + 1 >= len ) { + if ( i + 1 >= len ) { /* message too short */ g_string_append_c( mx->msg, '.' ); break; } - switch ( message[i+1] ) { - case '+' : - /* increment text size */ - g_string_append( mx->msg, "" ); - i++; - break; - case '-' : - /* decrement text size */ - g_string_append( mx->msg, "" ); - i++; - break; - case '{' : - /* custom emoticon */ - if ( i + 2 >= len ) { - /* message too short */ - g_string_append_c( mx->msg, '.' ); - break; - } + if ( ( msgflags & CP_MSG_EMOTICON ) && ( message[i+1] == '{' ) ) { + /* custom emoticon */ + if ( i + 2 >= len ) { + /* message too short */ + g_string_append_c( mx->msg, '.' ); + break; + } + + parse_emoticon_str( &message[i+2], tmpstr1 ); + if ( tmpstr1[0] != '\0' ) { + mx->got_img = TRUE; + + if ( g_hash_table_lookup( mx->session->iimages, tmpstr1 ) ) { + /* emoticon found in the cache, so we do not have to request it from the WAPsite */ + } + else { + /* request emoticon from the WAPsite */ + mx->img_count++; + emoticon_request( mx, tmpstr1 ); + } - parse_emoticon_str( &message[i+2], tmpstr1 ); - if ( tmpstr1[0] != '\0' ) { - mx->got_img = TRUE; + g_string_append_printf( mx->msg, MXIT_II_TAG"%s>", tmpstr1 ); + i += strlen( tmpstr1 ) + 2; + } + else + g_string_append_c( mx->msg, '.' ); + } + else if ( ( msgflags & CP_MSG_MARKUP ) && ( message[i+1] == '+' ) ) { + /* increment text size */ + font_size++; + g_string_append_printf( mx->msg, "", font_size ); + i++; + } + else if ( ( msgflags & CP_MSG_MARKUP ) && ( message[i+1] == '-' ) ) { + /* decrement text size */ + font_size--; + g_string_append_printf( mx->msg, "", font_size ); + i++; + } + else + g_string_append_c( mx->msg, '.' ); - if ( g_hash_table_lookup( mx->session->iimages, tmpstr1 ) ) { - /* emoticon found in the cache, so we do not have to request it from the WAPsite */ - } - else { - /* request emoticon from the WAPsite */ - mx->img_count++; - emoticon_request( mx, tmpstr1 ); - } - - g_string_append_printf( mx->msg, MXIT_II_TAG"%s>", tmpstr1 ); - i += strlen( tmpstr1 ) + 2; - } - else - g_string_append_c( mx->msg, '.' ); - - break; - default : - g_string_append_c( mx->msg, '.' ); - break; - } break; case '\\' : if ( i + 1 >= len ) { diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/mxit/markup.h --- a/libpurple/protocols/mxit/markup.h Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/protocols/mxit/markup.h Mon Aug 29 12:28:49 2011 +0900 @@ -31,7 +31,7 @@ void mxit_parse_markup( struct RXMsgData* mx, char* message, int len, short msgtype, int msgflags ); char* mxit_convert_markup_tx( const char* message, int* msgtype ); -void mxit_add_html_link( struct RXMsgData* mx, const char* linkname, const char* displayname ); +void mxit_add_html_link( struct RXMsgData* mx, const char* replydata, gboolean isStructured, const char* displaytext ); void mxit_show_message( struct RXMsgData* mx ); void mxit_free_emoticon_cache( struct MXitSession* session ); diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/mxit/multimx.c --- a/libpurple/protocols/mxit/multimx.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/protocols/mxit/multimx.c Mon Aug 29 12:28:49 2011 +0900 @@ -277,7 +277,11 @@ GHashTable *components; struct multimx* multimx = NULL; - purple_debug_info(MXIT_PLUGIN_ID, "Groupchat invite to '%s' by '%s'\n", contact->alias, creator); + purple_debug_info(MXIT_PLUGIN_ID, "Groupchat invite to '%s' (roomid='%s') by '%s'\n", contact->alias, contact->username, creator); + + /* Check if the room already exists (ie, already joined or invite pending) */ + if (find_room_by_username(session, contact->username) != NULL) + return; /* Create a new room */ multimx = room_create(session, contact->username, contact->alias, STATE_INVITED); @@ -307,7 +311,7 @@ multimx = find_room_by_username(session, contact->username); if (multimx == NULL) { multimx = room_create(session, contact->username, contact->alias, TRUE); - } + } else if (multimx->state == STATE_INVITED) { /* After successfully accepting an invitation */ multimx->state = STATE_JOINED; @@ -454,7 +458,7 @@ */ void mxit_chat_join(PurpleConnection *gc, GHashTable *components) { - struct MXitSession* session = (struct MXitSession*) gc->proto_data; + struct MXitSession* session = purple_connection_get_protocol_data(gc); const char* roomname = NULL; struct multimx* multimx = NULL; @@ -496,7 +500,7 @@ */ void mxit_chat_reject(PurpleConnection *gc, GHashTable* components) { - struct MXitSession* session = (struct MXitSession*) gc->proto_data; + struct MXitSession* session = purple_connection_get_protocol_data(gc); const char* roomname = NULL; struct multimx* multimx = NULL; @@ -539,7 +543,7 @@ */ void mxit_chat_invite(PurpleConnection *gc, int id, const char *msg, const char *username) { - struct MXitSession* session = (struct MXitSession*) gc->proto_data; + struct MXitSession* session = purple_connection_get_protocol_data(gc); struct multimx* multimx = NULL; PurpleBuddy* buddy; PurpleConversation *convo; @@ -585,7 +589,7 @@ */ void mxit_chat_leave(PurpleConnection *gc, int id) { - struct MXitSession* session = (struct MXitSession*) gc->proto_data; + struct MXitSession* session = purple_connection_get_protocol_data(gc); struct multimx* multimx = NULL; purple_debug_info(MXIT_PLUGIN_ID, "Groupchat %i leave\n", id); @@ -616,7 +620,7 @@ */ int mxit_chat_send(PurpleConnection *gc, int id, const char *message, PurpleMessageFlags flags) { - struct MXitSession* session = (struct MXitSession*) gc->proto_data; + struct MXitSession* session = purple_connection_get_protocol_data(gc); struct multimx* multimx = NULL; const char* nickname; diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/mxit/mxit.c --- a/libpurple/protocols/mxit/mxit.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/protocols/mxit/mxit.c Mon Aug 29 12:28:49 2011 +0900 @@ -58,7 +58,7 @@ static void* mxit_link_click( const char* link64 ) { PurpleAccount* account; - PurpleConnection* con; + PurpleConnection* gc; gchar** parts = NULL; gchar* link = NULL; gsize len; @@ -75,10 +75,10 @@ link = (gchar*) purple_base64_decode( link64 + strlen( MXIT_LINK_PREFIX ), &len ); purple_debug_info( MXIT_PLUGIN_ID, "Clicked Link: '%s'\n", link ); - parts = g_strsplit( link, "|", 5 ); + parts = g_strsplit( link, "|", 6 ); /* check if this is a valid mxit link */ - if ( ( !parts ) || ( !parts[0] ) || ( !parts[1] ) || ( !parts[2] ) || ( !parts[3] ) || ( !parts[4] ) ) { + if ( ( !parts ) || ( !parts[0] ) || ( !parts[1] ) || ( !parts[2] ) || ( !parts[3] ) || ( !parts[4] ) || ( !parts[5] ) ) { /* this is not for us */ goto skip; } @@ -91,15 +91,15 @@ account = purple_accounts_find( parts[1], parts[2] ); if ( !account ) goto skip; - con = purple_account_get_connection( account ); - if ( !con ) + gc = purple_account_get_connection( account ); + if ( !gc ) goto skip; /* determine if it's a command-response to send */ - is_command = g_str_has_prefix( parts[4], "::type=reply|" ); + is_command = ( atoi( parts[4] ) == 1 ); /* send click message back to MXit */ - mxit_send_message( con->proto_data, parts[3], parts[4], FALSE, is_command ); + mxit_send_message( purple_connection_get_protocol_data( gc ), parts[3], parts[5], FALSE, is_command ); g_free( link ); link = NULL; @@ -129,7 +129,7 @@ /*------------------------------------------------------------------------ * Register MXit to receive URI click notifications from the UI */ -void mxit_register_uri_handler(void) +void mxit_register_uri_handler( void ) { not_link_ref_count++; if ( not_link_ref_count == 1 ) { @@ -198,7 +198,7 @@ if ( !buddy ) return; - contact = purple_buddy_get_protocol_data(buddy); + contact = purple_buddy_get_protocol_data( buddy ); if ( !contact ) return; @@ -214,7 +214,7 @@ case MXIT_TYPE_INFO : tmp = g_strdup_printf("%s\n", _( "Loading menu..." )); serv_got_im( session->con, who, tmp, PURPLE_MESSAGE_NOTIFY, time( NULL ) ); - g_free(tmp); + g_free( tmp ); mxit_send_message( session, who, " ", FALSE, FALSE ); default : break; @@ -268,7 +268,7 @@ */ static const char* mxit_list_emblem( PurpleBuddy* buddy ) { - struct contact* contact = purple_buddy_get_protocol_data(buddy); + struct contact* contact = purple_buddy_get_protocol_data( buddy ); if ( !contact ) return NULL; @@ -309,19 +309,18 @@ */ char* mxit_status_text( PurpleBuddy* buddy ) { - struct contact* contact = purple_buddy_get_protocol_data(buddy); + char* text = NULL; + struct contact* contact = purple_buddy_get_protocol_data( buddy ); if ( !contact ) return NULL; - if ( contact->statusMsg ) { - /* status message */ - return g_strdup( contact-> statusMsg ); - } - else { - /* mood */ - return g_strdup( mxit_convert_mood_to_name( contact->mood ) ); - } + if ( contact->statusMsg ) /* status message */ + text = g_strdup( contact-> statusMsg ); + else if ( contact->mood != MXIT_MOOD_NONE ) /* mood */ + text = g_strdup( mxit_convert_mood_to_name( contact->mood ) ); + + return text; } @@ -334,34 +333,33 @@ */ static void mxit_tooltip( PurpleBuddy* buddy, PurpleNotifyUserInfo* info, gboolean full ) { - struct contact* contact = purple_buddy_get_protocol_data(buddy); + struct contact* contact = purple_buddy_get_protocol_data( buddy ); if ( !contact ) return; /* status (reference: "libpurple/notify.h") */ if ( contact->presence != MXIT_PRESENCE_OFFLINE ) - purple_notify_user_info_add_pair( info, _( "Status" ), mxit_convert_presence_to_name( contact->presence ) ); + purple_notify_user_info_add_pair_plaintext( info, _( "Status" ), mxit_convert_presence_to_name( contact->presence ) ); /* status message */ - if ( contact->statusMsg ) - purple_notify_user_info_add_pair( info, _( "Status Message" ), contact->statusMsg ); + if ( contact->statusMsg ) { + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html( info, _( "Status Message" ), contact->statusMsg ); + } /* mood */ if ( contact->mood != MXIT_MOOD_NONE ) - purple_notify_user_info_add_pair( info, _( "Mood" ), mxit_convert_mood_to_name( contact->mood ) ); + purple_notify_user_info_add_pair_plaintext( info, _( "Mood" ), mxit_convert_mood_to_name( contact->mood ) ); /* subscription type */ if ( contact->subtype != 0 ) - purple_notify_user_info_add_pair( info, _( "Subscription" ), mxit_convert_subtype_to_name( contact->subtype ) ); + purple_notify_user_info_add_pair_plaintext( info, _( "Subscription" ), mxit_convert_subtype_to_name( contact->subtype ) ); /* rejection message */ if ( ( contact->subtype == MXIT_SUBTYPE_REJECTED ) && ( contact->msg != NULL ) ) - purple_notify_user_info_add_pair( info, _( "Rejection Message" ), contact->msg ); - - /* hidden number */ - if ( contact->flags & MXIT_CFLAG_HIDDEN ) - purple_notify_user_info_add_pair( info, _( "Hidden Number" ), _( "Yes" ) ); + purple_notify_user_info_add_pair_plaintext( info, _( "Rejection Message" ), contact->msg ); } @@ -372,7 +370,7 @@ */ static void mxit_close( PurpleConnection* gc ) { - struct MXitSession* session = (struct MXitSession*) gc->proto_data; + struct MXitSession* session = purple_connection_get_protocol_data( gc ); /* disable signals */ mxit_disable_signals( session ); @@ -408,7 +406,7 @@ { purple_debug_info( MXIT_PLUGIN_ID, "Sending message '%s' to buddy '%s'\n", message, who ); - mxit_send_message( gc->proto_data, who, message, TRUE, FALSE ); + mxit_send_message( purple_connection_get_protocol_data( gc ), who, message, TRUE, FALSE ); return 1; /* echo to conversation window */ } @@ -422,14 +420,14 @@ */ static void mxit_set_status( PurpleAccount* account, PurpleStatus* status ) { - struct MXitSession* session = purple_account_get_connection( account )->proto_data; + struct MXitSession* session = purple_connection_get_protocol_data( purple_account_get_connection( account ) ); const char* statusid; int presence; char* statusmsg1; char* statusmsg2; /* Handle mood changes */ - if (purple_status_type_get_primitive(purple_status_get_type(status)) == PURPLE_STATUS_MOOD) { + if ( purple_status_type_get_primitive(purple_status_get_type( status ) ) == PURPLE_STATUS_MOOD ) { const char* moodid = purple_status_get_attr_string( status, PURPLE_MOOD_NAME ); int mood; @@ -492,7 +490,7 @@ purple_debug_info( MXIT_PLUGIN_ID, "mxit_free_buddy\n" ); - contact = purple_buddy_get_protocol_data(buddy); + contact = purple_buddy_get_protocol_data( buddy ); if ( contact ) { if ( contact->statusMsg ) g_free( contact->statusMsg ); @@ -503,7 +501,7 @@ g_free( contact ); } - purple_buddy_set_protocol_data(buddy, NULL); + purple_buddy_set_protocol_data( buddy, NULL ); } @@ -515,7 +513,7 @@ */ static void mxit_keepalive( PurpleConnection *gc ) { - struct MXitSession* session = (struct MXitSession*) gc->proto_data; + struct MXitSession* session = purple_connection_get_protocol_data( gc ); /* if not logged in, there is nothing to do */ if ( !( session->flags & MXIT_FLAG_LOGGEDIN ) ) @@ -543,7 +541,7 @@ */ static void mxit_set_buddy_icon( PurpleConnection *gc, PurpleStoredImage *img ) { - struct MXitSession* session = (struct MXitSession*) gc->proto_data; + struct MXitSession* session = purple_connection_get_protocol_data( gc ); if ( img == NULL ) mxit_set_avatar( session, NULL, 0 ); @@ -562,7 +560,7 @@ { PurpleBuddy* buddy; struct contact* contact; - struct MXitSession* session = (struct MXitSession*) gc->proto_data; + struct MXitSession* session = purple_connection_get_protocol_data( gc ); const char* profilelist[] = { CP_PROFILE_BIRTHDATE, CP_PROFILE_GENDER, CP_PROFILE_FULLNAME, CP_PROFILE_FIRSTNAME, CP_PROFILE_LASTNAME, CP_PROFILE_REGCOUNTRY, CP_PROFILE_LASTSEEN, CP_PROFILE_STATUS, CP_PROFILE_AVATAR, CP_PROFILE_WHEREAMI, CP_PROFILE_ABOUTME }; @@ -612,14 +610,10 @@ */ static void mxit_reinvite( PurpleBlistNode *node, gpointer ignored ) { - PurpleBuddy* buddy; + PurpleBuddy* buddy = (PurpleBuddy *) node; + PurpleConnection* gc = purple_account_get_connection( purple_buddy_get_account( buddy ) ); + struct MXitSession* session = purple_connection_get_protocol_data( gc ); struct contact* contact; - PurpleConnection* gc; - struct MXitSession* session; - - buddy = (PurpleBuddy *)node; - gc = purple_account_get_connection( purple_buddy_get_account( buddy ) ); - session = gc->proto_data; contact = purple_buddy_get_protocol_data( (PurpleBuddy*) node ); if ( !contact ) @@ -653,12 +647,24 @@ if ( ( contact->subtype == MXIT_SUBTYPE_DELETED ) || ( contact->subtype == MXIT_SUBTYPE_REJECTED ) || ( contact->subtype == MXIT_SUBTYPE_NONE ) ) { /* contact is in Deleted, Rejected or None state */ act = purple_menu_action_new( _( "Re-Invite" ), PURPLE_CALLBACK( mxit_reinvite ), NULL, NULL ); - m = g_list_append(m, act); + m = g_list_append( m, act ); } return m; } + +/*------------------------------------------------------------------------ + * Return Chat-room default settings. + * + * @return Chat defaults list + */ +static GHashTable *mxit_chat_info_defaults( PurpleConnection *gc, const char *chat_name ) +{ + return g_hash_table_new_full( g_str_hash, g_str_equal, NULL, g_free ); +} + + /*========================================================================================================================*/ static PurplePluginProtocolInfo proto_info = { @@ -680,7 +686,7 @@ mxit_status_types, /* status types [roster.c] */ mxit_blist_menu, /* blist_node_menu */ mxit_chat_info, /* chat_info [multimx.c] */ - NULL, /* chat_info_defaults */ + mxit_chat_info_defaults,/* chat_info_defaults */ mxit_login, /* login [login.c] */ mxit_close, /* close */ mxit_send_im, /* send_im */ diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/mxit/mxit.h --- a/libpurple/protocols/mxit/mxit.h Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/protocols/mxit/mxit.h Mon Aug 29 12:28:49 2011 +0900 @@ -191,7 +191,7 @@ void mxit_enable_signals( struct MXitSession* session ); #ifdef MXIT_LINK_CLICK -void mxit_register_uri_handler(void); +void mxit_register_uri_handler( void ); #endif diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/mxit/profile.c --- a/libpurple/protocols/mxit/profile.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/protocols/mxit/profile.c Mon Aug 29 12:28:49 2011 +0900 @@ -115,16 +115,16 @@ struct tm now, bdate; int age; - if ( ( !date ) || ( strlen( date ) == 0 ) ) + if ( ( !date ) || ( !*date ) ) return 0; /* current time */ - t = time(NULL); + t = time( NULL ); localtime_r( &t, &now ); /* decode hdate */ memset( &bdate, 0, sizeof( struct tm ) ); - purple_str_to_time(date, FALSE, &bdate, NULL, NULL); + purple_str_to_time( date, FALSE, &bdate, NULL, NULL ); /* calculate difference */ age = now.tm_year - bdate.tm_year; @@ -170,54 +170,56 @@ buddy = purple_find_buddy( session->acc, username ); if ( buddy ) { - purple_notify_user_info_add_pair( info, _( "Alias" ), purple_buddy_get_alias( buddy ) ); + purple_notify_user_info_add_pair_plaintext( info, _( "Alias" ), purple_buddy_get_alias( buddy ) ); purple_notify_user_info_add_section_break( info ); - contact = purple_buddy_get_protocol_data(buddy); + contact = purple_buddy_get_protocol_data( buddy ); } - purple_notify_user_info_add_pair( info, _( "Display Name" ), profile->nickname ); + purple_notify_user_info_add_pair_plaintext( info, _( "Display Name" ), profile->nickname ); tmp = g_strdup_printf("%s (%i)", profile->birthday, calculateAge( profile->birthday ) ); - purple_notify_user_info_add_pair( info, _( "Birthday" ), tmp ); + purple_notify_user_info_add_pair_plaintext( info, _( "Birthday" ), tmp ); g_free( tmp ); - purple_notify_user_info_add_pair( info, _( "Gender" ), profile->male ? _( "Male" ) : _( "Female" ) ); + purple_notify_user_info_add_pair_plaintext( info, _( "Gender" ), profile->male ? _( "Male" ) : _( "Female" ) ); /* optional information */ - purple_notify_user_info_add_pair( info, _( "First Name" ), profile->firstname ); - purple_notify_user_info_add_pair( info, _( "Last Name" ), profile->lastname ); - purple_notify_user_info_add_pair( info, _( "Country" ), profile->regcountry ); + purple_notify_user_info_add_pair_plaintext( info, _( "First Name" ), profile->firstname ); + purple_notify_user_info_add_pair_plaintext( info, _( "Last Name" ), profile->lastname ); + + purple_notify_user_info_add_pair_plaintext( info, _( "Country" ), profile->regcountry ); - if ( strlen( profile->aboutme ) > 0 ) - purple_notify_user_info_add_pair( info, _( "About Me" ), profile->aboutme ); - if ( strlen( profile->whereami ) > 0 ) - purple_notify_user_info_add_pair( info, _( "Where I Live" ), profile->whereami ); + if ( *profile->aboutme ) + purple_notify_user_info_add_pair_plaintext( info, _( "About Me" ), profile->aboutme ); + + if ( *profile->whereami ) + purple_notify_user_info_add_pair_plaintext( info, _( "Where I Live" ), profile->whereami ); purple_notify_user_info_add_section_break( info ); if ( contact ) { /* presence */ - purple_notify_user_info_add_pair( info, _( "Status" ), mxit_convert_presence_to_name( contact->presence ) ); + purple_notify_user_info_add_pair_plaintext( info, _( "Status" ), mxit_convert_presence_to_name( contact->presence ) ); /* last online */ if ( contact->presence == MXIT_PRESENCE_OFFLINE ) - purple_notify_user_info_add_pair( info, _( "Last Online" ), ( profile->lastonline == 0 ) ? _( "Unknown" ) : datetime( profile->lastonline ) ); + purple_notify_user_info_add_pair_plaintext( info, _( "Last Online" ), ( profile->lastonline == 0 ) ? _( "Unknown" ) : datetime( profile->lastonline ) ); /* mood */ if ( contact->mood != MXIT_MOOD_NONE ) - purple_notify_user_info_add_pair( info, _( "Mood" ), mxit_convert_mood_to_name( contact->mood ) ); + purple_notify_user_info_add_pair_plaintext( info, _( "Mood" ), mxit_convert_mood_to_name( contact->mood ) ); else - purple_notify_user_info_add_pair( info, _( "Mood" ), _( "None" ) ); + purple_notify_user_info_add_pair_plaintext( info, _( "Mood" ), _( "None" ) ); /* status message */ - if ( contact->statusMsg ) - purple_notify_user_info_add_pair( info, _( "Status Message" ), contact->statusMsg ); + if ( contact->statusMsg ) { + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html( info, _( "Status Message" ), contact->statusMsg ); + } /* subscription type */ - purple_notify_user_info_add_pair( info, _( "Subscription" ), mxit_convert_subtype_to_name( contact->subtype ) ); - - /* hidden number */ - purple_notify_user_info_add_pair( info, _( "Hidden Number" ), ( contact->flags & MXIT_CFLAG_HIDDEN ) ? _( "Yes" ) : _( "No" ) ); + purple_notify_user_info_add_pair_plaintext( info, _( "Subscription" ), mxit_convert_subtype_to_name( contact->subtype ) ); } else { /* this is an invite */ @@ -226,17 +228,21 @@ /* invite found */ if ( contact->msg ) - purple_notify_user_info_add_pair( info, _( "Invite Message" ), contact->msg ); + purple_notify_user_info_add_pair_plaintext( info, _( "Invite Message" ), contact->msg ); if ( contact->imgid ) { /* this invite has a avatar */ char* img_text; img_text = g_strdup_printf( "", contact->imgid ); - purple_notify_user_info_add_pair( info, _( "Photo" ), img_text ); + purple_notify_user_info_add_pair_html( info, _( "Photo" ), img_text ); + g_free(img_text); } - if ( contact->statusMsg ) - purple_notify_user_info_add_pair( info, _( "Status Message" ), contact->statusMsg ); + if ( contact->statusMsg ) { + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html( info, _( "Status Message" ), contact->statusMsg ); + } } } @@ -284,6 +290,7 @@ /* define columns */ column = purple_notify_searchresults_column_new( _( "UserId" ) ); + purple_notify_searchresult_column_set_visible( column, FALSE ); purple_notify_searchresults_column_add( results, column ); column = purple_notify_searchresults_column_new( _( "Display Name" ) ); purple_notify_searchresults_column_add( results, column ); @@ -298,7 +305,7 @@ column = purple_notify_searchresults_column_new( _( "Where I live" ) ); purple_notify_searchresults_column_add( results, column ); - while (entries != NULL) { + while ( entries != NULL ) { struct MXitProfile* profile = ( struct MXitProfile *) entries->data; GList* row; gchar* tmp = purple_base64_encode( (unsigned char *) profile->userid, strlen( profile->userid ) ); @@ -328,5 +335,5 @@ purple_notify_searchresults( session->con, NULL, text, NULL, results, NULL, NULL ); - g_free( text); + g_free( text ); } diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/mxit/profile.h --- a/libpurple/protocols/mxit/profile.h Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/protocols/mxit/profile.h Mon Aug 29 12:28:49 2011 +0900 @@ -50,7 +50,6 @@ int flags; /* user's profile flags */ gint64 lastonline; /* user's last-online timestamp */ - gboolean hidden; /* set if the user's mxitid should remain hidden */ }; struct MXitSession; diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/mxit/protocol.c --- a/libpurple/protocols/mxit/protocol.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/protocols/mxit/protocol.c Mon Aug 29 12:28:49 2011 +0900 @@ -86,7 +86,7 @@ void mxit_strip_domain( char* username ) { if ( g_str_has_suffix( username, "@m" ) ) - username[ strlen(username) - 2 ] = '\0'; + username[ strlen( username ) - 2 ] = '\0'; } @@ -704,9 +704,9 @@ locale = purple_account_get_string( session->acc, MXIT_CONFIG_LOCALE, MXIT_DEFAULT_LOCALE ); /* Voice and Video supported */ - if (mxit_audio_enabled() && mxit_video_enabled()) - features |= (MXIT_CF_VOICE | MXIT_CF_VIDEO); - else if (mxit_audio_enabled()) + if ( mxit_audio_enabled() && mxit_video_enabled() ) + features |= ( MXIT_CF_VOICE | MXIT_CF_VIDEO ); + else if ( mxit_audio_enabled() ) features |= MXIT_CF_VOICE; /* generate client version string (eg, P-2.7.10-Y-PURPLE) */ @@ -748,9 +748,9 @@ locale = purple_account_get_string( session->acc, MXIT_CONFIG_LOCALE, MXIT_DEFAULT_LOCALE ); /* Voice and Video supported */ - if (mxit_audio_enabled() && mxit_video_enabled()) - features |= (MXIT_CF_VOICE | MXIT_CF_VIDEO); - else if (mxit_audio_enabled()) + if ( mxit_audio_enabled() && mxit_video_enabled() ) + features |= ( MXIT_CF_VOICE | MXIT_CF_VIDEO ); + else if ( mxit_audio_enabled() ) features |= MXIT_CF_VOICE; /* generate client version string (eg, P-2.7.10-Y-PURPLE) */ @@ -835,7 +835,7 @@ /* add attributes */ for ( i = 0; i < nr_attrib; i++ ) - datalen += sprintf( data + datalen, "%c%s", CP_FLD_TERM, attribute[i] ); + datalen += sprintf( data + datalen, "%c%s", CP_FLD_TERM, attribute[i] ); /* queue packet for transmission */ mxit_queue_packet( session, data, datalen, CP_CMD_EXTPROFILE_GET ); @@ -868,7 +868,7 @@ /* add attributes */ for ( i = 1; i < nr_attrib * 3; i+=3 ) - datalen += sprintf( data + datalen, "%c%s%c%s%c%s", /* \1name\1type\1value */ + datalen += sprintf( data + datalen, "%c%s%c%s%c%s", /* \1name\1type\1value */ CP_FLD_TERM, parts[i], CP_FLD_TERM, parts[i + 1], CP_FLD_TERM, parts[i + 2] ); /* queue packet for transmission */ @@ -900,7 +900,7 @@ /* add attributes */ for ( i = 0; i < nr_attrib; i++ ) - datalen += sprintf( data + datalen, "%c%s", CP_FLD_TERM, attribute[i] ); + datalen += sprintf( data + datalen, "%c%s", CP_FLD_TERM, attribute[i] ); /* queue packet for transmission */ mxit_queue_packet( session, data, datalen, CP_CMD_SUGGESTCONTACTS ); @@ -929,7 +929,7 @@ /* add attributes */ for ( i = 0; i < nr_attrib; i++ ) - datalen += sprintf( data + datalen, "%c%s", CP_FLD_TERM, attribute[i] ); + datalen += sprintf( data + datalen, "%c%s", CP_FLD_TERM, attribute[i] ); /* queue packet for transmission */ mxit_queue_packet( session, data, datalen, CP_CMD_SUGGESTCONTACTS ); @@ -1175,7 +1175,7 @@ /* add usernames */ for ( i = 0; i < nr_usernames; i++ ) - datalen += sprintf( data + datalen, "%c%s", CP_FLD_TERM, usernames[i] ); + datalen += sprintf( data + datalen, "%c%s", CP_FLD_TERM, usernames[i] ); /* queue packet for transmission */ mxit_queue_packet( session, data, datalen, CP_CMD_GRPCHAT_CREATE ); @@ -1204,7 +1204,7 @@ /* add usernames */ for ( i = 0; i < nr_usernames; i++ ) - datalen += sprintf( data + datalen, "%c%s", CP_FLD_TERM, usernames[i] ); + datalen += sprintf( data + datalen, "%c%s", CP_FLD_TERM, usernames[i] ); /* queue packet for transmission */ mxit_queue_packet( session, data, datalen, CP_CMD_GRPCHAT_INVITE ); @@ -1448,7 +1448,7 @@ PurpleStatus* status; int presence; const char* statusmsg; - const char* profilelist[] = { CP_PROFILE_BIRTHDATE, CP_PROFILE_GENDER, CP_PROFILE_HIDENUMBER, CP_PROFILE_FULLNAME, + const char* profilelist[] = { CP_PROFILE_BIRTHDATE, CP_PROFILE_GENDER, CP_PROFILE_FULLNAME, CP_PROFILE_TITLE, CP_PROFILE_FIRSTNAME, CP_PROFILE_LASTNAME, CP_PROFILE_EMAIL, CP_PROFILE_MOBILENR, CP_PROFILE_WHEREAMI, CP_PROFILE_ABOUTME, CP_PROFILE_FLAGS }; @@ -1516,6 +1516,7 @@ { struct RXMsgData* mx = NULL; char* message = NULL; + char* sender = NULL; int msglen = 0; int msgflags = 0; int msgtype = 0; @@ -1529,10 +1530,11 @@ msglen = strlen( message ); /* strip off dummy domain */ - mxit_strip_domain( records[0]->fields[0]->data ); + sender = records[0]->fields[0]->data; + mxit_strip_domain( sender ); #ifdef DEBUG_PROTOCOL - purple_debug_info( MXIT_PLUGIN_ID, "Message received from '%s'\n", records[0]->fields[0]->data ); + purple_debug_info( MXIT_PLUGIN_ID, "Message received from '%s'\n", sender ); #endif /* decode message flags (if any) */ @@ -1540,33 +1542,42 @@ msgflags = atoi( records[0]->fields[4]->data ); msgtype = atoi( records[0]->fields[2]->data ); - if ( msgflags & CP_MSG_ENCRYPTED ) { - /* this is an encrypted message. we do not currently support those so ignore it */ + if ( msgflags & CP_MSG_PWD_ENCRYPTED ) { + /* this is a password encrypted message. we do not currently support those so ignore it */ PurpleBuddy* buddy; const char* name; char msg[128]; - buddy = purple_find_buddy( session->acc, records[0]->fields[0]->data ); + buddy = purple_find_buddy( session->acc, sender ); if ( buddy ) name = purple_buddy_get_alias( buddy ); else - name = records[0]->fields[0]->data; + name = sender; g_snprintf( msg, sizeof( msg ), _( "%s sent you an encrypted message, but it is not supported on this client." ), name ); mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Message Error" ), msg ); return; } + else if ( msgflags & CP_MSG_TL_ENCRYPTED ) { + /* this is a transport-layer encrypted message. */ + message = mxit_decrypt_message( session, message ); + if ( !message ) { + /* could not be decrypted */ + serv_got_im( session->con, sender, _( "An encrypted message was received which could not be decrypted." ), PURPLE_MESSAGE_ERROR, time( NULL ) ); + return; + } + } if ( msgflags & CP_MSG_NOTIFY_DELIVERY ) { /* delivery notification is requested */ if ( records[0]->fcount >= 4 ) - mxit_send_msgevent( session, records[0]->fields[0]->data, records[0]->fields[3]->data, CP_MSGEVENT_DELIVERED ); + mxit_send_msgevent( session, sender, records[0]->fields[3]->data, CP_MSGEVENT_DELIVERED ); } /* create and initialise new markup struct */ mx = g_new0( struct RXMsgData, 1 ); mx->msg = g_string_sized_new( msglen ); mx->session = session; - mx->from = g_strdup( records[0]->fields[0]->data ); + mx->from = g_strdup( sender ); mx->timestamp = atoi( records[0]->fields[1]->data ); mx->got_img = FALSE; mx->chatid = -1; @@ -1597,6 +1608,10 @@ * so the image received callback function will eventually display * the message. */ } + + /* cleanup */ + if ( msgflags & CP_MSG_TL_ENCRYPTED ) + g_free( message ); } @@ -1633,7 +1648,7 @@ if ( rec->fcount >= 5 ) { /* there is a personal invite message attached */ - if ( ( rec->fields[4]->data ) && ( strlen( rec->fields[4]->data ) > 0 ) ) + if ( ( rec->fields[4]->data ) && ( *rec->fields[4]->data ) ) contact->msg = strdup( rec->fields[4]->data ); } @@ -1810,10 +1825,6 @@ /* gender */ profile->male = ( fvalue[0] == '1' ); } - else if ( strcmp( CP_PROFILE_HIDENUMBER, fname ) == 0 ) { - /* hide number */ - profile->hidden = ( fvalue[0] == '1' ); - } else if ( strcmp( CP_PROFILE_FULLNAME, fname ) == 0 ) { /* nickname */ g_strlcpy( profile->nickname, fvalue, sizeof( profile->nickname ) ); @@ -1879,7 +1890,7 @@ contact = get_mxit_invite_contact( session, mxitId ); if ( contact ) { /* this is an invite, so update its profile info */ - if ( ( statusMsg ) && ( strlen( statusMsg ) > 0 ) ) { + if ( ( statusMsg ) && ( *statusMsg ) ) { /* update the status message */ if ( contact->statusMsg ) g_free( contact->statusMsg ); @@ -1890,7 +1901,7 @@ if ( contact->profile ) g_free( contact->profile ); contact->profile = profile; - if ( ( avatarId ) && ( strlen( avatarId ) > 0 ) ) { + if ( ( avatarId ) && ( *avatarId ) ) { /* avatar must be requested for this invite before we can display it */ mxit_get_avatar( session, mxitId, avatarId ); if ( contact->avatarId ) @@ -1908,7 +1919,7 @@ if ( avatarId ) mxit_update_buddy_avatar( session, mxitId, avatarId ); - if ( ( statusMsg ) && ( strlen( statusMsg ) > 0 ) ) { + if ( ( statusMsg ) && ( *statusMsg ) ) { /* update the status message */ PurpleBuddy* buddy = NULL; @@ -2270,7 +2281,7 @@ case CP_CMD_PRESENCE : /* presence update */ - mxit_parse_cmd_presence(session, &packet->records[2], packet->rcount - 3 ); + mxit_parse_cmd_presence( session, &packet->records[2], packet->rcount - 3 ); break; case CP_CMD_RX_MSG : diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/mxit/protocol.h --- a/libpurple/protocols/mxit/protocol.h Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/protocols/mxit/protocol.h Mon Aug 29 12:28:49 2011 +0900 @@ -155,7 +155,10 @@ /* message flags */ #define CP_MSG_NOTIFY_DELIVERY 0x0002 /* request delivery notification */ #define CP_MSG_NOTIFY_READ 0x0004 /* request read notification */ -#define CP_MSG_ENCRYPTED 0x0010 /* message is encrypted */ +#define CP_MSG_PWD_ENCRYPTED 0x0010 /* message is password encrypted */ +#define CP_MSG_TL_ENCRYPTED 0x0020 /* message is transport encrypted */ +#define CP_MSG_RPLY_PWD_ENCRYPT 0x0040 /* reply should be password encrypted */ +#define CP_MSG_RPLY_TL_ENCRYPT 0x0080 /* reply should be transport encrypted */ #define CP_MSG_MARKUP 0x0200 /* message may contain markup */ #define CP_MSG_EMOTICON 0x0400 /* message may contain custom emoticons */ @@ -179,7 +182,7 @@ /* extended profile attribute fields */ #define CP_PROFILE_BIRTHDATE "birthdate" /* Birthdate (String - ISO 8601 format) */ #define CP_PROFILE_GENDER "gender" /* Gender (Boolean - 0=female, 1=male) */ -#define CP_PROFILE_HIDENUMBER "hidenumber" /* Hide Number (Boolean - 0=false, 1=true) */ +// #define CP_PROFILE_HIDENUMBER "hidenumber" /* Hide Number (Boolean - 0=false, 1=true) (DEPRECATED) */ #define CP_PROFILE_FULLNAME "fullname" /* Fullname (UTF8 String) */ #define CP_PROFILE_STATUS "statusmsg" /* Status Message (UTF8 String) */ #define CP_PROFILE_PREVSTATUS "prevstatusmsgs" /* Previous Status Messages (UTF8 String) */ diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/mxit/roster.c --- a/libpurple/protocols/mxit/roster.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/protocols/mxit/roster.c Mon Aug 29 12:28:49 2011 +0900 @@ -82,9 +82,9 @@ } /* add Mood option */ - type = purple_status_type_new_with_attrs(PURPLE_STATUS_MOOD, "mood", NULL, FALSE, TRUE, TRUE, + type = purple_status_type_new_with_attrs( PURPLE_STATUS_MOOD, "mood", NULL, FALSE, TRUE, TRUE, PURPLE_MOOD_NAME, _("Mood Name"), purple_value_new( PURPLE_TYPE_STRING ), - NULL); + NULL ); statuslist = g_list_append( statuslist, type ); return statuslist; @@ -135,21 +135,21 @@ /* moods (reference: libpurple/status.h) */ static PurpleMood mxit_moods[] = { - {"angry", N_("Angry"), NULL}, - {"excited", N_("Excited"), NULL}, - {"grumpy", N_("Grumpy"), NULL}, - {"happy", N_("Happy"), NULL}, - {"in_love", N_("In love"), NULL}, - {"invincible", N_("Invincible"), NULL}, - {"sad", N_("Sad"), NULL}, - {"hot", N_("Hot"), NULL}, - {"sick", N_("Sick"), NULL}, - {"sleepy", N_("Sleepy"), NULL}, - {"bored", N_("Bored"), NULL}, - {"cold", N_("Cold"), NULL}, - {"confused", N_("Confused"), NULL}, - {"hungry", N_("Hungry"), NULL}, - {"stressed", N_("Stressed"), NULL}, + { "angry", N_( "Angry" ), NULL }, + { "excited", N_( "Excited" ), NULL }, + { "grumpy", N_( "Grumpy" ), NULL }, + { "happy", N_( "Happy" ), NULL }, + { "in_love", N_( "In love" ), NULL }, + { "invincible", N_( "Invincible" ), NULL }, + { "sad", N_( "Sad" ), NULL }, + { "hot", N_( "Hot" ), NULL }, + { "sick", N_( "Sick" ), NULL }, + { "sleepy", N_( "Sleepy" ), NULL }, + { "bored", N_( "Bored" ), NULL }, + { "cold", N_( "Cold" ), NULL }, + { "confused", N_( "Confused" ), NULL }, + { "hungry", N_( "Hungry" ), NULL }, + { "stressed", N_( "Stressed" ), NULL }, /* Mark the last record. */ { NULL, NULL, NULL } }; @@ -293,14 +293,15 @@ */ static PurpleBuddy* mxit_update_buddy_group( struct MXitSession* session, PurpleBuddy* buddy, PurpleGroup* group ) { - struct contact* contact = NULL; PurpleGroup* current_group = purple_buddy_get_group( buddy ); - PurpleBuddy* newbuddy = NULL; /* make sure the groups actually differs */ if ( strcmp( current_group->name, group->name ) != 0 ) { /* groupnames does not match, so we need to make the update */ + struct contact* contact = purple_buddy_get_protocol_data( buddy ); + PurpleBuddy* newbuddy = NULL; + purple_debug_info( MXIT_PLUGIN_ID, "Moving '%s' from group '%s' to '%s'\n", buddy->alias, current_group->name, group->name ); /* @@ -310,10 +311,10 @@ * again. This is really not ideal and very irritating, but how else then? */ - /* create new buddy */ + /* create new buddy, and transfer 'contact' data */ newbuddy = purple_buddy_new( session->acc, buddy->name, buddy->alias ); - newbuddy->proto_data = buddy->proto_data; - buddy->proto_data = NULL; + purple_buddy_set_protocol_data( newbuddy, contact ); + purple_buddy_set_protocol_data( buddy, NULL ); /* remove the buddy */ purple_blist_remove_buddy( buddy ); @@ -322,7 +323,6 @@ purple_blist_add_buddy( newbuddy, NULL, group, NULL ); /* now re-instate his presence again */ - contact = newbuddy->proto_data; if ( contact ) { /* update the buddy's status (reference: "libpurple/prpl.h") */ @@ -396,7 +396,7 @@ /* create new buddy */ buddy = purple_buddy_new( session->acc, contact->username, contact->alias ); - purple_buddy_set_protocol_data(buddy, contact); + purple_buddy_set_protocol_data( buddy, contact ); /* add new buddy to list */ purple_blist_add_buddy( buddy, NULL, group, NULL ); @@ -728,7 +728,7 @@ */ void mxit_add_buddy( PurpleConnection* gc, PurpleBuddy* buddy, PurpleGroup* group, const char* message ) { - struct MXitSession* session = (struct MXitSession*) gc->proto_data; + struct MXitSession* session = purple_connection_get_protocol_data( gc ); GSList* list = NULL; PurpleBuddy* mxbuddy = NULL; unsigned int i; @@ -804,7 +804,7 @@ */ void mxit_remove_buddy( PurpleConnection* gc, PurpleBuddy* buddy, PurpleGroup* group ) { - struct MXitSession* session = (struct MXitSession*) gc->proto_data; + struct MXitSession* session = purple_connection_get_protocol_data( gc ); const gchar * buddy_name = purple_buddy_get_name( buddy ); purple_debug_info( MXIT_PLUGIN_ID, "mxit_remove_buddy '%s'\n", buddy_name ); @@ -822,7 +822,7 @@ */ void mxit_buddy_alias( PurpleConnection* gc, const char* who, const char* alias ) { - struct MXitSession* session = (struct MXitSession*) gc->proto_data; + struct MXitSession* session = purple_connection_get_protocol_data( gc ); PurpleBuddy* buddy = NULL; PurpleGroup* group = NULL; @@ -856,7 +856,7 @@ */ void mxit_buddy_group( PurpleConnection* gc, const char* who, const char* old_group, const char* new_group ) { - struct MXitSession* session = (struct MXitSession*) gc->proto_data; + struct MXitSession* session = purple_connection_get_protocol_data( gc ); PurpleBuddy* buddy = NULL; purple_debug_info( MXIT_PLUGIN_ID, "mxit_buddy_group from '%s' to '%s'\n", old_group, new_group ); @@ -883,7 +883,7 @@ */ void mxit_rename_group( PurpleConnection* gc, const char* old_name, PurpleGroup* group, GList* moved_buddies ) { - struct MXitSession* session = (struct MXitSession*) gc->proto_data; + struct MXitSession* session = purple_connection_get_protocol_data( gc ); PurpleBuddy* buddy = NULL; GList* item = NULL; diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/mxit/roster.h --- a/libpurple/protocols/mxit/roster.h Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/protocols/mxit/roster.h Mon Aug 29 12:28:49 2011 +0900 @@ -74,7 +74,7 @@ /* MXit contact flags */ -#define MXIT_CFLAG_HIDDEN 0x02 +//#define MXIT_CFLAG_HIDDEN 0x02 /* (DEPRECATED) */ #define MXIT_CFLAG_GATEWAY 0x04 #define MXIT_CFLAG_FOCUS_SEND_BLANK 0x20000 @@ -96,7 +96,7 @@ /* client protocol constants */ #define MXIT_CP_MAX_JID_LEN 64 #define MXIT_CP_MAX_GROUP_LEN 32 -#define MXIT_CP_MAX_ALIAS_LEN 48 +#define MXIT_CP_MAX_ALIAS_LEN 100 #define MXIT_DEFAULT_GROUP "MXit" @@ -106,8 +106,8 @@ */ struct contact { char username[MXIT_CP_MAX_JID_LEN+1]; /* unique contact name (with domain) */ - char alias[MXIT_CP_MAX_GROUP_LEN+1]; /* contact alias (what will be seen) */ - char groupname[MXIT_CP_MAX_ALIAS_LEN+1]; /* contact group name */ + char alias[MXIT_CP_MAX_ALIAS_LEN+1]; /* contact alias (what will be seen) */ + char groupname[MXIT_CP_MAX_GROUP_LEN+1]; /* contact group name */ short type; /* contact type */ short mood; /* contact current mood */ diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/mxit/splashscreen.c --- a/libpurple/protocols/mxit/splashscreen.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/protocols/mxit/splashscreen.c Mon Aug 29 12:28:49 2011 +0900 @@ -144,7 +144,7 @@ */ static void splash_click_ok(PurpleConnection* gc, PurpleRequestFields* fields) { - struct MXitSession* session = (struct MXitSession*) gc->proto_data; + struct MXitSession* session = purple_connection_get_protocol_data(gc); const char* splashId; /* Get current splash ID */ diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/mxit/voicevideo.c --- a/libpurple/protocols/mxit/voicevideo.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/protocols/mxit/voicevideo.c Mon Aug 29 12:28:49 2011 +0900 @@ -63,7 +63,7 @@ */ PurpleMediaCaps mxit_media_caps(PurpleAccount *account, const char *who) { - struct MXitSession* session = purple_account_get_connection(account)->proto_data; + struct MXitSession* session = purple_connection_get_protocol_data(purple_account_get_connection(account)); PurpleBuddy* buddy; struct contact* contact; PurpleMediaCaps capa = PURPLE_MEDIA_CAPS_NONE; @@ -71,7 +71,7 @@ purple_debug_info(MXIT_PLUGIN_ID, "mxit_media_caps: buddy '%s'\n", who); /* We need to have a voice/video server */ - if (strlen(session->voip_server) == 0) + if (!*session->voip_server) return PURPLE_MEDIA_CAPS_NONE; /* find the buddy information for this contact (reference: "libpurple/blist.h") */ @@ -95,7 +95,7 @@ /* and only when they're online */ if (contact->presence == MXIT_PRESENCE_OFFLINE) - return MXIT_PRESENCE_OFFLINE; + return PURPLE_MEDIA_CAPS_NONE; /* they support voice-only */ if (contact->capabilities & MXIT_PFLAG_VOICE) diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/myspace/user.c --- a/libpurple/protocols/myspace/user.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/protocols/myspace/user.c Mon Aug 29 12:28:49 2011 +0900 @@ -128,15 +128,21 @@ } if (user->gender && *user->gender) { + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ purple_notify_user_info_add_pair_plaintext(user_info, _("Gender"), user->gender); } if (user->location && *user->location) { + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ purple_notify_user_info_add_pair_plaintext(user_info, _("Location"), user->location); } /* Other information */ if (user->headline && *user->headline) { + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ purple_notify_user_info_add_pair_plaintext(user_info, _("Headline"), user->headline); } @@ -153,6 +159,8 @@ str = msim_format_now_playing(artist, title); if (str && *str) { + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ purple_notify_user_info_add_pair_plaintext(user_info, _("Song"), str); } g_free(str); @@ -180,8 +188,11 @@ } else if (cv) { client = g_strdup_printf("Build %d", cv); } - if (client && *client) + if (client && *client) { + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ purple_notify_user_info_add_pair_plaintext(user_info, _("Client Version"), client); + } g_free(client); } @@ -195,7 +206,7 @@ else profile = g_strdup_printf("%s", user->id, _("View web profile")); - purple_notify_user_info_add_pair(user_info, NULL, profile); + purple_notify_user_info_add_pair_html(user_info, NULL, profile); g_free(profile); } } diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/novell/novell.c --- a/libpurple/protocols/novell/novell.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/protocols/novell/novell.c Mon Aug 29 12:28:49 2011 +0900 @@ -1515,20 +1515,27 @@ tag = _("User ID"); value = nm_user_record_get_userid(user_record); if (value) { - purple_notify_user_info_add_pair(user_info, tag, value); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, tag, value); } -/* tag = _("DN"); +#if 0 + tag = _("DN"); value = nm_user_record_get_dn(user_record); if (value) { - purple_notify_user_info_add_pair(user_info, tag, value); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, tag, value); } -*/ +#endif /* if 0 */ tag = _("Full name"); value = nm_user_record_get_full_name(user_record); if (value) { - purple_notify_user_info_add_pair(user_info, tag, value); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, tag, value); } count = nm_user_record_get_property_count(user_record); @@ -1538,7 +1545,9 @@ tag = _map_property_tag(nm_property_get_tag(property)); value = nm_property_get_value(property); if (tag && value) { - purple_notify_user_info_add_pair(user_info, tag, value); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, tag, value); } nm_release_property(property); } @@ -2860,10 +2869,13 @@ break; } - purple_notify_user_info_add_pair(user_info, _("Status"), status_str); - - if (text) - purple_notify_user_info_add_pair(user_info, _("Message"), text); + purple_notify_user_info_add_pair_plaintext(user_info, _("Status"), status_str); + + if (text) { + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("Message"), text); + } } } } diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/null/nullprpl.c --- a/libpurple/protocols/null/nullprpl.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/protocols/null/nullprpl.c Mon Aug 29 12:28:49 2011 +0900 @@ -234,7 +234,7 @@ const char *message = purple_status_get_attr_string(status, "message"); char *text; - if (message && strlen(message) > 0) + if (message && *message) text = g_strdup_printf("%s: %s", name, message); else text = g_strdup(name); @@ -258,6 +258,8 @@ PurplePresence *presence = purple_buddy_get_presence(buddy); PurpleStatus *status = purple_presence_get_active_status(presence); char *msg = nullprpl_status_text(buddy); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ purple_notify_user_info_add_pair(info, purple_status_get_name(status), msg); g_free(msg); @@ -265,12 +267,14 @@ if (full) { const char *user_info = purple_account_get_user_info(gc->account); if (user_info) + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ purple_notify_user_info_add_pair(info, _("User info"), user_info); } } else { /* they're not logged in */ - purple_notify_user_info_add_pair(info, _("User info"), _("not logged in")); + purple_notify_user_info_add_pair_plaintext(info, _("User info"), _("not logged in")); } purple_debug_info("nullprpl", "showing %s tooltip for %s\n", @@ -510,6 +514,8 @@ body = purple_account_get_user_info(acct); else body = _("No user info."); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ purple_notify_user_info_add_pair(info, "Info", body); /* show a buddy's user info in a nice dialog box */ @@ -775,10 +781,10 @@ to_username = args[0]; message = args[1]; - if (!to_username || strlen(to_username) == 0) { + if (!to_username || !*to_username) { *error = g_strdup(_("Whisper is missing recipient.")); return PURPLE_CMD_RET_FAILED; - } else if (!message || strlen(message) == 0) { + } else if (!message || !*message) { *error = g_strdup(_("Whisper is missing message.")); return PURPLE_CMD_RET_FAILED; } @@ -927,7 +933,7 @@ purple_conv_chat_set_topic(to, username, topic); - if (topic && strlen(topic) > 0) + if (topic && *topic) msg = g_strdup_printf(_("%s sets topic to: %s"), username, topic); else msg = g_strdup_printf(_("%s clears topic"), username); diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/oscar/family_feedbag.c --- a/libpurple/protocols/oscar/family_feedbag.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/protocols/oscar/family_feedbag.c Mon Aug 29 12:28:49 2011 +0900 @@ -990,7 +990,7 @@ return -EINVAL; /* Either add or remove the 0x0131 TLV from the TLV chain */ - if ((alias != NULL) && (strlen(alias) > 0)) + if (alias && *alias) aim_tlvlist_replace_str(&tmp->data, 0x0131, alias); else aim_tlvlist_remove(&tmp->data, 0x0131); @@ -1020,7 +1020,7 @@ return -EINVAL; /* Either add or remove the 0x0131 TLV from the TLV chain */ - if ((comment != NULL) && (strlen(comment) > 0)) + if (comment && *comment) aim_tlvlist_replace_str(&tmp->data, 0x013c, comment); else aim_tlvlist_remove(&tmp->data, 0x013c); diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/oscar/oft.c --- a/libpurple/protocols/oscar/oft.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/protocols/oscar/oft.c Mon Aug 29 12:28:49 2011 +0900 @@ -589,7 +589,7 @@ { PeerConnection *conn; - conn = xfer->data; + conn = purple_xfer_get_protocol_data(xfer); conn->flags |= PEER_CONNECTION_FLAG_APPROVED; peer_connection_trynext(conn); } @@ -599,7 +599,7 @@ { PeerConnection *conn; - conn = xfer->data; + conn = purple_xfer_get_protocol_data(xfer); /* Tell the other person that we've received everything */ conn->fd = conn->xfer->fd; @@ -617,7 +617,7 @@ PeerConnection *conn; /* Update our rolling checksum. Like Walmart, yo. */ - conn = xfer->data; + conn = purple_xfer_get_protocol_data(xfer); conn->xferdata.recvcsum = peer_oft_checksum_chunk(buffer, size, conn->xferdata.recvcsum, purple_xfer_get_bytes_sent(xfer) & 1); } @@ -655,7 +655,7 @@ gchar *f1 = NULL, *f2 = NULL; gsize dummy; - conn = xfer->data; + conn = purple_xfer_get_protocol_data(xfer); conn->flags |= PEER_CONNECTION_FLAG_APPROVED; /* Make sure the file size can be represented in 32 bits */ @@ -724,7 +724,7 @@ { PeerConnection *conn; - conn = xfer->data; + conn = purple_xfer_get_protocol_data(xfer); /* * If we're done sending, intercept the socket from the core ft code @@ -753,7 +753,7 @@ { PeerConnection *conn; - conn = xfer->data; + conn = purple_xfer_get_protocol_data(xfer); if (conn == NULL) return; diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/oscar/oscar.c --- a/libpurple/protocols/oscar/oscar.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/protocols/oscar/oscar.c Mon Aug 29 12:28:49 2011 +0900 @@ -2278,7 +2278,7 @@ return 0; } -static int purple_parse_clientauto_ch4(OscarData *od, char *who, guint16 reason, guint32 state, char *msg) { +static int purple_parse_clientauto_ch4(OscarData *od, const char *who, guint16 reason, guint32 state, char *msg) { PurpleConnection *gc = od->gc; switch(reason) { @@ -2286,16 +2286,20 @@ char *statusmsg, **splitmsg; PurpleNotifyUserInfo *user_info; + statusmsg = oscar_icqstatus(state); + /* Split at (carriage return/newline)'s, then rejoin later with BRs between. */ - statusmsg = oscar_icqstatus(state); + /* TODO: Don't we need to escape each piece? */ splitmsg = g_strsplit(msg, "\r\n", 0); user_info = purple_notify_user_info_new(); - purple_notify_user_info_add_pair(user_info, _("UIN"), who); - purple_notify_user_info_add_pair(user_info, _("Status"), statusmsg); + purple_notify_user_info_add_pair_plaintext(user_info, _("UIN"), who); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("Status"), statusmsg); purple_notify_user_info_add_section_break(user_info); - purple_notify_user_info_add_pair(user_info, NULL, g_strjoinv("
", splitmsg)); + purple_notify_user_info_add_pair_html(user_info, NULL, g_strjoinv("
", splitmsg)); g_free(statusmsg); g_strfreev(splitmsg); @@ -2309,16 +2313,20 @@ char *statusmsg, **splitmsg; PurpleNotifyUserInfo *user_info; + statusmsg = oscar_icqstatus(state); + /* Split at (carriage return/newline)'s, then rejoin later with BRs between. */ - statusmsg = oscar_icqstatus(state); + /* TODO: Don't we need to escape each piece? */ splitmsg = g_strsplit(msg, "\r\n", 0); user_info = purple_notify_user_info_new(); - purple_notify_user_info_add_pair(user_info, _("UIN"), who); - purple_notify_user_info_add_pair(user_info, _("Status"), statusmsg); + purple_notify_user_info_add_pair_plaintext(user_info, _("UIN"), who); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("Status"), statusmsg); purple_notify_user_info_add_section_break(user_info); - purple_notify_user_info_add_pair(user_info, NULL, g_strjoinv("
", splitmsg)); + purple_notify_user_info_add_pair_html(user_info, NULL, g_strjoinv("
", splitmsg)); g_free(statusmsg); g_strfreev(splitmsg); @@ -5468,7 +5476,7 @@ conn->flags |= PEER_CONNECTION_FLAG_APPROVED; aim_icbm_makecookie(conn->cookie); conn->xfer = xfer; - xfer->data = conn; + purple_xfer_set_protocol_data(xfer, conn); } return xfer; diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/oscar/peer.c --- a/libpurple/protocols/oscar/peer.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/protocols/oscar/peer.c Mon Aug 29 12:28:49 2011 +0900 @@ -212,7 +212,7 @@ if (conn->xfer != NULL) { PurpleXferStatusType status; - conn->xfer->data = NULL; + purple_xfer_set_protocol_data(conn->xfer, NULL); status = purple_xfer_get_status(conn->xfer); if ((status != PURPLE_XFER_STATUS_DONE) && (status != PURPLE_XFER_STATUS_CANCEL_LOCAL) && @@ -1072,7 +1072,7 @@ conn->xfer = purple_xfer_new(account, PURPLE_XFER_RECEIVE, bn); if (conn->xfer) { - conn->xfer->data = conn; + purple_xfer_set_protocol_data(conn->xfer, conn); purple_xfer_ref(conn->xfer); purple_xfer_set_size(conn->xfer, args->info.sendfile.totsize); diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/oscar/userinfo.c --- a/libpurple/protocols/oscar/userinfo.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/protocols/oscar/userinfo.c Mon Aug 29 12:28:49 2011 +0900 @@ -131,21 +131,16 @@ } static void -oscar_user_info_add_pair(PurpleNotifyUserInfo *user_info, const char *name, const char *value) -{ - if (value && value[0]) { - purple_notify_user_info_add_pair(user_info, name, value); - } -} - -static void oscar_user_info_convert_and_add(PurpleAccount *account, OscarData *od, PurpleNotifyUserInfo *user_info, const char *name, const char *value) { gchar *utf8; if (value && value[0] && (utf8 = oscar_utf8_try_convert(account, od, value))) { - purple_notify_user_info_add_pair(user_info, name, utf8); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext. Will + need to check callers of this function. */ + purple_notify_user_info_add_pair_html(user_info, name, utf8); g_free(utf8); } } @@ -158,7 +153,10 @@ if (value && value[0] && (utf8 = oscar_utf8_try_convert(account, od, value))) { gchar *tmp = g_strdup_printf("%s", url_prefix, utf8, utf8); - purple_notify_user_info_add_pair(user_info, name, tmp); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext. Will + need to check callers of this function. */ + purple_notify_user_info_add_pair_html(user_info, name, tmp); g_free(utf8); g_free(tmp); } @@ -295,12 +293,12 @@ } else { description = g_strdup(_(mood)); } - purple_notify_user_info_add_pair(user_info, _("Mood"), description); + purple_notify_user_info_add_pair_html(user_info, _("Mood"), description); g_free(description); } } - purple_notify_user_info_add_pair(user_info, _("Status"), message); + purple_notify_user_info_add_pair_html(user_info, _("Status"), message); g_free(message); } @@ -340,19 +338,19 @@ bi = g_hash_table_lookup(od->buddyinfo, purple_normalize(account, userinfo->bn)); if ((bi != NULL) && (bi->ipaddr != 0)) { - tmp = g_strdup_printf("%hhu.%hhu.%hhu.%hhu", - (bi->ipaddr & 0xff000000) >> 24, - (bi->ipaddr & 0x00ff0000) >> 16, - (bi->ipaddr & 0x0000ff00) >> 8, - (bi->ipaddr & 0x000000ff)); - oscar_user_info_add_pair(user_info, _("IP Address"), tmp); - g_free(tmp); + char tmp2[40]; + sprintf(tmp2, "%hhu.%hhu.%hhu.%hhu", + (bi->ipaddr & 0xff000000) >> 24, + (bi->ipaddr & 0x00ff0000) >> 16, + (bi->ipaddr & 0x0000ff00) >> 8, + (bi->ipaddr & 0x000000ff)); + purple_notify_user_info_add_pair_plaintext(user_info, _("IP Address"), tmp2); } if ((userinfo != NULL) && (userinfo->warnlevel != 0)) { - tmp = g_strdup_printf("%d", (int)(userinfo->warnlevel/10.0 + .5)); - oscar_user_info_add_pair(user_info, _("Warning Level"), tmp); - g_free(tmp); + char tmp2[12]; + sprintf(tmp2, "%d", (int)(userinfo->warnlevel/10.0 + .5)); + purple_notify_user_info_add_pair_plaintext(user_info, _("Warning Level"), tmp2); } if ((b != NULL) && (bname != NULL) && (g != NULL) && (gname != NULL)) { @@ -372,7 +370,7 @@ { PurpleNotifyUserInfo *user_info = purple_notify_user_info_new(); gchar *buf = g_strdup_printf(_("User information not available: %s"), oscar_get_msgerr_reason(error_reason)); - purple_notify_user_info_add_pair(user_info, NULL, buf); + purple_notify_user_info_add_pair_plaintext(user_info, NULL, buf); purple_notify_userinfo(od->gc, buddy, user_info, NULL, NULL); purple_notify_user_info_destroy(user_info); purple_conv_present_error(buddy, purple_connection_get_account(od->gc), buf); @@ -402,16 +400,16 @@ else bi = NULL; - purple_notify_user_info_add_pair(user_info, _("UIN"), who); + purple_notify_user_info_add_pair_plaintext(user_info, _("UIN"), who); oscar_user_info_convert_and_add(account, od, user_info, _("Nick"), info->nick); if ((bi != NULL) && (bi->ipaddr != 0)) { - char *tstr = g_strdup_printf("%hhu.%hhu.%hhu.%hhu", - (bi->ipaddr & 0xff000000) >> 24, - (bi->ipaddr & 0x00ff0000) >> 16, - (bi->ipaddr & 0x0000ff00) >> 8, - (bi->ipaddr & 0x000000ff)); - purple_notify_user_info_add_pair(user_info, _("IP Address"), tstr); - g_free(tstr); + char tstr[40]; + sprintf(tstr, "%hhu.%hhu.%hhu.%hhu", + (bi->ipaddr & 0xff000000) >> 24, + (bi->ipaddr & 0x00ff0000) >> 16, + (bi->ipaddr & 0x0000ff00) >> 8, + (bi->ipaddr & 0x000000ff)); + purple_notify_user_info_add_pair_plaintext(user_info, _("IP Address"), tstr); } oscar_user_info_convert_and_add(account, od, user_info, _("First Name"), info->first); oscar_user_info_convert_and_add(account, od, user_info, _("Last Name"), info->last); @@ -425,7 +423,7 @@ oscar_user_info_convert_and_add(account, od, user_info, _("Mobile Phone"), info->mobile); if (info->gender != 0) - purple_notify_user_info_add_pair(user_info, _("Gender"), (info->gender == 1 ? _("Female") : _("Male"))); + purple_notify_user_info_add_pair_plaintext(user_info, _("Gender"), (info->gender == 1 ? _("Female") : _("Male"))); if ((info->birthyear > 1900) && (info->birthmonth > 0) && (info->birthday > 0)) { /* Initialize the struct properly or strftime() will crash @@ -437,7 +435,7 @@ tm->tm_mon = (int)info->birthmonth - 1; tm->tm_year = (int)info->birthyear - 1900; - /* Ignore dst setting of today to avoid timezone shift between + /* Ignore dst setting of today to avoid timezone shift between * dates in summer and winter time. */ tm->tm_isdst = -1; @@ -451,8 +449,9 @@ if ((info->age > 0) && (info->age < 255)) { char age[5]; snprintf(age, sizeof(age), "%hhd", info->age); - purple_notify_user_info_add_pair(user_info, _("Age"), age); + purple_notify_user_info_add_pair_plaintext(user_info, _("Age"), age); } + /* TODO: Is it correct to pass info->email here...? */ oscar_user_info_convert_and_add_hyperlink(account, od, user_info, _("Personal Web Page"), info->email, ""); if (buddy != NULL) oscar_user_info_append_status(gc, user_info, buddy, /* aim_userinfo_t */ NULL, /* use_html_status */ TRUE); @@ -482,6 +481,7 @@ oscar_user_info_convert_and_add(account, od, user_info, _("Company"), info->workcompany); oscar_user_info_convert_and_add(account, od, user_info, _("Division"), info->workdivision); oscar_user_info_convert_and_add(account, od, user_info, _("Position"), info->workposition); + /* TODO: Is it correct to pass info->email here...? */ oscar_user_info_convert_and_add_hyperlink(account, od, user_info, _("Web Page"), info->email, ""); } @@ -505,7 +505,7 @@ if ((userinfo->present & AIM_USERINFO_PRESENT_IDLE) && userinfo->idletime != 0) { tmp = purple_str_seconds_to_string(userinfo->idletime*60); - oscar_user_info_add_pair(user_info, _("Idle"), tmp); + purple_notify_user_info_add_pair_plaintext(user_info, _("Idle"), tmp); g_free(tmp); } @@ -514,17 +514,18 @@ if ((userinfo->present & AIM_USERINFO_PRESENT_ONLINESINCE) && !oscar_util_valid_name_sms(userinfo->bn)) { /* An SMS contact is always online; its Online Since value is not useful */ time_t t = userinfo->onlinesince; - oscar_user_info_add_pair(user_info, _("Online Since"), purple_date_format_full(localtime(&t))); + purple_notify_user_info_add_pair_plaintext(user_info, _("Online Since"), purple_date_format_full(localtime(&t))); } if (userinfo->present & AIM_USERINFO_PRESENT_MEMBERSINCE) { time_t t = userinfo->membersince; - oscar_user_info_add_pair(user_info, _("Member Since"), purple_date_format_full(localtime(&t))); + purple_notify_user_info_add_pair_plaintext(user_info, _("Member Since"), purple_date_format_full(localtime(&t))); } if (userinfo->capabilities != 0) { tmp = oscar_caps_to_string(userinfo->capabilities); - oscar_user_info_add_pair(user_info, _("Capabilities"), tmp); + if (tmp && *tmp) + purple_notify_user_info_add_pair_plaintext(user_info, _("Capabilities"), tmp); g_free(tmp); } @@ -533,7 +534,11 @@ info_utf8 = oscar_encoding_to_utf8(userinfo->info_encoding, userinfo->info, userinfo->info_len); tmp = oscar_util_format_string(info_utf8, purple_account_get_username(account)); purple_notify_user_info_add_section_break(user_info); - oscar_user_info_add_pair(user_info, _("Profile"), tmp); + if (tmp && *tmp) { + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("Profile"), tmp); + } g_free(tmp); g_free(info_utf8); } @@ -542,7 +547,7 @@ base_profile_url = oscar_util_valid_name_icq(userinfo->bn) ? "http://www.icq.com/people" : "http://profiles.aim.com"; tmp = g_strdup_printf("%s", base_profile_url, purple_normalize(account, userinfo->bn), _("View web profile")); - purple_notify_user_info_add_pair(user_info, NULL, tmp); + purple_notify_user_info_add_pair_html(user_info, NULL, tmp); g_free(tmp); purple_notify_userinfo(gc, userinfo->bn, user_info, NULL, NULL); diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/sametime/sametime.c --- a/libpurple/protocols/sametime/sametime.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/protocols/sametime/sametime.c Mon Aug 29 12:28:49 2011 +0900 @@ -861,7 +861,7 @@ enum mwSametimeUserType type = mwSametimeUser_getType(stuser); g_return_val_if_fail(id != NULL, NULL); - g_return_val_if_fail(strlen(id) > 0, NULL); + g_return_val_if_fail(*id, NULL); buddy = purple_find_buddy_in_group(acct, id, group); if(! buddy) { @@ -2139,7 +2139,7 @@ static void ft_incoming_cancel(PurpleXfer *xfer) { /* incoming transfer rejected or cancelled in-progress */ - struct mwFileTransfer *ft = xfer->data; + struct mwFileTransfer *ft = purple_xfer_get_protocol_data(xfer); if(ft) mwFileTransfer_reject(ft); } @@ -2155,7 +2155,7 @@ struct mwFileTransfer *ft; FILE *fp; - ft = xfer->data; + ft = purple_xfer_get_protocol_data(xfer); fp = g_fopen(xfer->local_filename, "wb"); if(! fp) { @@ -2202,7 +2202,7 @@ { purple_xfer_ref(xfer); mwFileTransfer_setClientData(ft, xfer, (GDestroyNotify) purple_xfer_unref); - xfer->data = ft; + purple_xfer_set_protocol_data(xfer, ft); purple_xfer_set_init_fnc(xfer, ft_incoming_init); purple_xfer_set_cancel_recv_fnc(xfer, ft_incoming_cancel); @@ -2281,7 +2281,7 @@ xfer = mwFileTransfer_getClientData(ft); if(xfer) { - xfer->data = NULL; + purple_xfer_set_protocol_data(xfer, NULL); if(! mwFileTransfer_getRemaining(ft)) { purple_xfer_set_completed(xfer, TRUE); @@ -3337,13 +3337,13 @@ purple_notify_user_info_add_pair_plaintext(user_info, status, message); } else { - purple_notify_user_info_add_pair(user_info, _("Status"), status); + purple_notify_user_info_add_pair_plaintext(user_info, _("Status"), status); } if(full && pd != NULL) { tmp = user_supports_text(pd->srvc_aware, purple_buddy_get_name(b)); if(tmp) { - purple_notify_user_info_add_pair(user_info, _("Supports"), tmp); + purple_notify_user_info_add_pair_plaintext(user_info, _("Supports"), tmp); g_free(tmp); } @@ -4198,46 +4198,47 @@ user_info = purple_notify_user_info_new(); if(purple_str_has_prefix(who, "@E ")) { - purple_notify_user_info_add_pair(user_info, _("External User"), NULL); + purple_notify_user_info_add_pair_html(user_info, _("External User"), NULL); } - purple_notify_user_info_add_pair(user_info, _("User ID"), who); + purple_notify_user_info_add_pair_plaintext(user_info, _("User ID"), who); if(b) { guint32 type; if(purple_buddy_get_server_alias(b)) { - purple_notify_user_info_add_pair(user_info, _("Full Name"), purple_buddy_get_server_alias(b)); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("Full Name"), purple_buddy_get_server_alias(b)); } type = purple_blist_node_get_int((PurpleBlistNode *) b, BUDDY_KEY_CLIENT); if(type) { - tmp = g_strdup(mw_client_name(type)); - if (!tmp) + tmp2 = mw_client_name(type); + if (tmp2) { + purple_notify_user_info_add_pair_plaintext(user_info, _("Last Known Client"), tmp2); + } else { tmp = g_strdup_printf(_("Unknown (0x%04x)
"), type); - - purple_notify_user_info_add_pair(user_info, _("Last Known Client"), tmp); - - g_free(tmp); + purple_notify_user_info_add_pair_html(user_info, _("Last Known Client"), tmp); + g_free(tmp); + } } } tmp = user_supports_text(pd->srvc_aware, who); if(tmp) { - purple_notify_user_info_add_pair(user_info, _("Supports"), tmp); + purple_notify_user_info_add_pair_plaintext(user_info, _("Supports"), tmp); g_free(tmp); } if(b) { - purple_notify_user_info_add_pair(user_info, _("Status"), status_text(b)); + purple_notify_user_info_add_pair_plaintext(user_info, _("Status"), status_text(b)); /* XXX Is this adding a status message in its own section rather than with the "Status" label? */ tmp2 = mwServiceAware_getText(pd->srvc_aware, &idb); if(tmp2 && g_utf8_validate(tmp2, -1, NULL)) { - tmp = g_markup_escape_text(tmp2, -1); purple_notify_user_info_add_section_break(user_info); - purple_notify_user_info_add_pair(user_info, NULL, tmp); - g_free(tmp); + purple_notify_user_info_add_pair_plaintext(user_info, NULL, tmp2); } } @@ -5105,14 +5106,14 @@ purple_xfer_ref(xfer); mwFileTransfer_setClientData(ft, xfer, (GDestroyNotify) purple_xfer_unref); - xfer->data = ft; + purple_xfer_set_protocol_data(xfer, ft); mwFileTransfer_offer(ft); } static void ft_outgoing_cancel(PurpleXfer *xfer) { - struct mwFileTransfer *ft = xfer->data; + struct mwFileTransfer *ft = purple_xfer_get_protocol_data(xfer); DEBUG_INFO("ft_outgoing_cancel called\n"); diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/silc/buddy.c --- a/libpurple/protocols/silc/buddy.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/protocols/silc/buddy.c Mon Aug 29 12:28:49 2011 +0900 @@ -1547,54 +1547,72 @@ return; if (client_entry->nickname) - purple_notify_user_info_add_pair(user_info, _("Nickname"), + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("Nickname"), client_entry->nickname); if (client_entry->username && client_entry->hostname) { g_snprintf(tmp, sizeof(tmp), "%s@%s", client_entry->username, client_entry->hostname); - purple_notify_user_info_add_pair(user_info, _("Username"), tmp); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("Username"), tmp); } if (client_entry->mode) { memset(tmp, 0, sizeof(tmp)); silcpurple_get_umode_string(client_entry->mode, tmp, sizeof(tmp) - strlen(tmp)); - purple_notify_user_info_add_pair(user_info, _("User Modes"), tmp); + purple_notify_user_info_add_pair_plaintext(user_info, _("User Modes"), tmp); } silcpurple_parse_attrs(client_entry->attrs, &moodstr, &statusstr, &contactstr, &langstr, &devicestr, &tzstr, &geostr); if (statusstr) { - purple_notify_user_info_add_pair(user_info, _("Message"), statusstr); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("Message"), statusstr); g_free(statusstr); } if (full) { if (moodstr) { - purple_notify_user_info_add_pair(user_info, _("Mood"), moodstr); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("Mood"), moodstr); g_free(moodstr); } if (contactstr) { - purple_notify_user_info_add_pair(user_info, _("Preferred Contact"), contactstr); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("Preferred Contact"), contactstr); g_free(contactstr); } if (langstr) { - purple_notify_user_info_add_pair(user_info, _("Preferred Language"), langstr); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("Preferred Language"), langstr); g_free(langstr); } if (devicestr) { - purple_notify_user_info_add_pair(user_info, _("Device"), devicestr); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("Device"), devicestr); g_free(devicestr); } if (tzstr) { - purple_notify_user_info_add_pair(user_info, _("Timezone"), tzstr); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("Timezone"), tzstr); g_free(tzstr); } if (geostr) { - purple_notify_user_info_add_pair(user_info, _("Geolocation"), geostr); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("Geolocation"), geostr); g_free(geostr); } } diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/silc/chat.c --- a/libpurple/protocols/silc/chat.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/protocols/silc/chat.c Mon Aug 29 12:28:49 2011 +0900 @@ -1419,7 +1419,8 @@ void silcpurple_roomlist_cancel(PurpleRoomlist *list) { - PurpleConnection *gc = purple_account_get_connection(list->account); + PurpleAccount *account = purple_roomlist_get_account(list); + PurpleConnection *gc = purple_account_get_connection(account); SilcPurple sg; if (!gc) diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/silc/ft.c --- a/libpurple/protocols/silc/ft.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/protocols/silc/ft.c Mon Aug 29 12:28:49 2011 +0900 @@ -76,7 +76,7 @@ if (status == SILC_CLIENT_FILE_MONITOR_CLOSED) { /* All started sessions terminate here */ - xfer->xfer->data = NULL; + purple_xfer_set_protocol_data(xfer->xfer, NULL); purple_xfer_unref(xfer->xfer); silc_free(xfer); return; @@ -150,7 +150,7 @@ static void silcpurple_ftp_cancel(PurpleXfer *x) { - SilcPurpleXfer xfer = x->data; + SilcPurpleXfer xfer = purple_xfer_get_protocol_data(x); if (!xfer) return; @@ -163,7 +163,7 @@ static void silcpurple_ftp_ask_name_cancel(PurpleXfer *x) { - SilcPurpleXfer xfer = x->data; + SilcPurpleXfer xfer = purple_xfer_get_protocol_data(x); if (!xfer) return; @@ -176,7 +176,7 @@ static void silcpurple_ftp_ask_name_ok(PurpleXfer *x) { - SilcPurpleXfer xfer = x->data; + SilcPurpleXfer xfer = purple_xfer_get_protocol_data(x); const char *name; if (!xfer) @@ -212,7 +212,7 @@ static void silcpurple_ftp_request_result(PurpleXfer *x) { - SilcPurpleXfer xfer = x->data; + SilcPurpleXfer xfer = purple_xfer_get_protocol_data(x); SilcClientFileError status; PurpleConnection *gc = xfer->sg->gc; SilcClientConnectionParams params; @@ -337,7 +337,7 @@ purple_xfer_set_cancel_recv_fnc(xfer->xfer, silcpurple_ftp_cancel); xfer->xfer->remote_ip = g_strdup(hostname); xfer->xfer->remote_port = port; - xfer->xfer->data = xfer; + purple_xfer_set_protocol_data(xfer->xfer, xfer); /* File transfer request */ purple_xfer_request(xfer->xfer); @@ -346,7 +346,7 @@ static void silcpurple_ftp_send_cancel(PurpleXfer *x) { - SilcPurpleXfer xfer = x->data; + SilcPurpleXfer xfer = purple_xfer_get_protocol_data(x); if (!xfer) return; @@ -358,7 +358,7 @@ static void silcpurple_ftp_send(PurpleXfer *x) { - SilcPurpleXfer xfer = x->data; + SilcPurpleXfer xfer = purple_xfer_get_protocol_data(x); const char *name; char *local_ip = NULL, *remote_ip = NULL; gboolean local = TRUE; @@ -467,7 +467,7 @@ purple_xfer_set_init_fnc(xfer->xfer, silcpurple_ftp_send); purple_xfer_set_request_denied_fnc(xfer->xfer, silcpurple_ftp_request_denied); purple_xfer_set_cancel_send_fnc(xfer->xfer, silcpurple_ftp_send_cancel); - xfer->xfer->data = xfer; + purple_xfer_set_protocol_data(xfer->xfer, xfer); silc_free(clients); diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/silc/ops.c --- a/libpurple/protocols/silc/ops.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/protocols/silc/ops.c Mon Aug 29 12:28:49 2011 +0900 @@ -1162,7 +1162,7 @@ SilcUInt32 idle, *user_modes; SilcDList channels; SilcClientEntry client_entry; - char tmp[1024], *tmp2; + char tmp[1024]; char *moodstr, *statusstr, *contactstr, *langstr, *devicestr, *tzstr, *geostr; PurpleNotifyUserInfo *user_info; @@ -1184,71 +1184,80 @@ user_modes = va_arg(ap, SilcUInt32 *); user_info = purple_notify_user_info_new(); - tmp2 = g_markup_escape_text(client_entry->nickname, -1); - purple_notify_user_info_add_pair(user_info, _("Nickname"), tmp2); - g_free(tmp2); + purple_notify_user_info_add_pair_plaintext(user_info, _("Nickname"), client_entry->nickname); if (client_entry->realname) { - tmp2 = g_markup_escape_text(client_entry->realname, -1); - purple_notify_user_info_add_pair(user_info, _("Real Name"), tmp2); - g_free(tmp2); + purple_notify_user_info_add_pair_plaintext(user_info, _("Real Name"), client_entry->realname); } - tmp2 = g_markup_escape_text(client_entry->username, -1); if (*client_entry->hostname) { - gchar *tmp3; - tmp3 = g_strdup_printf("%s@%s", tmp2, client_entry->hostname); - purple_notify_user_info_add_pair(user_info, _("Username"), tmp3); - g_free(tmp3); + gchar *tmp2; + tmp2 = g_strdup_printf("%s@%s", client_entry->username, client_entry->hostname); + purple_notify_user_info_add_pair_plaintext(user_info, _("Username"), tmp2); + g_free(tmp2); } else - purple_notify_user_info_add_pair(user_info, _("Username"), tmp2); - g_free(tmp2); + purple_notify_user_info_add_pair_plaintext(user_info, _("Username"), client_entry->username); if (client_entry->mode) { memset(tmp, 0, sizeof(tmp)); silcpurple_get_umode_string(client_entry->mode, tmp, sizeof(tmp) - strlen(tmp)); - purple_notify_user_info_add_pair(user_info, _("User Modes"), tmp); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("User Modes"), tmp); } silcpurple_parse_attrs(client_entry->attrs, &moodstr, &statusstr, &contactstr, &langstr, &devicestr, &tzstr, &geostr); if (moodstr) { - purple_notify_user_info_add_pair(user_info, _("Mood"), moodstr); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("Mood"), moodstr); g_free(moodstr); } if (statusstr) { - tmp2 = g_markup_escape_text(statusstr, -1); - purple_notify_user_info_add_pair(user_info, _("Status Text"), tmp2); + purple_notify_user_info_add_pair_plaintext(user_info, _("Status Text"), statusstr); g_free(statusstr); - g_free(tmp2); } if (contactstr) { - purple_notify_user_info_add_pair(user_info, _("Preferred Contact"), contactstr); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("Preferred Contact"), contactstr); g_free(contactstr); } if (langstr) { - purple_notify_user_info_add_pair(user_info, _("Preferred Language"), langstr); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("Preferred Language"), langstr); g_free(langstr); } if (devicestr) { - purple_notify_user_info_add_pair(user_info, _("Device"), devicestr); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("Device"), devicestr); g_free(devicestr); } if (tzstr) { - purple_notify_user_info_add_pair(user_info, _("Timezone"), tzstr); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("Timezone"), tzstr); g_free(tzstr); } if (geostr) { - purple_notify_user_info_add_pair(user_info, _("Geolocation"), geostr); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("Geolocation"), geostr); g_free(geostr); } - if (*client_entry->server) - purple_notify_user_info_add_pair(user_info, _("Server"), client_entry->server); + if (*client_entry->server) { + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("Server"), client_entry->server); + } if (channels && user_modes) { SilcChannelPayload entry; @@ -1266,9 +1275,7 @@ silc_strncat(tmp, sizeof(tmp) - 1, " ", 1); silc_free(m); } - tmp2 = g_markup_escape_text(tmp, -1); - purple_notify_user_info_add_pair(user_info, _("Currently on"), tmp2); - g_free(tmp2); + purple_notify_user_info_add_pair_plaintext(user_info, _("Currently on"), tmp); } if (client_entry->public_key) { @@ -1279,8 +1286,8 @@ if (pk) { fingerprint = silc_hash_fingerprint(NULL, pk, pk_len); babbleprint = silc_hash_babbleprint(NULL, pk, pk_len); - purple_notify_user_info_add_pair(user_info, _("Public Key Fingerprint"), fingerprint); - purple_notify_user_info_add_pair(user_info, _("Public Key Babbleprint"), babbleprint); + purple_notify_user_info_add_pair_plaintext(user_info, _("Public Key Fingerprint"), fingerprint); + purple_notify_user_info_add_pair_plaintext(user_info, _("Public Key Babbleprint"), babbleprint); silc_free(fingerprint); silc_free(babbleprint); silc_free(pk); @@ -1304,7 +1311,7 @@ case SILC_COMMAND_WHOWAS: { SilcClientEntry client_entry; - char *nickname, *realname, *username, *tmp; + char *nickname, *realname, *username; PurpleNotifyUserInfo *user_info; if (status != SILC_STATUS_OK) { @@ -1322,27 +1329,23 @@ break; user_info = purple_notify_user_info_new(); - tmp = g_markup_escape_text(nickname, -1); - purple_notify_user_info_add_pair(user_info, _("Nickname"), tmp); - g_free(tmp); - if (realname) { - tmp = g_markup_escape_text(realname, -1); - purple_notify_user_info_add_pair(user_info, _("Real Name"), tmp); - g_free(tmp); - } + purple_notify_user_info_add_pair_plaintext(user_info, _("Nickname"), nickname); + if (realname) + purple_notify_user_info_add_pair_plaintext(user_info, _("Real Name"), realname); if (username) { - tmp = g_markup_escape_text(username, -1); if (client_entry && *client_entry->hostname) { - gchar *tmp3; - tmp3 = g_strdup_printf("%s@%s", tmp, client_entry->hostname); - purple_notify_user_info_add_pair(user_info, _("Username"), tmp3); - g_free(tmp3); + gchar *tmp; + tmp = g_strdup_printf("%s@%s", username, client_entry->hostname); + purple_notify_user_info_add_pair_plaintext(user_info, _("Username"), tmp); + g_free(tmp); } else - purple_notify_user_info_add_pair(user_info, _("Username"), tmp); - g_free(tmp); + purple_notify_user_info_add_pair_plaintext(user_info, _("Username"), username); } - if (client_entry && *client_entry->server) - purple_notify_user_info_add_pair(user_info, _("Server"), client_entry->server); + if (client_entry && *client_entry->server) { + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("Server"), client_entry->server); + } if (client_entry && client_entry->public_key) { @@ -1353,8 +1356,8 @@ if (pk) { fingerprint = silc_hash_fingerprint(NULL, pk, pk_len); babbleprint = silc_hash_babbleprint(NULL, pk, pk_len); - purple_notify_user_info_add_pair(user_info, _("Public Key Fingerprint"), fingerprint); - purple_notify_user_info_add_pair(user_info, _("Public Key Babbleprint"), babbleprint); + purple_notify_user_info_add_pair_plaintext(user_info, _("Public Key Fingerprint"), fingerprint); + purple_notify_user_info_add_pair_plaintext(user_info, _("Public Key Babbleprint"), babbleprint); silc_free(fingerprint); silc_free(babbleprint); silc_free(pk); diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/silc10/Makefile.am --- a/libpurple/protocols/silc10/Makefile.am Mon Aug 22 11:20:05 2011 +0900 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -EXTRA_DIST = \ - Makefile.mingw \ - README \ - TODO - -pkgdir = $(libdir)/purple-$(PURPLE_MAJOR_VERSION) - -SILCSOURCES = silc.c silcpurple.h buddy.c chat.c ft.c ops.c pk.c util.c wb.c wb.h - -AM_CFLAGS = $(st) - -libsilcpurple_la_LDFLAGS = -module -avoid-version - -if STATIC_SILC - -st = -DPURPLE_STATIC_PRPL $(SILC_CFLAGS) -noinst_LTLIBRARIES = libsilcpurple.la -libsilcpurple_la_SOURCES = $(SILCSOURCES) -libsilcpurple_la_CFLAGS = $(AM_CFLAGS) -libsilcpurple_la_LIBADD = $(SILC_LIBS) - -else - -st = $(SILC_CFLAGS) -pkg_LTLIBRARIES = libsilcpurple.la -libsilcpurple_la_SOURCES = $(SILCSOURCES) -libsilcpurple_la_LIBADD = $(GLIB_LIBS) $(SILC_LIBS) - -endif - -AM_CPPFLAGS = \ - -I$(top_srcdir)/libpurple \ - -I$(top_builddir)/libpurple \ - $(DEBUG_CFLAGS) \ - $(GLIB_CFLAGS) \ - $(SILC_CFLAGS) diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/silc10/Makefile.mingw --- a/libpurple/protocols/silc10/Makefile.mingw Mon Aug 22 11:20:05 2011 +0900 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,93 +0,0 @@ -# -# Makefile.mingw -# -# Description: Makefile for win32 (mingw) version of libsilc protocol plugin -# - -PIDGIN_TREE_TOP := ../../.. -include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak - -DEFINES := $(subst -DWIN32_LEAN_AND_MEAN,,$(DEFINES)) - -TARGET = libsilc -NEEDED_DLLS = $(SILC_TOOLKIT)/lib/silc.dll \ - $(SILC_TOOLKIT)/lib/silcclient.dll -TYPE = PLUGIN - -# Static or Plugin... -ifeq ($(TYPE),STATIC) - DEFINES += -DSTATIC - DLL_INSTALL_DIR = $(PURPLE_INSTALL_DIR) -else -ifeq ($(TYPE),PLUGIN) - DLL_INSTALL_DIR = $(PURPLE_INSTALL_PLUGINS_DIR) -endif -endif - -## -## INCLUDE PATHS -## -INCLUDE_PATHS += -I. \ - -I$(GTK_TOP)/include \ - -I$(GTK_TOP)/include/glib-2.0 \ - -I$(GTK_TOP)/lib/glib-2.0/include \ - -I$(PURPLE_TOP) \ - -I$(PURPLE_TOP)/win32 \ - -I$(PIDGIN_TREE_TOP) \ - -I$(SILC_TOOLKIT)/include - -LIB_PATHS += -L$(GTK_TOP)/lib \ - -L$(PURPLE_TOP) \ - -L$(SILC_TOOLKIT)/lib - -## -## SOURCES, OBJECTS -## -C_SRC = silc.c \ - buddy.c \ - chat.c \ - ft.c \ - ops.c \ - pk.c \ - util.c \ - wb.c - -OBJECTS = $(C_SRC:%.c=%.o) - -## -## LIBRARIES -## -LIBS = \ - -lglib-2.0 \ - -lws2_32 \ - -lintl \ - -lpurple \ - -lsilc \ - -lsilcclient - -include $(PIDGIN_COMMON_RULES) - -## -## TARGET DEFINITIONS -## -.PHONY: all install clean - -all: $(TARGET).dll - -install: all $(DLL_INSTALL_DIR) $(PURPLE_INSTALL_DIR) - cp $(TARGET).dll $(DLL_INSTALL_DIR) - cp $(NEEDED_DLLS) $(PURPLE_INSTALL_DIR) - -$(OBJECTS): $(PURPLE_CONFIG_H) - -$(TARGET).dll: $(PURPLE_DLL).a $(OBJECTS) - $(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -Wl,--image-base,0x64000000 -o $(TARGET).dll - -## -## CLEAN RULES -## -clean: - rm -f $(OBJECTS) - rm -f $(TARGET).dll - -include $(PIDGIN_COMMON_TARGETS) diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/silc10/README --- a/libpurple/protocols/silc10/README Mon Aug 22 11:20:05 2011 +0900 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,31 +0,0 @@ -SILC Purple Plugin -================== - -This is the Purple protocol plugin of the protocol called Secure Internet -Live Conferencing (SILC). The implementation will use the SILC Toolkit, -freely available from the http://silcnet.org/ site, for the actual SILC -protocol implementation. - -To include SILC into Purple, one needs to first compile and install -the SILC Toolkit. It is done as follows: - - ./configure --enable-shared - make - make install - -This will compile shared libraries of the SILC Toolkit. If the --prefix -is not given to ./configure, the binaries are installed into the -/usr/local/silc directory. - -Once the Toolkit is installed one needs to tell Purple's ./configure -script where the SILC Toolkit is located. It is done as simply as: - - ./configure - -if pkg-config is installed in your system. If it is isn't it's done as: - - ./configure --with-silc-libs=/path/to/silc/lib - --with-silc-includes=/path/to/silc/include - -If the SILC Toolkit cannot be found then the SILC protocol plugin will -not be compiled. diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/silc10/TODO --- a/libpurple/protocols/silc10/TODO Mon Aug 22 11:20:05 2011 +0900 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -Features TODO (maybe) -===================== - -Preferences - - Add joined channels to buddy list automatically (during - session) - - Add joined channels to buddy list automatically permanently - diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/silc10/buddy.c --- a/libpurple/protocols/silc10/buddy.c Mon Aug 22 11:20:05 2011 +0900 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1748 +0,0 @@ -/* - - silcpurple_buddy.c - - Author: Pekka Riikonen - - Copyright (C) 2004 Pekka Riikonen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - -*/ - -#include "silcincludes.h" -#include "silcclient.h" -#include "silcpurple.h" -#include "wb.h" - -/***************************** Key Agreement *********************************/ - -static void -silcpurple_buddy_keyagr(PurpleBlistNode *node, gpointer data); - -static void -silcpurple_buddy_keyagr_do(PurpleConnection *gc, const char *name, - gboolean force_local); - -typedef struct { - char *nick; - PurpleConnection *gc; -} *SilcPurpleResolve; - -static void -silcpurple_buddy_keyagr_resolved(SilcClient client, - SilcClientConnection conn, - SilcClientEntry *clients, - SilcUInt32 clients_count, - void *context) -{ - PurpleConnection *gc = client->application; - SilcPurpleResolve r = context; - char tmp[256]; - - if (!clients) { - g_snprintf(tmp, sizeof(tmp), - _("User %s is not present in the network"), r->nick); - purple_notify_error(gc, _("Key Agreement"), - _("Cannot perform the key agreement"), tmp); - silc_free(r->nick); - silc_free(r); - return; - } - - silcpurple_buddy_keyagr_do(gc, r->nick, FALSE); - silc_free(r->nick); - silc_free(r); -} - -typedef struct { - gboolean responder; -} *SilcPurpleKeyAgr; - -static void -silcpurple_buddy_keyagr_cb(SilcClient client, - SilcClientConnection conn, - SilcClientEntry client_entry, - SilcKeyAgreementStatus status, - SilcSKEKeyMaterial *key, - void *context) -{ - PurpleConnection *gc = client->application; - SilcPurple sg = gc->proto_data; - SilcPurpleKeyAgr a = context; - - if (!sg->conn) - return; - - switch (status) { - case SILC_KEY_AGREEMENT_OK: - { - PurpleConversation *convo; - char tmp[128]; - - /* Set the private key for this client */ - silc_client_del_private_message_key(client, conn, client_entry); - silc_client_add_private_message_key_ske(client, conn, client_entry, - NULL, NULL, key, a->responder); - silc_ske_free_key_material(key); - - - /* Open IM window */ - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, - client_entry->nickname, sg->account); - if (convo) { - /* we don't have windows in the core anymore...but we may want to - * provide some method for asking the UI to show the window - purple_conv_window_show(purple_conversation_get_window(convo)); - */ - } else { - convo = purple_conversation_new(PURPLE_CONV_TYPE_IM, sg->account, - client_entry->nickname); - } - g_snprintf(tmp, sizeof(tmp), "%s [private key]", client_entry->nickname); - purple_conversation_set_title(convo, tmp); - } - break; - - case SILC_KEY_AGREEMENT_ERROR: - purple_notify_error(gc, _("Key Agreement"), - _("Error occurred during key agreement"), NULL); - break; - - case SILC_KEY_AGREEMENT_FAILURE: - purple_notify_error(gc, _("Key Agreement"), _("Key Agreement failed"), NULL); - break; - - case SILC_KEY_AGREEMENT_TIMEOUT: - purple_notify_error(gc, _("Key Agreement"), - _("Timeout during key agreement"), NULL); - break; - - case SILC_KEY_AGREEMENT_ABORTED: - purple_notify_error(gc, _("Key Agreement"), - _("Key agreement was aborted"), NULL); - break; - - case SILC_KEY_AGREEMENT_ALREADY_STARTED: - purple_notify_error(gc, _("Key Agreement"), - _("Key agreement is already started"), NULL); - break; - - case SILC_KEY_AGREEMENT_SELF_DENIED: - purple_notify_error(gc, _("Key Agreement"), - _("Key agreement cannot be started with yourself"), - NULL); - break; - - default: - break; - } - - silc_free(a); -} - -static void -silcpurple_buddy_keyagr_do(PurpleConnection *gc, const char *name, - gboolean force_local) -{ - SilcPurple sg = gc->proto_data; - SilcClientEntry *clients; - SilcUInt32 clients_count; - char *local_ip = NULL, *remote_ip = NULL; - gboolean local = TRUE; - char *nickname; - SilcPurpleKeyAgr a; - - if (!sg->conn || !name) - return; - - if (!silc_parse_userfqdn(name, &nickname, NULL)) - return; - - /* Find client entry */ - clients = silc_client_get_clients_local(sg->client, sg->conn, nickname, name, - &clients_count); - if (!clients) { - /* Resolve unknown user */ - SilcPurpleResolve r = silc_calloc(1, sizeof(*r)); - if (!r) - return; - r->nick = g_strdup(name); - r->gc = gc; - silc_client_get_clients(sg->client, sg->conn, nickname, NULL, - silcpurple_buddy_keyagr_resolved, r); - silc_free(nickname); - return; - } - - /* Resolve the local IP from the outgoing socket connection. We resolve - it to check whether we have a private range IP address or public IP - address. If we have public then we will assume that we are not behind - NAT and will provide automatically the point of connection to the - agreement. If we have private range address we assume that we are - behind NAT and we let the responder provide the point of connection. - - The algorithm also checks the remote IP address of server connection. - If it is private range address and we have private range address we - assume that we are chatting in LAN and will provide the point of - connection. - - Naturally this algorithm does not always get things right. */ - - if (silc_net_check_local_by_sock(sg->conn->sock->sock, NULL, &local_ip)) { - /* Check if the IP is private */ - if (!force_local && silcpurple_ip_is_private(local_ip)) { - local = FALSE; - - /* Local IP is private, resolve the remote server IP to see whether - we are talking to Internet or just on LAN. */ - if (silc_net_check_host_by_sock(sg->conn->sock->sock, NULL, - &remote_ip)) - if (silcpurple_ip_is_private(remote_ip)) - /* We assume we are in LAN. Let's provide - the connection point. */ - local = TRUE; - } - } - - if (force_local) - local = TRUE; - - if (local && !local_ip) - local_ip = silc_net_localip(); - - a = silc_calloc(1, sizeof(*a)); - if (!a) - return; - a->responder = local; - - /* Send the key agreement request */ - silc_client_send_key_agreement(sg->client, sg->conn, clients[0], - local ? local_ip : NULL, NULL, 0, 60, - silcpurple_buddy_keyagr_cb, a); - - silc_free(local_ip); - silc_free(remote_ip); - silc_free(clients); -} - -typedef struct { - SilcClient client; - SilcClientConnection conn; - SilcClientID client_id; - char *hostname; - SilcUInt16 port; -} *SilcPurpleKeyAgrAsk; - -static void -silcpurple_buddy_keyagr_request_cb(SilcPurpleKeyAgrAsk a, gint id) -{ - SilcPurpleKeyAgr ai; - SilcClientEntry client_entry; - - if (id != 1) - goto out; - - /* Get the client entry. */ - client_entry = silc_client_get_client_by_id(a->client, a->conn, - &a->client_id); - if (!client_entry) { - purple_notify_error(a->client->application, _("Key Agreement"), - _("The remote user is not present in the network any more"), - NULL); - goto out; - } - - /* If the hostname was provided by the requestor perform the key agreement - now. Otherwise, we will send him a request to connect to us. */ - if (a->hostname) { - ai = silc_calloc(1, sizeof(*ai)); - if (!ai) - goto out; - ai->responder = FALSE; - silc_client_perform_key_agreement(a->client, a->conn, client_entry, - a->hostname, a->port, - silcpurple_buddy_keyagr_cb, ai); - } else { - /* Send request. Force us as the point of connection since requestor - did not provide the point of connection. */ - silcpurple_buddy_keyagr_do(a->client->application, - client_entry->nickname, TRUE); - } - - out: - silc_free(a->hostname); - silc_free(a); -} - -void silcpurple_buddy_keyagr_request(SilcClient client, - SilcClientConnection conn, - SilcClientEntry client_entry, - const char *hostname, SilcUInt16 port) -{ - char tmp[128], tmp2[128]; - SilcPurpleKeyAgrAsk a; - PurpleConnection *gc = client->application; - - g_snprintf(tmp, sizeof(tmp), - _("Key agreement request received from %s. Would you like to " - "perform the key agreement?"), client_entry->nickname); - if (hostname) - g_snprintf(tmp2, sizeof(tmp2), - _("The remote user is waiting key agreement on:\n" - "Remote host: %s\nRemote port: %d"), hostname, port); - - a = silc_calloc(1, sizeof(*a)); - if (!a) - return; - a->client = client; - a->conn = conn; - a->client_id = *client_entry->id; - if (hostname) - a->hostname = strdup(hostname); - a->port = port; - - purple_request_action(client->application, _("Key Agreement Request"), tmp, - hostname ? tmp2 : NULL, 1, gc->account, client_entry->nickname, - NULL, a, 2, _("Yes"), G_CALLBACK(silcpurple_buddy_keyagr_request_cb), - _("No"), G_CALLBACK(silcpurple_buddy_keyagr_request_cb)); -} - -static void -silcpurple_buddy_keyagr(PurpleBlistNode *node, gpointer data) -{ - PurpleBuddy *buddy; - - buddy = (PurpleBuddy *)node; - silcpurple_buddy_keyagr_do(buddy->account->gc, buddy->name, FALSE); -} - - -/**************************** Static IM Key **********************************/ - -static void -silcpurple_buddy_resetkey(PurpleBlistNode *node, gpointer data) -{ - PurpleBuddy *b; - PurpleConnection *gc; - SilcPurple sg; - char *nickname; - SilcClientEntry *clients; - SilcUInt32 clients_count; - - g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); - - b = (PurpleBuddy *) node; - gc = purple_account_get_connection(b->account); - sg = gc->proto_data; - - if (!silc_parse_userfqdn(b->name, &nickname, NULL)) - return; - - /* Find client entry */ - clients = silc_client_get_clients_local(sg->client, sg->conn, - nickname, b->name, - &clients_count); - if (!clients) { - silc_free(nickname); - return; - } - - clients[0]->prv_resp = FALSE; - silc_client_del_private_message_key(sg->client, sg->conn, - clients[0]); - silc_free(clients); - silc_free(nickname); -} - -typedef struct { - SilcClient client; - SilcClientConnection conn; - SilcClientID client_id; -} *SilcPurplePrivkey; - -static void -silcpurple_buddy_privkey(PurpleConnection *gc, const char *name); - -static void -silcpurple_buddy_privkey_cb(SilcPurplePrivkey p, const char *passphrase) -{ - SilcClientEntry client_entry; - - if (!passphrase || !(*passphrase)) { - silc_free(p); - return; - } - - /* Get the client entry. */ - client_entry = silc_client_get_client_by_id(p->client, p->conn, - &p->client_id); - if (!client_entry) { - purple_notify_error(p->client->application, _("IM With Password"), - _("The remote user is not present in the network any more"), - NULL); - silc_free(p); - return; - } - - /* Set the private message key */ - silc_client_del_private_message_key(p->client, p->conn, - client_entry); - silc_client_add_private_message_key(p->client, p->conn, - client_entry, NULL, NULL, - (unsigned char *)passphrase, - strlen(passphrase), FALSE, - client_entry->prv_resp); - if (!client_entry->prv_resp) - silc_client_send_private_message_key_request(p->client, - p->conn, - client_entry); - silc_free(p); -} - -static void -silcpurple_buddy_privkey_resolved(SilcClient client, - SilcClientConnection conn, - SilcClientEntry *clients, - SilcUInt32 clients_count, - void *context) -{ - char tmp[256]; - - if (!clients) { - g_snprintf(tmp, sizeof(tmp), - _("User %s is not present in the network"), - (const char *)context); - purple_notify_error(client->application, _("IM With Password"), - _("Cannot set IM key"), tmp); - g_free(context); - return; - } - - silcpurple_buddy_privkey(client->application, context); - silc_free(context); -} - -static void -silcpurple_buddy_privkey(PurpleConnection *gc, const char *name) -{ - SilcPurple sg = gc->proto_data; - char *nickname; - SilcPurplePrivkey p; - SilcClientEntry *clients; - SilcUInt32 clients_count; - - if (!name) - return; - if (!silc_parse_userfqdn(name, &nickname, NULL)) - return; - - /* Find client entry */ - clients = silc_client_get_clients_local(sg->client, sg->conn, - nickname, name, - &clients_count); - if (!clients) { - silc_client_get_clients(sg->client, sg->conn, nickname, NULL, - silcpurple_buddy_privkey_resolved, - g_strdup(name)); - silc_free(nickname); - return; - } - - p = silc_calloc(1, sizeof(*p)); - if (!p) - return; - p->client = sg->client; - p->conn = sg->conn; - p->client_id = *clients[0]->id; - purple_request_input(gc, _("IM With Password"), NULL, - _("Set IM Password"), NULL, FALSE, TRUE, NULL, - _("OK"), G_CALLBACK(silcpurple_buddy_privkey_cb), - _("Cancel"), G_CALLBACK(silcpurple_buddy_privkey_cb), - gc->account, NULL, NULL, p); - - silc_free(clients); - silc_free(nickname); -} - -static void -silcpurple_buddy_privkey_menu(PurpleBlistNode *node, gpointer data) -{ - PurpleBuddy *buddy; - PurpleConnection *gc; - - g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); - - buddy = (PurpleBuddy *) node; - gc = purple_account_get_connection(buddy->account); - - silcpurple_buddy_privkey(gc, buddy->name); -} - - -/**************************** Get Public Key *********************************/ - -typedef struct { - SilcClient client; - SilcClientConnection conn; - SilcClientID client_id; -} *SilcPurpleBuddyGetkey; - -static void -silcpurple_buddy_getkey(PurpleConnection *gc, const char *name); - -static void -silcpurple_buddy_getkey_cb(SilcPurpleBuddyGetkey g, - SilcClientCommandReplyContext cmd) -{ - SilcClientEntry client_entry; - unsigned char *pk; - SilcUInt32 pk_len; - - /* Get the client entry. */ - client_entry = silc_client_get_client_by_id(g->client, g->conn, - &g->client_id); - if (!client_entry) { - purple_notify_error(g->client->application, _("Get Public Key"), - _("The remote user is not present in the network any more"), - NULL); - silc_free(g); - return; - } - - if (!client_entry->public_key) { - silc_free(g); - return; - } - - /* Now verify the public key */ - pk = silc_pkcs_public_key_encode(client_entry->public_key, &pk_len); - silcpurple_verify_public_key(g->client, g->conn, client_entry->nickname, - SILC_SOCKET_TYPE_CLIENT, - pk, pk_len, SILC_SKE_PK_TYPE_SILC, - NULL, NULL); - silc_free(pk); - silc_free(g); -} - -static void -silcpurple_buddy_getkey_resolved(SilcClient client, - SilcClientConnection conn, - SilcClientEntry *clients, - SilcUInt32 clients_count, - void *context) -{ - char tmp[256]; - - if (!clients) { - g_snprintf(tmp, sizeof(tmp), - _("User %s is not present in the network"), - (const char *)context); - purple_notify_error(client->application, _("Get Public Key"), - _("Cannot fetch the public key"), tmp); - g_free(context); - return; - } - - silcpurple_buddy_getkey(client->application, context); - silc_free(context); -} - -static void -silcpurple_buddy_getkey(PurpleConnection *gc, const char *name) -{ - SilcPurple sg = gc->proto_data; - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - SilcClientEntry *clients; - SilcUInt32 clients_count; - SilcPurpleBuddyGetkey g; - char *nickname; - - if (!name) - return; - - if (!silc_parse_userfqdn(name, &nickname, NULL)) - return; - - /* Find client entry */ - clients = silc_client_get_clients_local(client, conn, nickname, name, - &clients_count); - if (!clients) { - silc_client_get_clients(client, conn, nickname, NULL, - silcpurple_buddy_getkey_resolved, - g_strdup(name)); - silc_free(nickname); - return; - } - - /* Call GETKEY */ - g = silc_calloc(1, sizeof(*g)); - if (!g) - return; - g->client = client; - g->conn = conn; - g->client_id = *clients[0]->id; - silc_client_command_call(client, conn, NULL, "GETKEY", - clients[0]->nickname, NULL); - silc_client_command_pending(conn, SILC_COMMAND_GETKEY, - conn->cmd_ident, - (SilcCommandCb)silcpurple_buddy_getkey_cb, g); - silc_free(clients); - silc_free(nickname); -} - -static void -silcpurple_buddy_getkey_menu(PurpleBlistNode *node, gpointer data) -{ - PurpleBuddy *buddy; - PurpleConnection *gc; - - g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); - - buddy = (PurpleBuddy *) node; - gc = purple_account_get_connection(buddy->account); - - silcpurple_buddy_getkey(gc, buddy->name); -} - -static void -silcpurple_buddy_showkey(PurpleBlistNode *node, gpointer data) -{ - PurpleBuddy *b; - PurpleConnection *gc; - SilcPurple sg; - SilcPublicKey public_key; - const char *pkfile; - - g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); - - b = (PurpleBuddy *) node; - gc = purple_account_get_connection(b->account); - sg = gc->proto_data; - - pkfile = purple_blist_node_get_string(node, "public-key"); - if (!silc_pkcs_load_public_key(pkfile, &public_key, SILC_PKCS_FILE_PEM) && - !silc_pkcs_load_public_key(pkfile, &public_key, SILC_PKCS_FILE_BIN)) { - purple_notify_error(gc, - _("Show Public Key"), - _("Could not load public key"), NULL); - return; - } - - silcpurple_show_public_key(sg, b->name, public_key, NULL, NULL); - silc_pkcs_public_key_free(public_key); -} - - -/**************************** Buddy routines *********************************/ - -/* The buddies are implemented by using the WHOIS and WATCH commands that - can be used to search users by their public key. Since nicknames aren't - unique in SILC we cannot trust the buddy list using their nickname. We - associate public keys to buddies and use those to search and watch - in the network. - - The problem is that Purple does not return PurpleBuddy contexts to the - callbacks but the buddy names. Naturally, this is not going to work - with SILC. But, for now, we have to do what we can... */ - -typedef struct { - SilcClient client; - SilcClientConnection conn; - SilcClientID client_id; - PurpleBuddy *b; - unsigned char *offline_pk; - SilcUInt32 offline_pk_len; - unsigned int offline : 1; - unsigned int pubkey_search : 1; - unsigned int init : 1; -} *SilcPurpleBuddyRes; - -static void -silcpurple_add_buddy_ask_pk_cb(SilcPurpleBuddyRes r, gint id); -static void -silcpurple_add_buddy_resolved(SilcClient client, - SilcClientConnection conn, - SilcClientEntry *clients, - SilcUInt32 clients_count, - void *context); - -void silcpurple_get_info(PurpleConnection *gc, const char *who) -{ - SilcPurple sg = gc->proto_data; - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - SilcClientEntry client_entry; - PurpleBuddy *b; - const char *filename, *nick = who; - char tmp[256]; - - if (!who) - return; - if (strlen(who) > 1 && who[0] == '@') - nick = who + 1; - if (strlen(who) > 1 && who[0] == '*') - nick = who + 1; - if (strlen(who) > 2 && who[0] == '*' && who[1] == '@') - nick = who + 2; - - b = purple_find_buddy(gc->account, nick); - if (b) { - /* See if we have this buddy's public key. If we do use that - to search the details. */ - filename = purple_blist_node_get_string((PurpleBlistNode *)b, "public-key"); - if (filename) { - /* Call WHOIS. The user info is displayed in the WHOIS - command reply. */ - silc_client_command_call(client, conn, NULL, "WHOIS", - "-details", "-pubkey", filename, NULL); - return; - } - - if (!b->proto_data) { - g_snprintf(tmp, sizeof(tmp), - _("User %s is not present in the network"), b->name); - purple_notify_error(gc, _("User Information"), - _("Cannot get user information"), tmp); - return; - } - - client_entry = silc_client_get_client_by_id(client, conn, b->proto_data); - if (client_entry) { - /* Call WHOIS. The user info is displayed in the WHOIS - command reply. */ - silc_client_command_call(client, conn, NULL, "WHOIS", - client_entry->nickname, "-details", NULL); - } - } else { - /* Call WHOIS just with nickname. */ - silc_client_command_call(client, conn, NULL, "WHOIS", nick, NULL); - } -} - -static void -silcpurple_add_buddy_pk_no(SilcPurpleBuddyRes r) -{ - char tmp[512]; - g_snprintf(tmp, sizeof(tmp), _("The %s buddy is not trusted"), - r->b->name); - purple_notify_error(r->client->application, _("Add Buddy"), tmp, - _("You cannot receive buddy notifications until you " - "import his/her public key. You can use the Get Public Key " - "command to get the public key.")); - purple_prpl_got_user_status(purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), SILCPURPLE_STATUS_ID_OFFLINE, NULL); -} - -static void -silcpurple_add_buddy_save(bool success, void *context) -{ - SilcPurpleBuddyRes r = context; - PurpleBuddy *b = r->b; - SilcClient client = r->client; - SilcClientEntry client_entry; - SilcAttributePayload attr; - SilcAttribute attribute; - SilcVCardStruct vcard; - SilcAttributeObjMime message, extension; -#ifdef SILC_ATTRIBUTE_USER_ICON - SilcAttributeObjMime usericon; -#endif - SilcAttributeObjPk serverpk, usersign, serversign; - gboolean usign_success = TRUE, ssign_success = TRUE; - char filename[512], filename2[512], *fingerprint = NULL, *tmp; - SilcUInt32 len; - int i; - - if (!success) { - /* The user did not trust the public key. */ - silcpurple_add_buddy_pk_no(r); - silc_free(r); - return; - } - - if (r->offline) { - /* User is offline. Associate the imported public key with - this user. */ - fingerprint = silc_hash_fingerprint(NULL, r->offline_pk, - r->offline_pk_len); - for (i = 0; i < strlen(fingerprint); i++) - if (fingerprint[i] == ' ') - fingerprint[i] = '_'; - g_snprintf(filename, sizeof(filename) - 1, - "%s" G_DIR_SEPARATOR_S "clientkeys" G_DIR_SEPARATOR_S "clientkey_%s.pub", - silcpurple_silcdir(), fingerprint); - purple_blist_node_set_string((PurpleBlistNode *)b, "public-key", filename); - purple_prpl_got_user_status(purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), SILCPURPLE_STATUS_ID_OFFLINE, NULL); - silc_free(fingerprint); - silc_free(r->offline_pk); - silc_free(r); - return; - } - - /* Get the client entry. */ - client_entry = silc_client_get_client_by_id(r->client, r->conn, - &r->client_id); - if (!client_entry) { - silc_free(r); - return; - } - - memset(&vcard, 0, sizeof(vcard)); - memset(&message, 0, sizeof(message)); - memset(&extension, 0, sizeof(extension)); -#ifdef SILC_ATTRIBUTE_USER_ICON - memset(&usericon, 0, sizeof(usericon)); -#endif - memset(&serverpk, 0, sizeof(serverpk)); - memset(&usersign, 0, sizeof(usersign)); - memset(&serversign, 0, sizeof(serversign)); - - /* Now that we have the public key and we trust it now we - save the attributes of the buddy and update its status. */ - - if (client_entry->attrs) { - silc_dlist_start(client_entry->attrs); - while ((attr = silc_dlist_get(client_entry->attrs)) - != SILC_LIST_END) { - attribute = silc_attribute_get_attribute(attr); - - switch (attribute) { - case SILC_ATTRIBUTE_USER_INFO: - if (!silc_attribute_get_object(attr, (void *)&vcard, - sizeof(vcard))) - continue; - break; - - case SILC_ATTRIBUTE_STATUS_MESSAGE: - if (!silc_attribute_get_object(attr, (void *)&message, - sizeof(message))) - continue; - break; - - case SILC_ATTRIBUTE_EXTENSION: - if (!silc_attribute_get_object(attr, (void *)&extension, - sizeof(extension))) - continue; - break; - -#ifdef SILC_ATTRIBUTE_USER_ICON - case SILC_ATTRIBUTE_USER_ICON: - if (!silc_attribute_get_object(attr, (void *)&usericon, - sizeof(usericon))) - continue; - break; -#endif - - case SILC_ATTRIBUTE_SERVER_PUBLIC_KEY: - if (serverpk.type) - continue; - if (!silc_attribute_get_object(attr, (void *)&serverpk, - sizeof(serverpk))) - continue; - break; - - case SILC_ATTRIBUTE_USER_DIGITAL_SIGNATURE: - if (usersign.data) - continue; - if (!silc_attribute_get_object(attr, (void *)&usersign, - sizeof(usersign))) - continue; - break; - - case SILC_ATTRIBUTE_SERVER_DIGITAL_SIGNATURE: - if (serversign.data) - continue; - if (!silc_attribute_get_object(attr, (void *)&serversign, - sizeof(serversign))) - continue; - break; - - default: - break; - } - } - } - - /* Verify the attribute signatures */ - - if (usersign.data) { - SilcPKCS pkcs; - unsigned char *verifyd; - SilcUInt32 verify_len; - - silc_pkcs_alloc((unsigned char*)"rsa", &pkcs); - verifyd = silc_attribute_get_verify_data(client_entry->attrs, - FALSE, &verify_len); - if (verifyd && silc_pkcs_public_key_set(pkcs, client_entry->public_key)){ - if (!silc_pkcs_verify_with_hash(pkcs, client->sha1hash, - usersign.data, - usersign.data_len, - verifyd, verify_len)) - usign_success = FALSE; - } - silc_free(verifyd); - } - - if (serversign.data && !strcmp(serverpk.type, "silc-rsa")) { - SilcPublicKey public_key; - SilcPKCS pkcs; - unsigned char *verifyd; - SilcUInt32 verify_len; - - if (silc_pkcs_public_key_decode(serverpk.data, serverpk.data_len, - &public_key)) { - silc_pkcs_alloc((unsigned char *)"rsa", &pkcs); - verifyd = silc_attribute_get_verify_data(client_entry->attrs, - TRUE, &verify_len); - if (verifyd && silc_pkcs_public_key_set(pkcs, public_key)) { - if (!silc_pkcs_verify_with_hash(pkcs, client->sha1hash, - serversign.data, - serversign.data_len, - verifyd, verify_len)) - ssign_success = FALSE; - } - silc_pkcs_public_key_free(public_key); - silc_free(verifyd); - } - } - - fingerprint = silc_fingerprint(client_entry->fingerprint, - client_entry->fingerprint_len); - for (i = 0; i < strlen(fingerprint); i++) - if (fingerprint[i] == ' ') - fingerprint[i] = '_'; - - if (usign_success || ssign_success) { - struct passwd *pw; - struct stat st; - - memset(filename2, 0, sizeof(filename2)); - - /* Filename for dir */ - tmp = fingerprint + strlen(fingerprint) - 9; - g_snprintf(filename, sizeof(filename) - 1, - "%s" G_DIR_SEPARATOR_S "friends" G_DIR_SEPARATOR_S "%s", - silcpurple_silcdir(), tmp); - - pw = getpwuid(getuid()); - if (!pw) - return; - - /* Create dir if it doesn't exist */ - if ((g_stat(filename, &st)) == -1) { - if (errno == ENOENT) { - if (pw->pw_uid == geteuid()) { - int ret = g_mkdir(filename, 0755); - if (ret < 0) - return; - } - } - } - - /* Save VCard */ - g_snprintf(filename2, sizeof(filename2) - 1, - "%s" G_DIR_SEPARATOR_S "vcard", filename); - if (vcard.full_name) { - tmp = (char *)silc_vcard_encode(&vcard, &len); - silc_file_writefile(filename2, tmp, len); - silc_free(tmp); - } - - /* Save status message */ - if (message.mime) { - memset(filename2, 0, sizeof(filename2)); - g_snprintf(filename2, sizeof(filename2) - 1, - "%s" G_DIR_SEPARATOR_S "status_message.mime", - filename); - silc_file_writefile(filename2, (char *)message.mime, - message.mime_len); - } - - /* Save extension data */ - if (extension.mime) { - memset(filename2, 0, sizeof(filename2)); - g_snprintf(filename2, sizeof(filename2) - 1, - "%s" G_DIR_SEPARATOR_S "extension.mime", - filename); - silc_file_writefile(filename2, (char *)extension.mime, - extension.mime_len); - } - -#ifdef SILC_ATTRIBUTE_USER_ICON - /* Save user icon */ - if (usericon.mime) { - SilcMime m = silc_mime_decode(usericon.mime, - usericon.mime_len); - if (m) { - const char *type = silc_mime_get_field(m, "Content-Type"); - if (!strcmp(type, "image/jpeg") || - !strcmp(type, "image/gif") || - !strcmp(type, "image/bmp") || - !strcmp(type, "image/png")) { - const unsigned char *data; - SilcUInt32 data_len; - data = silc_mime_get_data(m, &data_len); - if (data) { - /* TODO: Check if SILC gives us something to use as the checksum instead */ - purple_buddy_icons_set_for_user(purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), g_memdup(data, data_len), data_len, NULL); - } - } - silc_mime_free(m); - } - } -#endif - } - - /* Save the public key path to buddy properties, as it is used - to identify the buddy in the network (and not the nickname). */ - memset(filename, 0, sizeof(filename)); - g_snprintf(filename, sizeof(filename) - 1, - "%s" G_DIR_SEPARATOR_S "clientkeys" G_DIR_SEPARATOR_S "clientkey_%s.pub", - silcpurple_silcdir(), fingerprint); - purple_blist_node_set_string((PurpleBlistNode *)b, "public-key", filename); - - /* Update online status */ - purple_prpl_got_user_status(purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), SILCPURPLE_STATUS_ID_AVAILABLE, NULL); - - /* Finally, start watching this user so we receive its status - changes from the server */ - g_snprintf(filename2, sizeof(filename2) - 1, "+%s", filename); - silc_client_command_call(r->client, r->conn, NULL, "WATCH", "-pubkey", - filename2, NULL); - - silc_free(fingerprint); - silc_free(r); -} - -static void -silcpurple_add_buddy_ask_import(void *user_data, const char *name) -{ - SilcPurpleBuddyRes r = (SilcPurpleBuddyRes)user_data; - SilcPublicKey public_key; - - /* Load the public key */ - if (!silc_pkcs_load_public_key(name, &public_key, SILC_PKCS_FILE_PEM) && - !silc_pkcs_load_public_key(name, &public_key, SILC_PKCS_FILE_BIN)) { - silcpurple_add_buddy_ask_pk_cb(r, 0); - purple_notify_error(r->client->application, - _("Add Buddy"), _("Could not load public key"), NULL); - return; - } - - /* Now verify the public key */ - r->offline_pk = silc_pkcs_public_key_encode(public_key, &r->offline_pk_len); - silcpurple_verify_public_key(r->client, r->conn, r->b->name, - SILC_SOCKET_TYPE_CLIENT, - r->offline_pk, r->offline_pk_len, - SILC_SKE_PK_TYPE_SILC, - silcpurple_add_buddy_save, r); -} - -static void -silcpurple_add_buddy_ask_pk_cancel(void *user_data, const char *name) -{ - SilcPurpleBuddyRes r = (SilcPurpleBuddyRes)user_data; - - /* The user did not import public key. The buddy is unusable. */ - silcpurple_add_buddy_pk_no(r); - silc_free(r); -} - -static void -silcpurple_add_buddy_ask_pk_cb(SilcPurpleBuddyRes r, gint id) -{ - if (id != 0) { - /* The user did not import public key. The buddy is unusable. */ - silcpurple_add_buddy_pk_no(r); - silc_free(r); - return; - } - - /* Open file selector to select the public key. */ - purple_request_file(r->client->application, _("Open..."), NULL, FALSE, - G_CALLBACK(silcpurple_add_buddy_ask_import), - G_CALLBACK(silcpurple_add_buddy_ask_pk_cancel), - purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), NULL, r); - -} - -static void -silcpurple_add_buddy_ask_pk(SilcPurpleBuddyRes r) -{ - char tmp[512]; - g_snprintf(tmp, sizeof(tmp), _("The %s buddy is not present in the network"), - r->b->name); - purple_request_action(r->client->application, _("Add Buddy"), tmp, - _("To add the buddy you must import his/her public key. " - "Press Import to import a public key."), 0, - purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), NULL, r, 2, - _("Cancel"), G_CALLBACK(silcpurple_add_buddy_ask_pk_cb), - _("_Import..."), G_CALLBACK(silcpurple_add_buddy_ask_pk_cb)); -} - -static void -silcpurple_add_buddy_getkey_cb(SilcPurpleBuddyRes r, - SilcClientCommandReplyContext cmd) -{ - SilcClientEntry client_entry; - unsigned char *pk; - SilcUInt32 pk_len; - - /* Get the client entry. */ - client_entry = silc_client_get_client_by_id(r->client, r->conn, - &r->client_id); - if (!client_entry || !client_entry->public_key) { - /* The buddy is offline/nonexistent. We will require user - to associate a public key with the buddy or the buddy - cannot be added. */ - r->offline = TRUE; - silcpurple_add_buddy_ask_pk(r); - return; - } - - /* Now verify the public key */ - pk = silc_pkcs_public_key_encode(client_entry->public_key, &pk_len); - silcpurple_verify_public_key(r->client, r->conn, client_entry->nickname, - SILC_SOCKET_TYPE_CLIENT, - pk, pk_len, SILC_SKE_PK_TYPE_SILC, - silcpurple_add_buddy_save, r); - silc_free(pk); -} - -static void -silcpurple_add_buddy_select_cb(SilcPurpleBuddyRes r, PurpleRequestFields *fields) -{ - PurpleRequestField *f; - GList *list; - SilcClientEntry client_entry; - - f = purple_request_fields_get_field(fields, "list"); - list = purple_request_field_list_get_selected(f); - if (!list) { - /* The user did not select any user. */ - silcpurple_add_buddy_pk_no(r); - silc_free(r); - return; - } - - client_entry = purple_request_field_list_get_data(f, list->data); - silcpurple_add_buddy_resolved(r->client, r->conn, &client_entry, 1, r); -} - -static void -silcpurple_add_buddy_select_cancel(SilcPurpleBuddyRes r, PurpleRequestFields *fields) -{ - /* The user did not select any user. */ - silcpurple_add_buddy_pk_no(r); - silc_free(r); -} - -static void -silcpurple_add_buddy_select(SilcPurpleBuddyRes r, - SilcClientEntry *clients, - SilcUInt32 clients_count) -{ - PurpleRequestFields *fields; - PurpleRequestFieldGroup *g; - PurpleRequestField *f; - char tmp[512], tmp2[128]; - int i; - char *fingerprint; - - fields = purple_request_fields_new(); - g = purple_request_field_group_new(NULL); - f = purple_request_field_list_new("list", NULL); - purple_request_field_group_add_field(g, f); - purple_request_field_list_set_multi_select(f, FALSE); - purple_request_fields_add_group(fields, g); - - for (i = 0; i < clients_count; i++) { - fingerprint = NULL; - if (clients[i]->fingerprint) { - fingerprint = silc_fingerprint(clients[i]->fingerprint, - clients[i]->fingerprint_len); - g_snprintf(tmp2, sizeof(tmp2), "\n%s", fingerprint); - } - g_snprintf(tmp, sizeof(tmp), "%s - %s (%s@%s)%s", - clients[i]->realname, clients[i]->nickname, - clients[i]->username, clients[i]->hostname ? - clients[i]->hostname : "", - fingerprint ? tmp2 : ""); - purple_request_field_list_add_icon(f, tmp, NULL, clients[i]); - silc_free(fingerprint); - } - - purple_request_fields(r->client->application, _("Add Buddy"), - _("Select correct user"), - r->pubkey_search - ? _("More than one user was found with the same public key. Select " - "the correct user from the list to add to the buddy list.") - : _("More than one user was found with the same name. Select " - "the correct user from the list to add to the buddy list."), - fields, - _("OK"), G_CALLBACK(silcpurple_add_buddy_select_cb), - _("Cancel"), G_CALLBACK(silcpurple_add_buddy_select_cancel), - purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), NULL, r); -} - -static void -silcpurple_add_buddy_resolved(SilcClient client, - SilcClientConnection conn, - SilcClientEntry *clients, - SilcUInt32 clients_count, - void *context) -{ - SilcPurpleBuddyRes r = context; - PurpleBuddy *b = r->b; - SilcAttributePayload pub; - SilcAttributeObjPk userpk; - unsigned char *pk; - SilcUInt32 pk_len; - const char *filename; - - filename = purple_blist_node_get_string((PurpleBlistNode *)b, "public-key"); - - /* If the buddy is offline/nonexistent, we will require user - to associate a public key with the buddy or the buddy - cannot be added. */ - if (!clients_count) { - if (r->init) { - silc_free(r); - return; - } - - r->offline = TRUE; - /* If the user has already associated a public key, try loading it - * before prompting the user to load it again */ - if (filename != NULL) - silcpurple_add_buddy_ask_import(r, filename); - else - silcpurple_add_buddy_ask_pk(r); - return; - } - - /* If more than one client was found with nickname, we need to verify - from user which one is the correct. */ - if (clients_count > 1 && !r->pubkey_search) { - if (r->init) { - silc_free(r); - return; - } - - silcpurple_add_buddy_select(r, clients, clients_count); - return; - } - - /* If we searched using public keys and more than one entry was found - the same person is logged on multiple times. */ - if (clients_count > 1 && r->pubkey_search && b->name) { - if (r->init) { - /* Find the entry that closest matches to the - buddy nickname. */ - int i; - for (i = 0; i < clients_count; i++) { - if (!g_ascii_strncasecmp(b->name, clients[i]->nickname, - strlen(b->name))) { - clients[0] = clients[i]; - break; - } - } - } else { - /* Verify from user which one is correct */ - silcpurple_add_buddy_select(r, clients, clients_count); - return; - } - } - - /* The client was found. Now get its public key and verify - that before adding the buddy. */ - memset(&userpk, 0, sizeof(userpk)); - b->proto_data = silc_memdup(clients[0]->id, sizeof(*clients[0]->id)); - r->client_id = *clients[0]->id; - - /* Get the public key from attributes, if not present then - resolve it with GETKEY unless we have it cached already. */ - if (clients[0]->attrs && !clients[0]->public_key) { - pub = silcpurple_get_attr(clients[0]->attrs, - SILC_ATTRIBUTE_USER_PUBLIC_KEY); - if (!pub || !silc_attribute_get_object(pub, (void *)&userpk, - sizeof(userpk))) { - /* Get public key with GETKEY */ - silc_client_command_call(client, conn, NULL, - "GETKEY", clients[0]->nickname, NULL); - silc_client_command_pending(conn, SILC_COMMAND_GETKEY, - conn->cmd_ident, - (SilcCommandCb)silcpurple_add_buddy_getkey_cb, - r); - return; - } - if (!silc_pkcs_public_key_decode(userpk.data, userpk.data_len, - &clients[0]->public_key)) - return; - silc_free(userpk.data); - } else if (filename && !clients[0]->public_key) { - if (!silc_pkcs_load_public_key(filename, &clients[0]->public_key, - SILC_PKCS_FILE_PEM) && - !silc_pkcs_load_public_key(filename, &clients[0]->public_key, - SILC_PKCS_FILE_BIN)) { - /* Get public key with GETKEY */ - silc_client_command_call(client, conn, NULL, - "GETKEY", clients[0]->nickname, NULL); - silc_client_command_pending(conn, SILC_COMMAND_GETKEY, - conn->cmd_ident, - (SilcCommandCb)silcpurple_add_buddy_getkey_cb, - r); - return; - } - } else if (!clients[0]->public_key) { - /* Get public key with GETKEY */ - silc_client_command_call(client, conn, NULL, - "GETKEY", clients[0]->nickname, NULL); - silc_client_command_pending(conn, SILC_COMMAND_GETKEY, - conn->cmd_ident, - (SilcCommandCb)silcpurple_add_buddy_getkey_cb, - r); - return; - } - - /* We have the public key, verify it. */ - pk = silc_pkcs_public_key_encode(clients[0]->public_key, &pk_len); - silcpurple_verify_public_key(client, conn, clients[0]->nickname, - SILC_SOCKET_TYPE_CLIENT, - pk, pk_len, SILC_SKE_PK_TYPE_SILC, - silcpurple_add_buddy_save, r); - silc_free(pk); -} - -static void -silcpurple_add_buddy_i(PurpleConnection *gc, PurpleBuddy *b, gboolean init) -{ - SilcPurple sg = gc->proto_data; - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - SilcPurpleBuddyRes r; - SilcBuffer attrs; - const char *filename, *name = b->name; - - r = silc_calloc(1, sizeof(*r)); - if (!r) - return; - r->client = client; - r->conn = conn; - r->b = b; - r->init = init; - - /* See if we have this buddy's public key. If we do use that - to search the details. */ - filename = purple_blist_node_get_string((PurpleBlistNode *)b, "public-key"); - if (filename) { - SilcPublicKey public_key; - SilcAttributeObjPk userpk; - - if (!silc_pkcs_load_public_key(filename, &public_key, - SILC_PKCS_FILE_PEM) && - !silc_pkcs_load_public_key(filename, &public_key, - SILC_PKCS_FILE_BIN)) - return; - - /* Get all attributes, and use the public key to search user */ - name = NULL; - attrs = silc_client_attributes_request(SILC_ATTRIBUTE_USER_INFO, - SILC_ATTRIBUTE_SERVICE, - SILC_ATTRIBUTE_STATUS_MOOD, - SILC_ATTRIBUTE_STATUS_FREETEXT, - SILC_ATTRIBUTE_STATUS_MESSAGE, - SILC_ATTRIBUTE_PREFERRED_LANGUAGE, - SILC_ATTRIBUTE_PREFERRED_CONTACT, - SILC_ATTRIBUTE_TIMEZONE, - SILC_ATTRIBUTE_GEOLOCATION, -#ifdef SILC_ATTRIBUTE_USER_ICON - SILC_ATTRIBUTE_USER_ICON, -#endif - SILC_ATTRIBUTE_DEVICE_INFO, 0); - userpk.type = "silc-rsa"; - userpk.data = silc_pkcs_public_key_encode(public_key, &userpk.data_len); - attrs = silc_attribute_payload_encode(attrs, - SILC_ATTRIBUTE_USER_PUBLIC_KEY, - SILC_ATTRIBUTE_FLAG_VALID, - &userpk, sizeof(userpk)); - silc_free(userpk.data); - silc_pkcs_public_key_free(public_key); - r->pubkey_search = TRUE; - } else { - /* Get all attributes */ - attrs = silc_client_attributes_request(0); - } - - /* Resolve */ - silc_client_get_clients_whois(client, conn, name, NULL, attrs, - silcpurple_add_buddy_resolved, r); - silc_buffer_free(attrs); -} - -void silcpurple_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group) -{ - /* Don't add if the buddy is already on the list. - * - * SILC doesn't have groups, so we don't need to do anything - * for a move. */ - if (purple_buddy_get_protocol_data(buddy) == NULL) - silcpurple_add_buddy_i(gc, buddy, FALSE); -} - -void silcpurple_send_buddylist(PurpleConnection *gc) -{ - PurpleBuddyList *blist; - PurpleBlistNode *gnode, *cnode, *bnode; - PurpleBuddy *buddy; - PurpleAccount *account; - - account = purple_connection_get_account(gc); - - if ((blist = purple_get_blist()) != NULL) - { - for (gnode = blist->root; gnode != NULL; gnode = gnode->next) - { - if (!PURPLE_BLIST_NODE_IS_GROUP(gnode)) - continue; - for (cnode = gnode->child; cnode != NULL; cnode = cnode->next) - { - if (!PURPLE_BLIST_NODE_IS_CONTACT(cnode)) - continue; - for (bnode = cnode->child; bnode != NULL; bnode = bnode->next) - { - if (!PURPLE_BLIST_NODE_IS_BUDDY(bnode)) - continue; - buddy = (PurpleBuddy *)bnode; - if (purple_buddy_get_account(buddy) == account) - silcpurple_add_buddy_i(gc, buddy, TRUE); - } - } - } - } -} - -void silcpurple_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, - PurpleGroup *group) -{ - silc_free(buddy->proto_data); -} - -void silcpurple_idle_set(PurpleConnection *gc, int idle) - -{ - SilcPurple sg; - SilcClient client; - SilcClientConnection conn; - SilcAttributeObjService service; - const char *server; - int port; - - sg = gc->proto_data; - if (sg == NULL) - return; - - client = sg->client; - if (client == NULL) - return; - - conn = sg->conn; - if (conn == NULL) - return; - - server = purple_account_get_string(sg->account, "server", - "silc.silcnet.org"); - port = purple_account_get_int(sg->account, "port", 706), - - memset(&service, 0, sizeof(service)); - silc_client_attribute_del(client, conn, - SILC_ATTRIBUTE_SERVICE, NULL); - service.port = port; - g_snprintf(service.address, sizeof(service.address), "%s", server); - service.idle = idle; - silc_client_attribute_add(client, conn, SILC_ATTRIBUTE_SERVICE, - &service, sizeof(service)); -} - -char *silcpurple_status_text(PurpleBuddy *b) -{ - SilcPurple sg = b->account->gc->proto_data; - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - SilcClientID *client_id = b->proto_data; - SilcClientEntry client_entry; - SilcAttributePayload attr; - SilcAttributeMood mood = 0; - - /* Get the client entry. */ - client_entry = silc_client_get_client_by_id(client, conn, client_id); - if (!client_entry) - return NULL; - - /* If user is online, we show the mood status, if available. - If user is offline or away that status is indicated. */ - - if (client_entry->mode & SILC_UMODE_DETACHED) - return g_strdup(_("Detached")); - if (client_entry->mode & SILC_UMODE_GONE) - return g_strdup(_("Away")); - if (client_entry->mode & SILC_UMODE_INDISPOSED) - return g_strdup(_("Indisposed")); - if (client_entry->mode & SILC_UMODE_BUSY) - return g_strdup(_("Busy")); - if (client_entry->mode & SILC_UMODE_PAGE) - return g_strdup(_("Wake Me Up")); - if (client_entry->mode & SILC_UMODE_HYPER) - return g_strdup(_("Hyper Active")); - if (client_entry->mode & SILC_UMODE_ROBOT) - return g_strdup(_("Robot")); - - attr = silcpurple_get_attr(client_entry->attrs, SILC_ATTRIBUTE_STATUS_MOOD); - if (attr && silc_attribute_get_object(attr, &mood, sizeof(mood))) { - /* The mood is a bit mask, so we could show multiple moods, - but let's show only one for now. */ - if (mood & SILC_ATTRIBUTE_MOOD_HAPPY) - return g_strdup(_("Happy")); - if (mood & SILC_ATTRIBUTE_MOOD_SAD) - return g_strdup(_("Sad")); - if (mood & SILC_ATTRIBUTE_MOOD_ANGRY) - return g_strdup(_("Angry")); - if (mood & SILC_ATTRIBUTE_MOOD_JEALOUS) - return g_strdup(_("Jealous")); - if (mood & SILC_ATTRIBUTE_MOOD_ASHAMED) - return g_strdup(_("Ashamed")); - if (mood & SILC_ATTRIBUTE_MOOD_INVINCIBLE) - return g_strdup(_("Invincible")); - if (mood & SILC_ATTRIBUTE_MOOD_INLOVE) - return g_strdup(_("In Love")); - if (mood & SILC_ATTRIBUTE_MOOD_SLEEPY) - return g_strdup(_("Sleepy")); - if (mood & SILC_ATTRIBUTE_MOOD_BORED) - return g_strdup(_("Bored")); - if (mood & SILC_ATTRIBUTE_MOOD_EXCITED) - return g_strdup(_("Excited")); - if (mood & SILC_ATTRIBUTE_MOOD_ANXIOUS) - return g_strdup(_("Anxious")); - } - - return NULL; -} - -void silcpurple_tooltip_text(PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboolean full) -{ - SilcPurple sg = b->account->gc->proto_data; - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - SilcClientID *client_id = b->proto_data; - SilcClientEntry client_entry; - char *moodstr, *statusstr, *contactstr, *langstr, *devicestr, *tzstr, *geostr; - char tmp[256]; - - /* Get the client entry. */ - client_entry = silc_client_get_client_by_id(client, conn, client_id); - if (!client_entry) - return; - - if (client_entry->nickname) - purple_notify_user_info_add_pair(user_info, _("Nickname"), - client_entry->nickname); - if (client_entry->username && client_entry->hostname) { - g_snprintf(tmp, sizeof(tmp), "%s@%s", client_entry->username, client_entry->hostname); - purple_notify_user_info_add_pair(user_info, _("Username"), tmp); - } - if (client_entry->mode) { - memset(tmp, 0, sizeof(tmp)); - silcpurple_get_umode_string(client_entry->mode, - tmp, sizeof(tmp) - strlen(tmp)); - purple_notify_user_info_add_pair(user_info, _("User Modes"), tmp); - } - - silcpurple_parse_attrs(client_entry->attrs, &moodstr, &statusstr, &contactstr, &langstr, &devicestr, &tzstr, &geostr); - - if (statusstr) { - purple_notify_user_info_add_pair(user_info, _("Message"), statusstr); - g_free(statusstr); - } - - if (full) { - if (moodstr) { - purple_notify_user_info_add_pair(user_info, _("Mood"), moodstr); - g_free(moodstr); - } - - if (contactstr) { - purple_notify_user_info_add_pair(user_info, _("Preferred Contact"), contactstr); - g_free(contactstr); - } - - if (langstr) { - purple_notify_user_info_add_pair(user_info, _("Preferred Language"), langstr); - g_free(langstr); - } - - if (devicestr) { - purple_notify_user_info_add_pair(user_info, _("Device"), devicestr); - g_free(devicestr); - } - - if (tzstr) { - purple_notify_user_info_add_pair(user_info, _("Timezone"), tzstr); - g_free(tzstr); - } - - if (geostr) { - purple_notify_user_info_add_pair(user_info, _("Geolocation"), geostr); - g_free(geostr); - } - } -} - -static void -silcpurple_buddy_kill(PurpleBlistNode *node, gpointer data) -{ - PurpleBuddy *b; - PurpleConnection *gc; - SilcPurple sg; - - g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); - - b = (PurpleBuddy *) node; - gc = purple_account_get_connection(b->account); - sg = gc->proto_data; - - /* Call KILL */ - silc_client_command_call(sg->client, sg->conn, NULL, "KILL", - b->name, "Killed by operator", NULL); -} - -typedef struct { - SilcPurple sg; - SilcClientEntry client_entry; -} *SilcPurpleBuddyWb; - -static void -silcpurple_buddy_wb(PurpleBlistNode *node, gpointer data) -{ - SilcPurpleBuddyWb wb = data; - silcpurple_wb_init(wb->sg, wb->client_entry); - silc_free(wb); -} - -GList *silcpurple_buddy_menu(PurpleBuddy *buddy) -{ - PurpleConnection *gc = purple_account_get_connection(buddy->account); - SilcPurple sg = gc->proto_data; - SilcClientConnection conn = sg->conn; - const char *pkfile = NULL; - SilcClientEntry client_entry = NULL; - PurpleMenuAction *act; - GList *m = NULL; - SilcPurpleBuddyWb wb; - - pkfile = purple_blist_node_get_string((PurpleBlistNode *) buddy, "public-key"); - client_entry = silc_client_get_client_by_id(sg->client, - sg->conn, - buddy->proto_data); - - if (client_entry && client_entry->send_key) { - act = purple_menu_action_new(_("Reset IM Key"), - PURPLE_CALLBACK(silcpurple_buddy_resetkey), - NULL, NULL); - m = g_list_append(m, act); - - } else { - act = purple_menu_action_new(_("IM with Key Exchange"), - PURPLE_CALLBACK(silcpurple_buddy_keyagr), - NULL, NULL); - m = g_list_append(m, act); - - act = purple_menu_action_new(_("IM with Password"), - PURPLE_CALLBACK(silcpurple_buddy_privkey_menu), - NULL, NULL); - m = g_list_append(m, act); - } - - if (pkfile) { - act = purple_menu_action_new(_("Show Public Key"), - PURPLE_CALLBACK(silcpurple_buddy_showkey), - NULL, NULL); - m = g_list_append(m, act); - - } else { - act = purple_menu_action_new(_("Get Public Key..."), - PURPLE_CALLBACK(silcpurple_buddy_getkey_menu), - NULL, NULL); - m = g_list_append(m, act); - } - - if (conn && conn->local_entry->mode & SILC_UMODE_ROUTER_OPERATOR) { - act = purple_menu_action_new(_("Kill User"), - PURPLE_CALLBACK(silcpurple_buddy_kill), - NULL, NULL); - m = g_list_append(m, act); - } - - if (client_entry) { - wb = silc_calloc(1, sizeof(*wb)); - wb->sg = sg; - wb->client_entry = client_entry; - act = purple_menu_action_new(_("Draw On Whiteboard"), - PURPLE_CALLBACK(silcpurple_buddy_wb), - (void *)wb, NULL); - m = g_list_append(m, act); - } - return m; -} - -#ifdef SILC_ATTRIBUTE_USER_ICON -void silcpurple_buddy_set_icon(PurpleConnection *gc, PurpleStoredImage *img) -{ - SilcPurple sg = gc->proto_data; - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - SilcMime mime; - char type[32]; - unsigned char *icon; - const char *t; - SilcAttributeObjMime obj; - - /* Remove */ - if (!img) { - silc_client_attribute_del(client, conn, - SILC_ATTRIBUTE_USER_ICON, NULL); - return; - } - - /* Add */ - mime = silc_mime_alloc(); - if (!mime) - return; - - t = purple_imgstore_get_extension(img); - if (!t || !strcmp(t, "icon")) { - silc_mime_free(mime); - return; - } - if (!strcmp(t, "jpg")) - t = "jpeg"; - g_snprintf(type, sizeof(type), "image/%s", t); - silc_mime_add_field(mime, "Content-Type", type); - silc_mime_add_data(mime, purple_imgstore_get_data(img), purple_imgstore_get_size(img)); - - obj.mime = icon = silc_mime_encode(mime, &obj.mime_len); - if (obj.mime) - silc_client_attribute_add(client, conn, - SILC_ATTRIBUTE_USER_ICON, &obj, sizeof(obj)); - - silc_free(icon); - silc_mime_free(mime); -} -#endif diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/silc10/chat.c --- a/libpurple/protocols/silc10/chat.c Mon Aug 22 11:20:05 2011 +0900 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1456 +0,0 @@ -/* - - silcpurple_chat.c - - Author: Pekka Riikonen - - Copyright (C) 2004 Pekka Riikonen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - -*/ - -#include "silcincludes.h" -#include "silcclient.h" -#include "silcpurple.h" -#include "wb.h" - -/***************************** Channel Routines ******************************/ - -GList *silcpurple_chat_info(PurpleConnection *gc) -{ - GList *ci = NULL; - struct proto_chat_entry *pce; - - pce = g_new0(struct proto_chat_entry, 1); - pce->label = _("_Channel:"); - pce->identifier = "channel"; - pce->required = TRUE; - ci = g_list_append(ci, pce); - - pce = g_new0(struct proto_chat_entry, 1); - pce->label = _("_Passphrase:"); - pce->identifier = "passphrase"; - pce->secret = TRUE; - ci = g_list_append(ci, pce); - - return ci; -} - -GHashTable *silcpurple_chat_info_defaults(PurpleConnection *gc, const char *chat_name) -{ - GHashTable *defaults; - - defaults = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free); - - if (chat_name != NULL) - g_hash_table_insert(defaults, "channel", g_strdup(chat_name)); - - return defaults; -} - -static void -silcpurple_chat_getinfo(PurpleConnection *gc, GHashTable *components); - -static void -silcpurple_chat_getinfo_res(SilcClient client, - SilcClientConnection conn, - SilcChannelEntry *channels, - SilcUInt32 channels_count, - void *context) -{ - GHashTable *components = context; - PurpleConnection *gc = client->application; - const char *chname; - char tmp[256]; - - chname = g_hash_table_lookup(components, "channel"); - if (!chname) - return; - - if (!channels) { - g_snprintf(tmp, sizeof(tmp), - _("Channel %s does not exist in the network"), chname); - purple_notify_error(gc, _("Channel Information"), - _("Cannot get channel information"), tmp); - return; - } - - silcpurple_chat_getinfo(gc, components); -} - - -static void -silcpurple_chat_getinfo(PurpleConnection *gc, GHashTable *components) -{ - SilcPurple sg = gc->proto_data; - const char *chname; - char *buf, tmp[256], *tmp2; - GString *s; - SilcChannelEntry channel; - SilcHashTableList htl; - SilcChannelUser chu; - - if (!components) - return; - - chname = g_hash_table_lookup(components, "channel"); - if (!chname) - return; - channel = silc_client_get_channel(sg->client, sg->conn, - (char *)chname); - if (!channel) { - silc_client_get_channel_resolve(sg->client, sg->conn, - (char *)chname, - silcpurple_chat_getinfo_res, - components); - return; - } - - s = g_string_new(""); - tmp2 = g_markup_escape_text(channel->channel_name, -1); - g_string_append_printf(s, _("Channel Name: %s"), tmp2); - g_free(tmp2); - if (channel->user_list && silc_hash_table_count(channel->user_list)) - g_string_append_printf(s, _("
User Count: %d"), - (int)silc_hash_table_count(channel->user_list)); - - silc_hash_table_list(channel->user_list, &htl); - while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { - if (chu->mode & SILC_CHANNEL_UMODE_CHANFO) { - tmp2 = g_markup_escape_text(chu->client->nickname, -1); - g_string_append_printf(s, _("
Channel Founder: %s"), - tmp2); - g_free(tmp2); - break; - } - } - silc_hash_table_list_reset(&htl); - - if (channel->channel_key) - g_string_append_printf(s, _("
Channel Cipher: %s"), - silc_cipher_get_name(channel->channel_key)); - if (channel->hmac) - /* Definition of HMAC: http://en.wikipedia.org/wiki/HMAC */ - g_string_append_printf(s, _("
Channel HMAC: %s"), - silc_hmac_get_name(channel->hmac)); - - if (channel->topic) { - tmp2 = g_markup_escape_text(channel->topic, -1); - g_string_append_printf(s, _("
Channel Topic:
%s"), tmp2); - g_free(tmp2); - } - - if (channel->mode) { - g_string_append_printf(s, _("
Channel Modes: ")); - silcpurple_get_chmode_string(channel->mode, tmp, sizeof(tmp)); - g_string_append(s, tmp); - } - - if (channel->founder_key) { - char *fingerprint, *babbleprint; - unsigned char *pk; - SilcUInt32 pk_len; - pk = silc_pkcs_public_key_encode(channel->founder_key, &pk_len); - fingerprint = silc_hash_fingerprint(NULL, pk, pk_len); - babbleprint = silc_hash_babbleprint(NULL, pk, pk_len); - - g_string_append_printf(s, _("
Founder Key Fingerprint:
%s"), fingerprint); - g_string_append_printf(s, _("
Founder Key Babbleprint:
%s"), babbleprint); - - silc_free(fingerprint); - silc_free(babbleprint); - silc_free(pk); - } - - buf = g_string_free(s, FALSE); - purple_notify_formatted(gc, NULL, _("Channel Information"), NULL, buf, NULL, NULL); - g_free(buf); -} - - -static void -silcpurple_chat_getinfo_menu(PurpleBlistNode *node, gpointer data) -{ - PurpleChat *chat = (PurpleChat *)node; - silcpurple_chat_getinfo(chat->account->gc, chat->components); -} - - -#if 0 /* XXX For now these are not implemented. We need better - listview dialog from Purple for these. */ -/************************** Channel Invite List ******************************/ - -static void -silcpurple_chat_invitelist(PurpleBlistNode *node, gpointer data); -{ - -} - - -/**************************** Channel Ban List *******************************/ - -static void -silcpurple_chat_banlist(PurpleBlistNode *node, gpointer data); -{ - -} -#endif - - -/************************* Channel Authentication ****************************/ - -typedef struct { - SilcPurple sg; - SilcChannelEntry channel; - PurpleChat *c; - SilcBuffer pubkeys; -} *SilcPurpleChauth; - -static void -silcpurple_chat_chpk_add(void *user_data, const char *name) -{ - SilcPurpleChauth sgc = (SilcPurpleChauth)user_data; - SilcPurple sg = sgc->sg; - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - SilcPublicKey public_key; - SilcBuffer chpks, pk, chidp; - unsigned char mode[4]; - SilcUInt32 m; - - /* Load the public key */ - if (!silc_pkcs_load_public_key(name, &public_key, SILC_PKCS_FILE_PEM) && - !silc_pkcs_load_public_key(name, &public_key, SILC_PKCS_FILE_BIN)) { - silcpurple_chat_chauth_show(sgc->sg, sgc->channel, sgc->pubkeys); - silc_buffer_free(sgc->pubkeys); - silc_free(sgc); - purple_notify_error(client->application, - _("Add Channel Public Key"), - _("Could not load public key"), NULL); - return; - } - - pk = silc_pkcs_public_key_payload_encode(public_key); - chpks = silc_buffer_alloc_size(2); - SILC_PUT16_MSB(1, chpks->head); - chpks = silc_argument_payload_encode_one(chpks, pk->data, - pk->len, 0x00); - silc_buffer_free(pk); - - m = sgc->channel->mode; - m |= SILC_CHANNEL_MODE_CHANNEL_AUTH; - - /* Send CMODE */ - SILC_PUT32_MSB(m, mode); - chidp = silc_id_payload_encode(sgc->channel->id, SILC_ID_CHANNEL); - silc_client_command_send(client, conn, SILC_COMMAND_CMODE, - ++conn->cmd_ident, 3, - 1, chidp->data, chidp->len, - 2, mode, sizeof(mode), - 9, chpks->data, chpks->len); - silc_buffer_free(chpks); - silc_buffer_free(chidp); - silc_buffer_free(sgc->pubkeys); - silc_free(sgc); -} - -static void -silcpurple_chat_chpk_cancel(void *user_data, const char *name) -{ - SilcPurpleChauth sgc = (SilcPurpleChauth)user_data; - silcpurple_chat_chauth_show(sgc->sg, sgc->channel, sgc->pubkeys); - silc_buffer_free(sgc->pubkeys); - silc_free(sgc); -} - -static void -silcpurple_chat_chpk_cb(SilcPurpleChauth sgc, PurpleRequestFields *fields) -{ - SilcPurple sg = sgc->sg; - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - PurpleRequestField *f; - GList *list; - SilcPublicKey public_key; - SilcBuffer chpks, pk, chidp; - SilcUInt16 c = 0, ct; - unsigned char mode[4]; - SilcUInt32 m; - - f = purple_request_fields_get_field(fields, "list"); - if (!purple_request_field_list_get_selected(f)) { - /* Add new public key */ - purple_request_file(sg->gc, _("Open Public Key..."), NULL, FALSE, - G_CALLBACK(silcpurple_chat_chpk_add), - G_CALLBACK(silcpurple_chat_chpk_cancel), - purple_connection_get_account(sg->gc), NULL, NULL, sgc); - return; - } - - list = purple_request_field_list_get_items(f); - chpks = silc_buffer_alloc_size(2); - - for (ct = 0; list; list = list->next, ct++) { - public_key = purple_request_field_list_get_data(f, list->data); - if (purple_request_field_list_is_selected(f, list->data)) { - /* Delete this public key */ - pk = silc_pkcs_public_key_payload_encode(public_key); - chpks = silc_argument_payload_encode_one(chpks, pk->data, - pk->len, 0x01); - silc_buffer_free(pk); - c++; - } - silc_pkcs_public_key_free(public_key); - } - if (!c) { - silc_buffer_free(chpks); - return; - } - SILC_PUT16_MSB(c, chpks->head); - - m = sgc->channel->mode; - if (ct == c) - m &= ~SILC_CHANNEL_MODE_CHANNEL_AUTH; - - /* Send CMODE */ - SILC_PUT32_MSB(m, mode); - chidp = silc_id_payload_encode(sgc->channel->id, SILC_ID_CHANNEL); - silc_client_command_send(client, conn, SILC_COMMAND_CMODE, - ++conn->cmd_ident, 3, - 1, chidp->data, chidp->len, - 2, mode, sizeof(mode), - 9, chpks->data, chpks->len); - silc_buffer_free(chpks); - silc_buffer_free(chidp); - silc_buffer_free(sgc->pubkeys); - silc_free(sgc); -} - -static void -silcpurple_chat_chauth_ok(SilcPurpleChauth sgc, PurpleRequestFields *fields) -{ - SilcPurple sg = sgc->sg; - PurpleRequestField *f; - const char *curpass, *val; - int set; - - f = purple_request_fields_get_field(fields, "passphrase"); - val = purple_request_field_string_get_value(f); - curpass = purple_blist_node_get_string((PurpleBlistNode *)sgc->c, "passphrase"); - - if (!val && curpass) - set = 0; - else if (val && !curpass) - set = 1; - else if (val && curpass && strcmp(val, curpass)) - set = 1; - else - set = -1; - - if (set == 1) { - silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", - sgc->channel->channel_name, "+a", val, NULL); - purple_blist_node_set_string((PurpleBlistNode *)sgc->c, "passphrase", val); - } else if (set == 0) { - silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", - sgc->channel->channel_name, "-a", NULL); - purple_blist_node_remove_setting((PurpleBlistNode *)sgc->c, "passphrase"); - } - - silc_buffer_free(sgc->pubkeys); - silc_free(sgc); -} - -void silcpurple_chat_chauth_show(SilcPurple sg, SilcChannelEntry channel, - SilcBuffer channel_pubkeys) -{ - SilcUInt16 argc; - SilcArgumentPayload chpks; - unsigned char *pk; - SilcUInt32 pk_len, type; - char *fingerprint, *babbleprint; - SilcPublicKey pubkey; - SilcPublicKeyIdentifier ident; - char tmp2[1024], t[512]; - PurpleRequestFields *fields; - PurpleRequestFieldGroup *g; - PurpleRequestField *f; - SilcPurpleChauth sgc; - const char *curpass = NULL; - - sgc = silc_calloc(1, sizeof(*sgc)); - if (!sgc) - return; - sgc->sg = sg; - sgc->channel = channel; - - fields = purple_request_fields_new(); - - if (sgc->c) - curpass = purple_blist_node_get_string((PurpleBlistNode *)sgc->c, "passphrase"); - - g = purple_request_field_group_new(NULL); - f = purple_request_field_string_new("passphrase", _("Channel Passphrase"), - curpass, FALSE); - purple_request_field_string_set_masked(f, TRUE); - purple_request_field_group_add_field(g, f); - purple_request_fields_add_group(fields, g); - - g = purple_request_field_group_new(NULL); - f = purple_request_field_label_new("l1", _("Channel Public Keys List")); - purple_request_field_group_add_field(g, f); - purple_request_fields_add_group(fields, g); - - g_snprintf(t, sizeof(t), - _("Channel authentication is used to secure the channel from " - "unauthorized access. The authentication may be based on " - "passphrase and digital signatures. If passphrase is set, it " - "is required to be able to join. If channel public keys are set " - "then only users whose public keys are listed are able to join.")); - - if (!channel_pubkeys) { - f = purple_request_field_list_new("list", NULL); - purple_request_field_group_add_field(g, f); - purple_request_fields(sg->gc, _("Channel Authentication"), - _("Channel Authentication"), t, fields, - _("Add / Remove"), G_CALLBACK(silcpurple_chat_chpk_cb), - _("OK"), G_CALLBACK(silcpurple_chat_chauth_ok), - purple_connection_get_account(sg->gc), NULL, NULL, sgc); - return; - } - sgc->pubkeys = silc_buffer_copy(channel_pubkeys); - - g = purple_request_field_group_new(NULL); - f = purple_request_field_list_new("list", NULL); - purple_request_field_group_add_field(g, f); - purple_request_fields_add_group(fields, g); - - SILC_GET16_MSB(argc, channel_pubkeys->data); - chpks = silc_argument_payload_parse(channel_pubkeys->data + 2, - channel_pubkeys->len - 2, argc); - if (!chpks) - return; - - pk = silc_argument_get_first_arg(chpks, &type, &pk_len); - while (pk) { - fingerprint = silc_hash_fingerprint(NULL, pk + 4, pk_len - 4); - babbleprint = silc_hash_babbleprint(NULL, pk + 4, pk_len - 4); - silc_pkcs_public_key_payload_decode(pk, pk_len, &pubkey); - ident = silc_pkcs_decode_identifier(pubkey->identifier); - - g_snprintf(tmp2, sizeof(tmp2), "%s\n %s\n %s", - ident->realname ? ident->realname : ident->username ? - ident->username : "", fingerprint, babbleprint); - purple_request_field_list_add_icon(f, tmp2, NULL, pubkey); - - silc_free(fingerprint); - silc_free(babbleprint); - silc_pkcs_free_identifier(ident); - pk = silc_argument_get_next_arg(chpks, &type, &pk_len); - } - - purple_request_field_list_set_multi_select(f, FALSE); - purple_request_fields(sg->gc, _("Channel Authentication"), - _("Channel Authentication"), t, fields, - _("Add / Remove"), G_CALLBACK(silcpurple_chat_chpk_cb), - _("OK"), G_CALLBACK(silcpurple_chat_chauth_ok), - purple_connection_get_account(sg->gc), NULL, NULL, sgc); - - silc_argument_payload_free(chpks); -} - -static void -silcpurple_chat_chauth(PurpleBlistNode *node, gpointer data) -{ - PurpleChat *chat; - PurpleConnection *gc; - SilcPurple sg; - - g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node)); - - chat = (PurpleChat *) node; - gc = purple_account_get_connection(chat->account); - sg = gc->proto_data; - - silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", - g_hash_table_lookup(chat->components, "channel"), - "+C", NULL); -} - - -/************************** Channel Private Groups **************************/ - -/* Private groups are "virtual" channels. They are groups inside a channel. - This is implemented by using channel private keys. By knowing a channel - private key user becomes part of that group and is able to talk on that - group. Other users, on the same channel, won't be able to see the - messages of that group. It is possible to have multiple groups inside - a channel - and thus having multiple private keys on the channel. */ - -typedef struct { - SilcPurple sg; - PurpleChat *c; - const char *channel; -} *SilcPurpleCharPrv; - -static void -silcpurple_chat_prv_add(SilcPurpleCharPrv p, PurpleRequestFields *fields) -{ - SilcPurple sg = p->sg; - char tmp[512]; - PurpleRequestField *f; - const char *name, *passphrase, *alias; - GHashTable *comp; - PurpleGroup *g; - PurpleChat *cn; - - f = purple_request_fields_get_field(fields, "name"); - name = purple_request_field_string_get_value(f); - if (!name) { - silc_free(p); - return; - } - f = purple_request_fields_get_field(fields, "passphrase"); - passphrase = purple_request_field_string_get_value(f); - f = purple_request_fields_get_field(fields, "alias"); - alias = purple_request_field_string_get_value(f); - - /* Add private group to buddy list */ - g_snprintf(tmp, sizeof(tmp), "%s [Private Group]", name); - comp = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); - g_hash_table_replace(comp, g_strdup("channel"), g_strdup(tmp)); - g_hash_table_replace(comp, g_strdup("passphrase"), g_strdup(passphrase)); - - cn = purple_chat_new(sg->account, alias, comp); - g = (PurpleGroup *)p->c->node.parent; - purple_blist_add_chat(cn, g, (PurpleBlistNode *)p->c); - - /* Associate to a real channel */ - purple_blist_node_set_string((PurpleBlistNode *)cn, "parentch", p->channel); - - /* Join the group */ - silcpurple_chat_join(sg->gc, comp); - - silc_free(p); -} - -static void -silcpurple_chat_prv_cancel(SilcPurpleCharPrv p, PurpleRequestFields *fields) -{ - silc_free(p); -} - -static void -silcpurple_chat_prv(PurpleBlistNode *node, gpointer data) -{ - PurpleChat *chat; - PurpleConnection *gc; - SilcPurple sg; - - SilcPurpleCharPrv p; - PurpleRequestFields *fields; - PurpleRequestFieldGroup *g; - PurpleRequestField *f; - char tmp[512]; - - g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node)); - - chat = (PurpleChat *) node; - gc = purple_account_get_connection(chat->account); - sg = gc->proto_data; - - p = silc_calloc(1, sizeof(*p)); - if (!p) - return; - p->sg = sg; - - p->channel = g_hash_table_lookup(chat->components, "channel"); - p->c = purple_blist_find_chat(sg->account, p->channel); - - fields = purple_request_fields_new(); - - g = purple_request_field_group_new(NULL); - f = purple_request_field_string_new("name", _("Group Name"), - NULL, FALSE); - purple_request_field_group_add_field(g, f); - - f = purple_request_field_string_new("passphrase", _("Passphrase"), - NULL, FALSE); - purple_request_field_string_set_masked(f, TRUE); - purple_request_field_group_add_field(g, f); - - f = purple_request_field_string_new("alias", _("Alias"), - NULL, FALSE); - purple_request_field_group_add_field(g, f); - purple_request_fields_add_group(fields, g); - - g_snprintf(tmp, sizeof(tmp), - _("Please enter the %s channel private group name and passphrase."), - p->channel); - purple_request_fields(gc, _("Add Channel Private Group"), NULL, tmp, fields, - _("Add"), G_CALLBACK(silcpurple_chat_prv_add), - _("Cancel"), G_CALLBACK(silcpurple_chat_prv_cancel), - purple_connection_get_account(gc), NULL, NULL, p); -} - - -/****************************** Channel Modes ********************************/ - -static void -silcpurple_chat_permanent_reset(PurpleBlistNode *node, gpointer data) -{ - PurpleChat *chat; - PurpleConnection *gc; - SilcPurple sg; - - g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node)); - - chat = (PurpleChat *) node; - gc = purple_account_get_connection(chat->account); - sg = gc->proto_data; - - silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", - g_hash_table_lookup(chat->components, "channel"), - "-f", NULL); -} - -static void -silcpurple_chat_permanent(PurpleBlistNode *node, gpointer data) -{ - PurpleChat *chat; - PurpleConnection *gc; - SilcPurple sg; - const char *channel; - - g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node)); - - chat = (PurpleChat *) node; - gc = purple_account_get_connection(chat->account); - sg = gc->proto_data; - - if (!sg->conn) - return; - - /* XXX we should have ability to define which founder - key to use. Now we use the user's own public key - (default key). */ - - /* Call CMODE */ - channel = g_hash_table_lookup(chat->components, "channel"); - silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", channel, - "+f", NULL); -} - -typedef struct { - SilcPurple sg; - char *channel; -} *SilcPurpleChatInput; - -static void -silcpurple_chat_ulimit_cb(SilcPurpleChatInput s, const char *limit) -{ - SilcChannelEntry channel; - int ulimit = 0; - - channel = silc_client_get_channel(s->sg->client, s->sg->conn, - (char *)s->channel); - if (!channel) - return; - if (limit) - ulimit = atoi(limit); - - if (!limit || !(*limit) || *limit == '0') { - if (limit && ulimit == channel->user_limit) { - silc_free(s); - return; - } - silc_client_command_call(s->sg->client, s->sg->conn, NULL, "CMODE", - s->channel, "-l", NULL); - - silc_free(s); - return; - } - - if (ulimit == channel->user_limit) { - silc_free(s); - return; - } - - /* Call CMODE */ - silc_client_command_call(s->sg->client, s->sg->conn, NULL, "CMODE", - s->channel, "+l", limit, NULL); - - silc_free(s); -} - -static void -silcpurple_chat_ulimit(PurpleBlistNode *node, gpointer data) -{ - PurpleChat *chat; - PurpleConnection *gc; - SilcPurple sg; - - SilcPurpleChatInput s; - SilcChannelEntry channel; - char *ch; - char tmp[32]; - - g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node)); - - chat = (PurpleChat *) node; - gc = purple_account_get_connection(chat->account); - sg = gc->proto_data; - - if (!sg->conn) - return; - - ch = g_strdup(g_hash_table_lookup(chat->components, "channel")); - channel = silc_client_get_channel(sg->client, sg->conn, (char *)ch); - if (!channel) - return; - - s = silc_calloc(1, sizeof(*s)); - if (!s) - return; - s->channel = ch; - s->sg = sg; - g_snprintf(tmp, sizeof(tmp), "%d", (int)channel->user_limit); - purple_request_input(gc, _("User Limit"), NULL, - _("Set user limit on channel. Set to zero to reset user limit."), - tmp, FALSE, FALSE, NULL, - _("OK"), G_CALLBACK(silcpurple_chat_ulimit_cb), - _("Cancel"), G_CALLBACK(silcpurple_chat_ulimit_cb), - purple_connection_get_account(gc), NULL, NULL, s); -} - -static void -silcpurple_chat_resettopic(PurpleBlistNode *node, gpointer data) -{ - PurpleChat *chat; - PurpleConnection *gc; - SilcPurple sg; - - g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node)); - - chat = (PurpleChat *) node; - gc = purple_account_get_connection(chat->account); - sg = gc->proto_data; - - silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", - g_hash_table_lookup(chat->components, "channel"), - "-t", NULL); -} - -static void -silcpurple_chat_settopic(PurpleBlistNode *node, gpointer data) -{ - PurpleChat *chat; - PurpleConnection *gc; - SilcPurple sg; - - g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node)); - - chat = (PurpleChat *) node; - gc = purple_account_get_connection(chat->account); - sg = gc->proto_data; - - silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", - g_hash_table_lookup(chat->components, "channel"), - "+t", NULL); -} - -static void -silcpurple_chat_resetprivate(PurpleBlistNode *node, gpointer data) -{ - PurpleChat *chat; - PurpleConnection *gc; - SilcPurple sg; - - g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node)); - - chat = (PurpleChat *) node; - gc = purple_account_get_connection(chat->account); - sg = gc->proto_data; - - silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", - g_hash_table_lookup(chat->components, "channel"), - "-p", NULL); -} - -static void -silcpurple_chat_setprivate(PurpleBlistNode *node, gpointer data) -{ - PurpleChat *chat; - PurpleConnection *gc; - SilcPurple sg; - - g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node)); - - chat = (PurpleChat *) node; - gc = purple_account_get_connection(chat->account); - sg = gc->proto_data; - - silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", - g_hash_table_lookup(chat->components, "channel"), - "+p", NULL); -} - -static void -silcpurple_chat_resetsecret(PurpleBlistNode *node, gpointer data) -{ - PurpleChat *chat; - PurpleConnection *gc; - SilcPurple sg; - - g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node)); - - chat = (PurpleChat *) node; - gc = purple_account_get_connection(chat->account); - sg = gc->proto_data; - - silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", - g_hash_table_lookup(chat->components, "channel"), - "-s", NULL); -} - -static void -silcpurple_chat_setsecret(PurpleBlistNode *node, gpointer data) -{ - PurpleChat *chat; - PurpleConnection *gc; - SilcPurple sg; - - g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node)); - - chat = (PurpleChat *) node; - gc = purple_account_get_connection(chat->account); - sg = gc->proto_data; - - silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", - g_hash_table_lookup(chat->components, "channel"), - "+s", NULL); -} - -typedef struct { - SilcPurple sg; - SilcChannelEntry channel; -} *SilcPurpleChatWb; - -static void -silcpurple_chat_wb(PurpleBlistNode *node, gpointer data) -{ - SilcPurpleChatWb wb = data; - silcpurple_wb_init_ch(wb->sg, wb->channel); - silc_free(wb); -} - -GList *silcpurple_chat_menu(PurpleChat *chat) -{ - GHashTable *components = chat->components; - PurpleConnection *gc = purple_account_get_connection(chat->account); - SilcPurple sg = gc->proto_data; - SilcClientConnection conn = sg->conn; - const char *chname = NULL; - SilcChannelEntry channel = NULL; - SilcChannelUser chu = NULL; - SilcUInt32 mode = 0; - - GList *m = NULL; - PurpleMenuAction *act; - - if (components) - chname = g_hash_table_lookup(components, "channel"); - if (chname) - channel = silc_client_get_channel(sg->client, sg->conn, - (char *)chname); - if (channel) { - chu = silc_client_on_channel(channel, conn->local_entry); - if (chu) - mode = chu->mode; - } - - if (strstr(chname, "[Private Group]")) - return NULL; - - act = purple_menu_action_new(_("Get Info"), - PURPLE_CALLBACK(silcpurple_chat_getinfo_menu), - NULL, NULL); - m = g_list_append(m, act); - -#if 0 /* XXX For now these are not implemented. We need better - listview dialog from Purple for these. */ - if (mode & SILC_CHANNEL_UMODE_CHANOP) { - act = purple_menu_action_new(_("Invite List"), - PURPLE_CALLBACK(silcpurple_chat_invitelist), - NULL, NULL); - m = g_list_append(m, act); - - act = purple_menu_action_new(_("Ban List"), - PURPLE_CALLBACK(silcpurple_chat_banlist), - NULL, NULL); - m = g_list_append(m, act); - } -#endif - - if (chu) { - act = purple_menu_action_new(_("Add Private Group"), - PURPLE_CALLBACK(silcpurple_chat_prv), - NULL, NULL); - m = g_list_append(m, act); - } - - if (mode & SILC_CHANNEL_UMODE_CHANFO) { - act = purple_menu_action_new(_("Channel Authentication"), - PURPLE_CALLBACK(silcpurple_chat_chauth), - NULL, NULL); - m = g_list_append(m, act); - - if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) { - act = purple_menu_action_new(_("Reset Permanent"), - PURPLE_CALLBACK(silcpurple_chat_permanent_reset), - NULL, NULL); - m = g_list_append(m, act); - } else { - act = purple_menu_action_new(_("Set Permanent"), - PURPLE_CALLBACK(silcpurple_chat_permanent), - NULL, NULL); - m = g_list_append(m, act); - } - } - - if (mode & SILC_CHANNEL_UMODE_CHANOP) { - act = purple_menu_action_new(_("Set User Limit"), - PURPLE_CALLBACK(silcpurple_chat_ulimit), - NULL, NULL); - m = g_list_append(m, act); - - if (channel->mode & SILC_CHANNEL_MODE_TOPIC) { - act = purple_menu_action_new(_("Reset Topic Restriction"), - PURPLE_CALLBACK(silcpurple_chat_resettopic), - NULL, NULL); - m = g_list_append(m, act); - } else { - act = purple_menu_action_new(_("Set Topic Restriction"), - PURPLE_CALLBACK(silcpurple_chat_settopic), - NULL, NULL); - m = g_list_append(m, act); - } - - if (channel->mode & SILC_CHANNEL_MODE_PRIVATE) { - act = purple_menu_action_new(_("Reset Private Channel"), - PURPLE_CALLBACK(silcpurple_chat_resetprivate), - NULL, NULL); - m = g_list_append(m, act); - } else { - act = purple_menu_action_new(_("Set Private Channel"), - PURPLE_CALLBACK(silcpurple_chat_setprivate), - NULL, NULL); - m = g_list_append(m, act); - } - - if (channel->mode & SILC_CHANNEL_MODE_SECRET) { - act = purple_menu_action_new(_("Reset Secret Channel"), - PURPLE_CALLBACK(silcpurple_chat_resetsecret), - NULL, NULL); - m = g_list_append(m, act); - } else { - act = purple_menu_action_new(_("Set Secret Channel"), - PURPLE_CALLBACK(silcpurple_chat_setsecret), - NULL, NULL); - m = g_list_append(m, act); - } - } - - if (channel) { - SilcPurpleChatWb wb; - wb = silc_calloc(1, sizeof(*wb)); - wb->sg = sg; - wb->channel = channel; - act = purple_menu_action_new(_("Draw On Whiteboard"), - PURPLE_CALLBACK(silcpurple_chat_wb), - (void *)wb, NULL); - m = g_list_append(m, act); - } - - return m; -} - - -/******************************* Joining Etc. ********************************/ - -void silcpurple_chat_join_done(SilcClient client, - SilcClientConnection conn, - SilcClientEntry *clients, - SilcUInt32 clients_count, - void *context) -{ - PurpleConnection *gc = client->application; - SilcPurple sg = gc->proto_data; - SilcChannelEntry channel = context; - PurpleConversation *convo; - SilcUInt32 retry = SILC_PTR_TO_32(channel->context); - SilcHashTableList htl; - SilcChannelUser chu; - GList *users = NULL, *flags = NULL; - char tmp[256]; - - if (!clients && retry < 1) { - /* Resolving users failed, try again. */ - channel->context = SILC_32_TO_PTR(retry + 1); - silc_client_get_clients_by_channel(client, conn, channel, - silcpurple_chat_join_done, channel); - return; - } - - /* Add channel to Purple */ - channel->context = SILC_32_TO_PTR(++sg->channel_ids); - serv_got_joined_chat(gc, sg->channel_ids, channel->channel_name); - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - channel->channel_name, sg->account); - if (!convo) - return; - - /* Add all users to channel */ - silc_hash_table_list(channel->user_list, &htl); - while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { - PurpleConvChatBuddyFlags f = PURPLE_CBFLAGS_NONE; - if (!chu->client->nickname) - continue; - chu->context = SILC_32_TO_PTR(sg->channel_ids); - - if (chu->mode & SILC_CHANNEL_UMODE_CHANFO) - f |= PURPLE_CBFLAGS_FOUNDER; - if (chu->mode & SILC_CHANNEL_UMODE_CHANOP) - f |= PURPLE_CBFLAGS_OP; - users = g_list_append(users, g_strdup(chu->client->nickname)); - flags = g_list_append(flags, GINT_TO_POINTER(f)); - - if (chu->mode & SILC_CHANNEL_UMODE_CHANFO) { - if (chu->client == conn->local_entry) - g_snprintf(tmp, sizeof(tmp), - _("You are channel founder on %s"), - channel->channel_name); - else - g_snprintf(tmp, sizeof(tmp), - _("Channel founder on %s is %s"), - channel->channel_name, chu->client->nickname); - - purple_conversation_write(convo, NULL, tmp, - PURPLE_MESSAGE_SYSTEM, time(NULL)); - - } - } - silc_hash_table_list_reset(&htl); - - purple_conv_chat_add_users(PURPLE_CONV_CHAT(convo), users, NULL, flags, FALSE); - g_list_free(users); - g_list_free(flags); - - /* Set topic */ - if (channel->topic) - purple_conv_chat_set_topic(PURPLE_CONV_CHAT(convo), NULL, channel->topic); - - /* Set nick */ - purple_conv_chat_set_nick(PURPLE_CONV_CHAT(convo), conn->local_entry->nickname); -} - -char *silcpurple_get_chat_name(GHashTable *data) -{ - return g_strdup(g_hash_table_lookup(data, "channel")); -} - -void silcpurple_chat_join(PurpleConnection *gc, GHashTable *data) -{ - SilcPurple sg = gc->proto_data; - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - const char *channel, *passphrase, *parentch; - - if (!conn) - return; - - channel = g_hash_table_lookup(data, "channel"); - passphrase = g_hash_table_lookup(data, "passphrase"); - - /* Check if we are joining a private group. Handle it - purely locally as it's not a real channel */ - if (strstr(channel, "[Private Group]")) { - SilcChannelEntry channel_entry; - SilcChannelPrivateKey key; - PurpleChat *c; - SilcPurplePrvgrp grp; - - c = purple_blist_find_chat(sg->account, channel); - parentch = purple_blist_node_get_string((PurpleBlistNode *)c, "parentch"); - if (!parentch) - return; - - channel_entry = silc_client_get_channel(sg->client, sg->conn, - (char *)parentch); - if (!channel_entry || - !silc_client_on_channel(channel_entry, sg->conn->local_entry)) { - char tmp[512]; - g_snprintf(tmp, sizeof(tmp), - _("You have to join the %s channel before you are " - "able to join the private group"), parentch); - purple_notify_error(gc, _("Join Private Group"), - _("Cannot join private group"), tmp); - return; - } - - /* Add channel private key */ - if (!silc_client_add_channel_private_key(client, conn, - channel_entry, channel, - NULL, NULL, - (unsigned char *)passphrase, - strlen(passphrase), &key)) - return; - - /* Join the group */ - grp = silc_calloc(1, sizeof(*grp)); - if (!grp) - return; - grp->id = ++sg->channel_ids + SILCPURPLE_PRVGRP; - grp->chid = SILC_PTR_TO_32(channel_entry->context); - grp->parentch = parentch; - grp->channel = channel; - grp->key = key; - sg->grps = g_list_append(sg->grps, grp); - serv_got_joined_chat(gc, grp->id, channel); - return; - } - - /* XXX We should have other properties here as well: - 1. whether to try to authenticate to the channel - 1a. with default key, - 1b. with specific key. - 2. whether to try to authenticate to become founder. - 2a. with default key, - 2b. with specific key. - - Since now such variety is not possible in the join dialog - we always use -founder and -auth options, which try to - do both 1 and 2 with default keys. */ - - /* Call JOIN */ - if ((passphrase != NULL) && (*passphrase != '\0')) - silc_client_command_call(client, conn, NULL, "JOIN", - channel, passphrase, "-auth", "-founder", NULL); - else - silc_client_command_call(client, conn, NULL, "JOIN", - channel, "-auth", "-founder", NULL); -} - -void silcpurple_chat_invite(PurpleConnection *gc, int id, const char *msg, - const char *name) -{ - SilcPurple sg = gc->proto_data; - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - SilcHashTableList htl; - SilcChannelUser chu; - gboolean found = FALSE; - - if (!conn) - return; - - /* See if we are inviting on a private group. Invite - to the actual channel */ - if (id > SILCPURPLE_PRVGRP) { - GList *l; - SilcPurplePrvgrp prv; - - for (l = sg->grps; l; l = l->next) - if (((SilcPurplePrvgrp)l->data)->id == id) - break; - if (!l) - return; - prv = l->data; - id = prv->chid; - } - - /* Find channel by id */ - silc_hash_table_list(conn->local_entry->channels, &htl); - while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { - if (SILC_PTR_TO_32(chu->channel->context) == id ) { - found = TRUE; - break; - } - } - silc_hash_table_list_reset(&htl); - if (!found) - return; - - /* Call INVITE */ - silc_client_command_call(client, conn, NULL, "INVITE", - chu->channel->channel_name, - name, NULL); -} - -void silcpurple_chat_leave(PurpleConnection *gc, int id) -{ - SilcPurple sg = gc->proto_data; - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - SilcHashTableList htl; - SilcChannelUser chu; - gboolean found = FALSE; - GList *l; - SilcPurplePrvgrp prv; - - if (!conn) - return; - - /* See if we are leaving a private group */ - if (id > SILCPURPLE_PRVGRP) { - SilcChannelEntry channel; - - for (l = sg->grps; l; l = l->next) - if (((SilcPurplePrvgrp)l->data)->id == id) - break; - if (!l) - return; - prv = l->data; - channel = silc_client_get_channel(sg->client, sg->conn, - (char *)prv->parentch); - if (!channel) - return; - silc_client_del_channel_private_key(client, conn, - channel, prv->key); - silc_free(prv); - sg->grps = g_list_remove(sg->grps, prv); - serv_got_chat_left(gc, id); - return; - } - - /* Find channel by id */ - silc_hash_table_list(conn->local_entry->channels, &htl); - while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { - if (SILC_PTR_TO_32(chu->channel->context) == id ) { - found = TRUE; - break; - } - } - silc_hash_table_list_reset(&htl); - if (!found) - return; - - /* Call LEAVE */ - silc_client_command_call(client, conn, NULL, "LEAVE", - chu->channel->channel_name, NULL); - - serv_got_chat_left(gc, id); - - /* Leave from private groups on this channel as well */ - for (l = sg->grps; l; l = l->next) - if (((SilcPurplePrvgrp)l->data)->chid == id) { - prv = l->data; - silc_client_del_channel_private_key(client, conn, - chu->channel, - prv->key); - serv_got_chat_left(gc, prv->id); - silc_free(prv); - sg->grps = g_list_remove(sg->grps, prv); - if (!sg->grps) - break; - } -} - -int silcpurple_chat_send(PurpleConnection *gc, int id, const char *msg, PurpleMessageFlags msgflags) -{ - SilcPurple sg = gc->proto_data; - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - SilcHashTableList htl; - SilcChannelUser chu; - SilcChannelEntry channel = NULL; - SilcChannelPrivateKey key = NULL; - SilcUInt32 flags; - int ret; - char *msg2, *tmp; - gboolean found = FALSE; - gboolean sign = purple_account_get_bool(sg->account, "sign-verify", FALSE); - - if (!msg || !conn) - return 0; - - flags = SILC_MESSAGE_FLAG_UTF8; - - tmp = msg2 = purple_unescape_html(msg); - - if (!g_ascii_strncasecmp(msg2, "/me ", 4)) - { - msg2 += 4; - if (!*msg2) { - g_free(tmp); - return 0; - } - flags |= SILC_MESSAGE_FLAG_ACTION; - } else if (strlen(msg) > 1 && msg[0] == '/') { - if (!silc_client_command_call(client, conn, msg + 1)) - purple_notify_error(gc, _("Call Command"), _("Cannot call command"), - _("Unknown command")); - g_free(tmp); - return 0; - } - - - if (sign) - flags |= SILC_MESSAGE_FLAG_SIGNED; - - /* Get the channel private key if we are sending on - private group */ - if (id > SILCPURPLE_PRVGRP) { - GList *l; - SilcPurplePrvgrp prv; - - for (l = sg->grps; l; l = l->next) - if (((SilcPurplePrvgrp)l->data)->id == id) - break; - if (!l) { - g_free(tmp); - return 0; - } - prv = l->data; - channel = silc_client_get_channel(sg->client, sg->conn, - (char *)prv->parentch); - if (!channel) { - g_free(tmp); - return 0; - } - key = prv->key; - } - - if (!channel) { - /* Find channel by id */ - silc_hash_table_list(conn->local_entry->channels, &htl); - while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { - if (SILC_PTR_TO_32(chu->channel->context) == id ) { - found = TRUE; - break; - } - } - silc_hash_table_list_reset(&htl); - if (!found) { - g_free(tmp); - return 0; - } - channel = chu->channel; - } - - /* Send channel message */ - ret = silc_client_send_channel_message(client, conn, channel, key, - flags, (unsigned char *)msg2, - strlen(msg2), TRUE); - if (ret) { - serv_got_chat_in(gc, id, purple_connection_get_display_name(gc), msgflags, msg, - time(NULL)); - } - g_free(tmp); - - return ret; -} - -void silcpurple_chat_set_topic(PurpleConnection *gc, int id, const char *topic) -{ - SilcPurple sg = gc->proto_data; - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - SilcHashTableList htl; - SilcChannelUser chu; - gboolean found = FALSE; - - if (!conn) - return; - - /* See if setting topic on private group. Set it - on the actual channel */ - if (id > SILCPURPLE_PRVGRP) { - GList *l; - SilcPurplePrvgrp prv; - - for (l = sg->grps; l; l = l->next) - if (((SilcPurplePrvgrp)l->data)->id == id) - break; - if (!l) - return; - prv = l->data; - id = prv->chid; - } - - /* Find channel by id */ - silc_hash_table_list(conn->local_entry->channels, &htl); - while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { - if (SILC_PTR_TO_32(chu->channel->context) == id ) { - found = TRUE; - break; - } - } - silc_hash_table_list_reset(&htl); - if (!found) - return; - - /* Call TOPIC */ - silc_client_command_call(client, conn, NULL, "TOPIC", - chu->channel->channel_name, topic, NULL); -} - -PurpleRoomlist *silcpurple_roomlist_get_list(PurpleConnection *gc) -{ - SilcPurple sg = gc->proto_data; - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - GList *fields = NULL; - PurpleRoomlistField *f; - - if (!conn) - return NULL; - - if (sg->roomlist) - purple_roomlist_unref(sg->roomlist); - - sg->roomlist_cancelled = FALSE; - - sg->roomlist = purple_roomlist_new(purple_connection_get_account(gc)); - f = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_STRING, "", "channel", TRUE); - fields = g_list_append(fields, f); - f = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_INT, - _("Users"), "users", FALSE); - fields = g_list_append(fields, f); - f = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_STRING, - _("Topic"), "topic", FALSE); - fields = g_list_append(fields, f); - purple_roomlist_set_fields(sg->roomlist, fields); - - /* Call LIST */ - silc_client_command_call(client, conn, "LIST"); - - purple_roomlist_set_in_progress(sg->roomlist, TRUE); - - return sg->roomlist; -} - -void silcpurple_roomlist_cancel(PurpleRoomlist *list) -{ - PurpleConnection *gc = purple_account_get_connection(list->account); - SilcPurple sg; - - if (!gc) - return; - sg = gc->proto_data; - - purple_roomlist_set_in_progress(list, FALSE); - if (sg->roomlist == list) { - purple_roomlist_unref(sg->roomlist); - sg->roomlist = NULL; - sg->roomlist_cancelled = TRUE; - } -} diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/silc10/ft.c --- a/libpurple/protocols/silc10/ft.c Mon Aug 22 11:20:05 2011 +0900 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,412 +0,0 @@ -/* - - silcpurple_ft.c - - Author: Pekka Riikonen - - Copyright (C) 2004 Pekka Riikonen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - -*/ - -#include "silcincludes.h" -#include "silcclient.h" -#include "silcpurple.h" - -/****************************** File Transfer ********************************/ - -/* This implements the secure file transfer protocol (SFTP) using the SILC - SFTP library implementation. The API we use from the SILC Toolkit is the - SILC Client file transfer API, as it provides a simple file transfer we - need in this case. We could use the SILC SFTP API directly, but it would - be an overkill since we'd effectively re-implement the file transfer what - the SILC Client's file transfer API already provides. - - From Purple we do NOT use the FT API to do the transfer as it is very limiting. - In fact it does not suite to file transfers like SFTP at all. For example, - it assumes that read operations are synchronous what they are not in SFTP. - It also assumes that the file transfer socket is to be handled by the Purple - eventloop, and this naturally is something we don't want to do in case of - SILC Toolkit. The FT API suites well to purely stream based file transfers - like HTTP GET and similar. - - For this reason, we directly access the Purple GKT FT API and hack the FT - API to merely provide the user interface experience and all the magic - is done in the SILC Toolkit. Ie. we update the statistics information in - the FT API for user interface, and that's it. A bit dirty but until the - FT API gets better this is the way to go. Good thing that FT API allowed - us to do this. */ - -typedef struct { - SilcPurple sg; - SilcClientEntry client_entry; - SilcUInt32 session_id; - char *hostname; - SilcUInt16 port; - PurpleXfer *xfer; - - SilcClientFileName completion; - void *completion_context; -} *SilcPurpleXfer; - -static void -silcpurple_ftp_monitor(SilcClient client, - SilcClientConnection conn, - SilcClientMonitorStatus status, - SilcClientFileError error, - SilcUInt64 offset, - SilcUInt64 filesize, - SilcClientEntry client_entry, - SilcUInt32 session_id, - const char *filepath, - void *context) -{ - SilcPurpleXfer xfer = context; - PurpleConnection *gc = xfer->sg->gc; - char tmp[256]; - - if (status == SILC_CLIENT_FILE_MONITOR_CLOSED) { - purple_xfer_unref(xfer->xfer); - silc_free(xfer); - return; - } - - if (status == SILC_CLIENT_FILE_MONITOR_KEY_AGREEMENT) - return; - - if (status == SILC_CLIENT_FILE_MONITOR_ERROR) { - if (error == SILC_CLIENT_FILE_NO_SUCH_FILE) { - g_snprintf(tmp, sizeof(tmp), "No such file %s", - filepath ? filepath : "[N/A]"); - purple_notify_error(gc, _("Secure File Transfer"), - _("Error during file transfer"), tmp); - } else if (error == SILC_CLIENT_FILE_PERMISSION_DENIED) { - purple_notify_error(gc, _("Secure File Transfer"), - _("Error during file transfer"), - _("Permission denied")); - } else if (error == SILC_CLIENT_FILE_KEY_AGREEMENT_FAILED) { - purple_notify_error(gc, _("Secure File Transfer"), - _("Error during file transfer"), - _("Key agreement failed")); - } else if (error == SILC_CLIENT_FILE_UNKNOWN_SESSION) { - purple_notify_error(gc, _("Secure File Transfer"), - _("Error during file transfer"), - _("File transfer session does not exist")); - } else { - purple_notify_error(gc, _("Secure File Transfer"), - _("Error during file transfer"), NULL); - } - silc_client_file_close(client, conn, session_id); - purple_xfer_unref(xfer->xfer); - silc_free(xfer); - return; - } - - /* Update file transfer UI */ - if (!offset && filesize) - purple_xfer_set_size(xfer->xfer, filesize); - if (offset && filesize) { - xfer->xfer->bytes_sent = offset; - xfer->xfer->bytes_remaining = filesize - offset; - } - purple_xfer_update_progress(xfer->xfer); - - if (status == SILC_CLIENT_FILE_MONITOR_SEND || - status == SILC_CLIENT_FILE_MONITOR_RECEIVE) { - if (offset == filesize) { - /* Download finished */ - purple_xfer_set_completed(xfer->xfer, TRUE); - silc_client_file_close(client, conn, session_id); - } - } -} - -static void -silcpurple_ftp_cancel(PurpleXfer *x) -{ - SilcPurpleXfer xfer = x->data; - xfer->xfer->status = PURPLE_XFER_STATUS_CANCEL_LOCAL; - purple_xfer_update_progress(xfer->xfer); - silc_client_file_close(xfer->sg->client, xfer->sg->conn, xfer->session_id); -} - -static void -silcpurple_ftp_ask_name_cancel(PurpleXfer *x) -{ - SilcPurpleXfer xfer = x->data; - - /* Cancel the transmission */ - xfer->completion(NULL, xfer->completion_context); - silc_client_file_close(xfer->sg->client, xfer->sg->conn, xfer->session_id); -} - -static void -silcpurple_ftp_ask_name_ok(PurpleXfer *x) -{ - SilcPurpleXfer xfer = x->data; - const char *name; - - name = purple_xfer_get_local_filename(x); - g_unlink(name); - xfer->completion(name, xfer->completion_context); -} - -static void -silcpurple_ftp_ask_name(SilcClient client, - SilcClientConnection conn, - SilcUInt32 session_id, - const char *remote_filename, - SilcClientFileName completion, - void *completion_context, - void *context) -{ - SilcPurpleXfer xfer = context; - - xfer->completion = completion; - xfer->completion_context = completion_context; - - purple_xfer_set_init_fnc(xfer->xfer, silcpurple_ftp_ask_name_ok); - purple_xfer_set_request_denied_fnc(xfer->xfer, silcpurple_ftp_ask_name_cancel); - - /* Request to save the file */ - purple_xfer_set_filename(xfer->xfer, remote_filename); - purple_xfer_request(xfer->xfer); -} - -static void -silcpurple_ftp_request_result(PurpleXfer *x) -{ - SilcPurpleXfer xfer = x->data; - SilcClientFileError status; - PurpleConnection *gc = xfer->sg->gc; - - if (purple_xfer_get_status(x) != PURPLE_XFER_STATUS_ACCEPTED) - return; - - /* Start the file transfer */ - status = silc_client_file_receive(xfer->sg->client, xfer->sg->conn, - silcpurple_ftp_monitor, xfer, - NULL, xfer->session_id, - silcpurple_ftp_ask_name, xfer); - switch (status) { - case SILC_CLIENT_FILE_OK: - return; - break; - - case SILC_CLIENT_FILE_UNKNOWN_SESSION: - purple_notify_error(gc, _("Secure File Transfer"), - _("No file transfer session active"), NULL); - break; - - case SILC_CLIENT_FILE_ALREADY_STARTED: - purple_notify_error(gc, _("Secure File Transfer"), - _("File transfer already started"), NULL); - break; - - case SILC_CLIENT_FILE_KEY_AGREEMENT_FAILED: - purple_notify_error(gc, _("Secure File Transfer"), - _("Could not perform key agreement for file transfer"), - NULL); - break; - - default: - purple_notify_error(gc, _("Secure File Transfer"), - _("Could not start the file transfer"), NULL); - break; - } - - /* Error */ - purple_xfer_unref(xfer->xfer); - g_free(xfer->hostname); - silc_free(xfer); -} - -static void -silcpurple_ftp_request_denied(PurpleXfer *x) -{ - -} - -void silcpurple_ftp_request(SilcClient client, SilcClientConnection conn, - SilcClientEntry client_entry, SilcUInt32 session_id, - const char *hostname, SilcUInt16 port) -{ - PurpleConnection *gc = client->application; - SilcPurple sg = gc->proto_data; - SilcPurpleXfer xfer; - - xfer = silc_calloc(1, sizeof(*xfer)); - if (!xfer) { - silc_client_file_close(sg->client, sg->conn, session_id); - return; - } - - xfer->sg = sg; - xfer->client_entry = client_entry; - xfer->session_id = session_id; - xfer->hostname = g_strdup(hostname); - xfer->port = port; - xfer->xfer = purple_xfer_new(xfer->sg->account, PURPLE_XFER_RECEIVE, - xfer->client_entry->nickname); - if (!xfer->xfer) { - silc_client_file_close(xfer->sg->client, xfer->sg->conn, xfer->session_id); - g_free(xfer->hostname); - silc_free(xfer); - return; - } - purple_xfer_set_init_fnc(xfer->xfer, silcpurple_ftp_request_result); - purple_xfer_set_request_denied_fnc(xfer->xfer, silcpurple_ftp_request_denied); - purple_xfer_set_cancel_recv_fnc(xfer->xfer, silcpurple_ftp_cancel); - xfer->xfer->remote_ip = g_strdup(hostname); - xfer->xfer->remote_port = port; - xfer->xfer->data = xfer; - - /* File transfer request */ - purple_xfer_request(xfer->xfer); -} - -static void -silcpurple_ftp_send_cancel(PurpleXfer *x) -{ - SilcPurpleXfer xfer = x->data; - silc_client_file_close(xfer->sg->client, xfer->sg->conn, xfer->session_id); - purple_xfer_unref(xfer->xfer); - g_free(xfer->hostname); - silc_free(xfer); -} - -static void -silcpurple_ftp_send(PurpleXfer *x) -{ - SilcPurpleXfer xfer = x->data; - const char *name; - char *local_ip = NULL, *remote_ip = NULL; - gboolean local = TRUE; - - name = purple_xfer_get_local_filename(x); - - /* Do the same magic what we do with key agreement (see silcpurple_buddy.c) - to see if we are behind NAT. */ - if (silc_net_check_local_by_sock(xfer->sg->conn->sock->sock, - NULL, &local_ip)) { - /* Check if the IP is private */ - if (silcpurple_ip_is_private(local_ip)) { - local = FALSE; - /* Local IP is private, resolve the remote server IP to see whether - we are talking to Internet or just on LAN. */ - if (silc_net_check_host_by_sock(xfer->sg->conn->sock->sock, NULL, - &remote_ip)) - if (silcpurple_ip_is_private(remote_ip)) - /* We assume we are in LAN. Let's provide the connection point. */ - local = TRUE; - } - } - - if (local && !local_ip) - local_ip = silc_net_localip(); - - /* Send the file */ - silc_client_file_send(xfer->sg->client, xfer->sg->conn, - silcpurple_ftp_monitor, xfer, - local_ip, 0, !local, xfer->client_entry, - name, &xfer->session_id); - - silc_free(local_ip); - silc_free(remote_ip); -} - -static void -silcpurple_ftp_send_file_resolved(SilcClient client, - SilcClientConnection conn, - SilcClientEntry *clients, - SilcUInt32 clients_count, - void *context) -{ - PurpleConnection *gc = client->application; - char tmp[256]; - - if (!clients) { - g_snprintf(tmp, sizeof(tmp), - _("User %s is not present in the network"), - (const char *)context); - purple_notify_error(gc, _("Secure File Transfer"), - _("Cannot send file"), tmp); - silc_free(context); - return; - } - - silcpurple_ftp_send_file(client->application, (const char *)context, NULL); - silc_free(context); -} - -PurpleXfer *silcpurple_ftp_new_xfer(PurpleConnection *gc, const char *name) -{ - SilcPurple sg = gc->proto_data; - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - SilcClientEntry *clients; - SilcUInt32 clients_count; - SilcPurpleXfer xfer; - char *nickname; - - g_return_val_if_fail(name != NULL, NULL); - - if (!silc_parse_userfqdn(name, &nickname, NULL)) - return NULL; - - /* Find client entry */ - clients = silc_client_get_clients_local(client, conn, nickname, name, - &clients_count); - if (!clients) { - silc_client_get_clients(client, conn, nickname, NULL, - silcpurple_ftp_send_file_resolved, - strdup(name)); - silc_free(nickname); - return NULL; - } - - xfer = silc_calloc(1, sizeof(*xfer)); - - g_return_val_if_fail(xfer != NULL, NULL); - - xfer->sg = sg; - xfer->client_entry = clients[0]; - xfer->xfer = purple_xfer_new(xfer->sg->account, PURPLE_XFER_SEND, - xfer->client_entry->nickname); - if (!xfer->xfer) { - silc_client_file_close(xfer->sg->client, xfer->sg->conn, xfer->session_id); - g_free(xfer->hostname); - silc_free(xfer); - return NULL; - } - purple_xfer_set_init_fnc(xfer->xfer, silcpurple_ftp_send); - purple_xfer_set_request_denied_fnc(xfer->xfer, silcpurple_ftp_request_denied); - purple_xfer_set_cancel_send_fnc(xfer->xfer, silcpurple_ftp_send_cancel); - xfer->xfer->data = xfer; - - silc_free(clients); - silc_free(nickname); - - return xfer->xfer; -} - -void silcpurple_ftp_send_file(PurpleConnection *gc, const char *name, const char *file) -{ - PurpleXfer *xfer = silcpurple_ftp_new_xfer(gc, name); - - g_return_if_fail(xfer != NULL); - - /* Choose file to send */ - if (file) - purple_xfer_request_accepted(xfer, file); - else - purple_xfer_request(xfer); -} diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/silc10/ops.c --- a/libpurple/protocols/silc10/ops.c Mon Aug 22 11:20:05 2011 +0900 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2063 +0,0 @@ -/* - - silcpurple_ops.c - - Author: Pekka Riikonen - - Copyright (C) 2004 Pekka Riikonen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - -*/ - -#include "silcincludes.h" -#include "silcclient.h" -#include "silcpurple.h" -#include "imgstore.h" -#include "wb.h" - -static void -silc_channel_message(SilcClient client, SilcClientConnection conn, - SilcClientEntry sender, SilcChannelEntry channel, - SilcMessagePayload payload, SilcChannelPrivateKey key, - SilcMessageFlags flags, const unsigned char *message, - SilcUInt32 message_len); -static void -silc_private_message(SilcClient client, SilcClientConnection conn, - SilcClientEntry sender, SilcMessagePayload payload, - SilcMessageFlags flags, const unsigned char *message, - SilcUInt32 message_len); - -/* Message sent to the application by library. `conn' associates the - message to a specific connection. `conn', however, may be NULL. - The `type' indicates the type of the message sent by the library. - The application can for example filter the message according the - type. */ - -static void -silc_say(SilcClient client, SilcClientConnection conn, - SilcClientMessageType type, char *msg, ...) -{ - /* Nothing */ -} - -#ifdef HAVE_SILCMIME_H -/* Processes incoming MIME message. Can be private message or channel - message. */ - -static void -silcpurple_mime_message(SilcClient client, SilcClientConnection conn, - SilcClientEntry sender, SilcChannelEntry channel, - SilcMessagePayload payload, SilcChannelPrivateKey key, - SilcMessageFlags flags, SilcMime mime, - gboolean recursive) -{ - PurpleConnection *gc = client->application; - SilcPurple sg = gc->proto_data; - const char *type; - const unsigned char *data; - SilcUInt32 data_len; - PurpleMessageFlags cflags = 0; - PurpleConversation *convo = NULL; - - if (!mime) - return; - - /* Check for fragmented MIME message */ - if (silc_mime_is_partial(mime)) { - if (!sg->mimeass) - sg->mimeass = silc_mime_assembler_alloc(); - - /* Defragment */ - mime = silc_mime_assemble(sg->mimeass, mime); - if (!mime) - /* More fragments to come */ - return; - - /* Process the complete message */ - silcpurple_mime_message(client, conn, sender, channel, - payload, key, flags, mime, FALSE); - return; - } - - /* Check for multipart message */ - if (silc_mime_is_multipart(mime)) { - SilcMime p; - const char *mtype; - SilcDList parts = silc_mime_get_multiparts(mime, &mtype); - - /* Only "mixed" type supported */ - if (strcmp(mtype, "mixed")) - goto out; - - silc_dlist_start(parts); - while ((p = silc_dlist_get(parts)) != SILC_LIST_END) { - /* Recursively process parts */ - silcpurple_mime_message(client, conn, sender, channel, - payload, key, flags, p, TRUE); - } - goto out; - } - - /* Get content type and MIME data */ - type = silc_mime_get_field(mime, "Content-Type"); - if (!type) - goto out; - data = silc_mime_get_data(mime, &data_len); - if (!data) - goto out; - - /* Process according to content type */ - - /* Plain text */ - if (strstr(type, "text/plain")) { - /* Default is UTF-8, don't check for other charsets */ - if (!strstr(type, "utf-8")) - goto out; - - if (channel) - silc_channel_message(client, conn, sender, channel, - payload, key, - SILC_MESSAGE_FLAG_UTF8, data, - data_len); - else - silc_private_message(client, conn, sender, payload, - SILC_MESSAGE_FLAG_UTF8, data, - data_len); - goto out; - } - - /* Image */ - if (strstr(type, "image/png") || - strstr(type, "image/jpeg") || - strstr(type, "image/gif") || - strstr(type, "image/tiff")) { - char tmp[32]; - int imgid; - - /* Get channel convo (if message is for channel) */ - if (key && channel) { - GList *l; - SilcPurplePrvgrp prv; - - for (l = sg->grps; l; l = l->next) - if (((SilcPurplePrvgrp)l->data)->key == key) { - prv = l->data; - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - prv->channel, sg->account); - break; - } - } - if (channel && !convo) - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - channel->channel_name, sg->account); - if (channel && !convo) - goto out; - - imgid = purple_imgstore_add_with_id(g_memdup(data, data_len), data_len, ""); - if (imgid) { - cflags |= PURPLE_MESSAGE_IMAGES | PURPLE_MESSAGE_RECV; - g_snprintf(tmp, sizeof(tmp), "", imgid); - - if (channel) - serv_got_chat_in(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo)), - sender->nickname ? - sender->nickname : - "", cflags, - tmp, time(NULL)); - else - serv_got_im(gc, sender->nickname ? - sender->nickname : "", - tmp, cflags, time(NULL)); - - purple_imgstore_unref_by_id(imgid); - cflags = 0; - } - goto out; - } - - /* Whiteboard message */ - if (strstr(type, "application/x-wb") && - !purple_account_get_bool(sg->account, "block-wb", FALSE)) { - if (channel) - silcpurple_wb_receive_ch(client, conn, sender, channel, - payload, flags, data, data_len); - else - silcpurple_wb_receive(client, conn, sender, payload, - flags, data, data_len); - goto out; - } - - out: - if (!recursive) - silc_mime_free(mime); -} -#endif /* HAVE_SILCMIME_H */ - -/* Message for a channel. The `sender' is the sender of the message - The `channel' is the channel. The `message' is the message. Note - that `message' maybe NULL. The `flags' indicates message flags - and it is used to determine how the message can be interpreted - (like it may tell the message is multimedia message). */ - -static void -silc_channel_message(SilcClient client, SilcClientConnection conn, - SilcClientEntry sender, SilcChannelEntry channel, - SilcMessagePayload payload, SilcChannelPrivateKey key, - SilcMessageFlags flags, const unsigned char *message, - SilcUInt32 message_len) -{ - PurpleConnection *gc = client->application; - SilcPurple sg = gc->proto_data; - PurpleConversation *convo = NULL; - char *msg, *tmp; - - if (!message) - return; - - if (key) { - GList *l; - SilcPurplePrvgrp prv; - - for (l = sg->grps; l; l = l->next) - if (((SilcPurplePrvgrp)l->data)->key == key) { - prv = l->data; - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - prv->channel, sg->account); - break; - } - } - if (!convo) - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - channel->channel_name, sg->account); - if (!convo) - return; - - if (flags & SILC_MESSAGE_FLAG_SIGNED && - purple_account_get_bool(sg->account, "sign-verify", FALSE)) { - /* XXX */ - } - - if (flags & SILC_MESSAGE_FLAG_DATA) { - /* Process MIME message */ -#ifdef HAVE_SILCMIME_H - SilcMime mime; - mime = silc_mime_decode(message, message_len); - silcpurple_mime_message(client, conn, sender, channel, payload, - key, flags, mime, FALSE); -#else - char type[128], enc[128]; - unsigned char *data; - SilcUInt32 data_len; - - memset(type, 0, sizeof(type)); - memset(enc, 0, sizeof(enc)); - - if (!silc_mime_parse(message, message_len, NULL, 0, - type, sizeof(type) - 1, enc, sizeof(enc) - 1, &data, - &data_len)) - return; - - if (!strcmp(type, "application/x-wb") && - !strcmp(enc, "binary") && - !purple_account_get_bool(sg->account, "block-wb", FALSE)) - silcpurple_wb_receive_ch(client, conn, sender, channel, - payload, flags, data, data_len); -#endif - return; - } - - if (flags & SILC_MESSAGE_FLAG_ACTION) { - msg = g_strdup_printf("/me %s", - (const char *)message); - if (!msg) - return; - - tmp = g_markup_escape_text(msg, -1); - /* Send to Purple */ - serv_got_chat_in(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo)), - sender->nickname ? - sender->nickname : "", 0, - tmp, time(NULL)); - g_free(tmp); - g_free(msg); - return; - } - - if (flags & SILC_MESSAGE_FLAG_NOTICE) { - msg = g_strdup_printf("(notice) %s %s", - sender->nickname ? - sender->nickname : "", - (const char *)message); - if (!msg) - return; - - /* Send to Purple */ - purple_conversation_write(convo, NULL, (const char *)msg, - PURPLE_MESSAGE_SYSTEM, time(NULL)); - g_free(msg); - return; - } - - if (flags & SILC_MESSAGE_FLAG_UTF8) { - tmp = g_markup_escape_text((const char *)message, -1); - /* Send to Purple */ - serv_got_chat_in(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo)), - sender->nickname ? - sender->nickname : "", 0, - tmp, time(NULL)); - g_free(tmp); - } -} - - -/* Private message to the client. The `sender' is the sender of the - message. The message is `message'and maybe NULL. The `flags' - indicates message flags and it is used to determine how the message - can be interpreted (like it may tell the message is multimedia - message). */ - -static void -silc_private_message(SilcClient client, SilcClientConnection conn, - SilcClientEntry sender, SilcMessagePayload payload, - SilcMessageFlags flags, const unsigned char *message, - SilcUInt32 message_len) -{ - PurpleConnection *gc = client->application; - SilcPurple sg = gc->proto_data; - PurpleConversation *convo = NULL; - char *msg, *tmp; - - if (!message) - return; - - if (sender->nickname) - /* XXX - Should this be PURPLE_CONV_TYPE_IM? */ - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY, - sender->nickname, sg->account); - - if (flags & SILC_MESSAGE_FLAG_SIGNED && - purple_account_get_bool(sg->account, "sign-verify", FALSE)) { - /* XXX */ - } - - if (flags & SILC_MESSAGE_FLAG_DATA) { -#ifdef HAVE_SILCMIME_H - /* Process MIME message */ - SilcMime mime; - mime = silc_mime_decode(message, message_len); - silcpurple_mime_message(client, conn, sender, NULL, payload, - NULL, flags, mime, FALSE); -#else - char type[128], enc[128]; - unsigned char *data; - SilcUInt32 data_len; - - memset(type, 0, sizeof(type)); - memset(enc, 0, sizeof(enc)); - - if (!silc_mime_parse(message, message_len, NULL, 0, - type, sizeof(type) - 1, enc, sizeof(enc) - 1, &data, - &data_len)) - return; - - if (!strcmp(type, "application/x-wb") && - !strcmp(enc, "binary") && - !purple_account_get_bool(sg->account, "block-wb", FALSE)) - silcpurple_wb_receive(client, conn, sender, payload, - flags, data, data_len); -#endif - return; - } - - if (flags & SILC_MESSAGE_FLAG_ACTION && convo) { - msg = g_strdup_printf("/me %s", - (const char *)message); - if (!msg) - return; - - tmp = g_markup_escape_text(msg, -1); - /* Send to Purple */ - serv_got_im(gc, sender->nickname ? - sender->nickname : "", - tmp, 0, time(NULL)); - g_free(msg); - g_free(tmp); - return; - } - - if (flags & SILC_MESSAGE_FLAG_NOTICE && convo) { - msg = g_strdup_printf("(notice) %s %s", - sender->nickname ? - sender->nickname : "", - (const char *)message); - if (!msg) - return; - - /* Send to Purple */ - purple_conversation_write(convo, NULL, (const char *)msg, - PURPLE_MESSAGE_SYSTEM, time(NULL)); - g_free(msg); - return; - } - - if (flags & SILC_MESSAGE_FLAG_UTF8) { - tmp = g_markup_escape_text((const char *)message, -1); - /* Send to Purple */ - serv_got_im(gc, sender->nickname ? - sender->nickname : "", - tmp, 0, time(NULL)); - g_free(tmp); - } -} - - -/* Notify message to the client. The notify arguments are sent in the - same order as servers sends them. The arguments are same as received - from the server except for ID's. If ID is received application receives - the corresponding entry to the ID. For example, if Client ID is received - application receives SilcClientEntry. Also, if the notify type is - for channel the channel entry is sent to application (even if server - does not send it because client library gets the channel entry from - the Channel ID in the packet's header). */ - -static void -silc_notify(SilcClient client, SilcClientConnection conn, - SilcNotifyType type, ...) -{ - va_list va; - PurpleConnection *gc = client->application; - SilcPurple sg = gc->proto_data; - PurpleConversation *convo; - SilcClientEntry client_entry, client_entry2; - SilcChannelEntry channel; - SilcServerEntry server_entry; - SilcIdType idtype; - void *entry; - SilcUInt32 mode; - SilcHashTableList htl; - SilcChannelUser chu; - char buf[512], buf2[512], *tmp, *name; - SilcNotifyType notify; - PurpleBuddy *b; - int i; - - va_start(va, type); - memset(buf, 0, sizeof(buf)); - - switch (type) { - - case SILC_NOTIFY_TYPE_NONE: - break; - - case SILC_NOTIFY_TYPE_INVITE: - { - GHashTable *components; - va_arg(va, SilcChannelEntry); - name = va_arg(va, char *); - client_entry = va_arg(va, SilcClientEntry); - - components = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); - g_hash_table_insert(components, strdup("channel"), strdup(name)); - serv_got_chat_invite(gc, name, client_entry->nickname, NULL, components); - } - break; - - case SILC_NOTIFY_TYPE_JOIN: - client_entry = va_arg(va, SilcClientEntry); - channel = va_arg(va, SilcChannelEntry); - - /* If we joined channel, do nothing */ - if (client_entry == conn->local_entry) - break; - - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - channel->channel_name, sg->account); - if (!convo) - break; - - /* Join user to channel */ - g_snprintf(buf, sizeof(buf), "%s@%s", - client_entry->username, client_entry->hostname); - purple_conv_chat_add_user(PURPLE_CONV_CHAT(convo), - g_strdup(client_entry->nickname), buf, PURPLE_CBFLAGS_NONE, TRUE); - - break; - - case SILC_NOTIFY_TYPE_LEAVE: - client_entry = va_arg(va, SilcClientEntry); - channel = va_arg(va, SilcChannelEntry); - - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - channel->channel_name, sg->account); - if (!convo) - break; - - /* Remove user from channel */ - purple_conv_chat_remove_user(PURPLE_CONV_CHAT(convo), - client_entry->nickname, NULL); - - break; - - case SILC_NOTIFY_TYPE_SIGNOFF: - client_entry = va_arg(va, SilcClientEntry); - tmp = va_arg(va, char *); - - if (!client_entry->nickname) - break; - - /* Remove from all channels */ - silc_hash_table_list(client_entry->channels, &htl); - while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - chu->channel->channel_name, sg->account); - if (!convo) - continue; - purple_conv_chat_remove_user(PURPLE_CONV_CHAT(convo), - client_entry->nickname, - tmp); - } - silc_hash_table_list_reset(&htl); - - break; - - case SILC_NOTIFY_TYPE_TOPIC_SET: - { - char *esc, *tmp2; - idtype = va_arg(va, int); - entry = va_arg(va, void *); - tmp = va_arg(va, char *); - channel = va_arg(va, SilcChannelEntry); - - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - channel->channel_name, sg->account); - if (!convo) - break; - - if (!tmp) - break; - - esc = g_markup_escape_text(tmp, -1); - tmp2 = purple_markup_linkify(esc); - g_free(esc); - - if (idtype == SILC_ID_CLIENT) { - client_entry = (SilcClientEntry)entry; - g_snprintf(buf, sizeof(buf), - _("%s has changed the topic of %s to: %s"), - client_entry->nickname, channel->channel_name, tmp2); - purple_conv_chat_write(PURPLE_CONV_CHAT(convo), client_entry->nickname, - buf, PURPLE_MESSAGE_SYSTEM, time(NULL)); - purple_conv_chat_set_topic(PURPLE_CONV_CHAT(convo), - client_entry->nickname, tmp); - } else if (idtype == SILC_ID_SERVER) { - server_entry = (SilcServerEntry)entry; - g_snprintf(buf, sizeof(buf), - _("%s has changed the topic of %s to: %s"), - server_entry->server_name, channel->channel_name, tmp2); - purple_conv_chat_write(PURPLE_CONV_CHAT(convo), server_entry->server_name, - buf, PURPLE_MESSAGE_SYSTEM, time(NULL)); - purple_conv_chat_set_topic(PURPLE_CONV_CHAT(convo), - server_entry->server_name, tmp); - } else if (idtype == SILC_ID_CHANNEL) { - channel = (SilcChannelEntry)entry; - g_snprintf(buf, sizeof(buf), - _("%s has changed the topic of %s to: %s"), - channel->channel_name, channel->channel_name, tmp2); - purple_conv_chat_write(PURPLE_CONV_CHAT(convo), channel->channel_name, - buf, PURPLE_MESSAGE_SYSTEM, time(NULL)); - purple_conv_chat_set_topic(PURPLE_CONV_CHAT(convo), - channel->channel_name, tmp); - } else { - purple_conv_chat_set_topic(PURPLE_CONV_CHAT(convo), NULL, tmp); - } - - g_free(tmp2); - - break; - - } - case SILC_NOTIFY_TYPE_NICK_CHANGE: - client_entry = va_arg(va, SilcClientEntry); - client_entry2 = va_arg(va, SilcClientEntry); - - if (!strcmp(client_entry->nickname, client_entry2->nickname)) - break; - - /* Change nick on all channels */ - silc_hash_table_list(client_entry2->channels, &htl); - while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - chu->channel->channel_name, sg->account); - if (!convo) - continue; - if (purple_conv_chat_find_user(PURPLE_CONV_CHAT(convo), client_entry->nickname)) - purple_conv_chat_rename_user(PURPLE_CONV_CHAT(convo), - client_entry->nickname, - client_entry2->nickname); - } - silc_hash_table_list_reset(&htl); - - break; - - case SILC_NOTIFY_TYPE_CMODE_CHANGE: - idtype = va_arg(va, int); - entry = va_arg(va, void *); - mode = va_arg(va, SilcUInt32); - (void)va_arg(va, char *); - (void)va_arg(va, char *); - (void)va_arg(va, char *); - (void)va_arg(va, SilcPublicKey); - (void)va_arg(va, SilcBuffer); - channel = va_arg(va, SilcChannelEntry); - - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - channel->channel_name, sg->account); - if (!convo) - break; - - if (idtype == SILC_ID_CLIENT) - name = ((SilcClientEntry)entry)->nickname; - else if (idtype == SILC_ID_SERVER) - name = ((SilcServerEntry)entry)->server_name; - else - name = ((SilcChannelEntry)entry)->channel_name; - if (!name) - break; - - if (mode) { - silcpurple_get_chmode_string(mode, buf2, sizeof(buf2)); - g_snprintf(buf, sizeof(buf), - _("%s set channel %s modes to: %s"), name, - channel->channel_name, buf2); - } else { - g_snprintf(buf, sizeof(buf), - _("%s removed all channel %s modes"), name, - channel->channel_name); - } - purple_conv_chat_write(PURPLE_CONV_CHAT(convo), channel->channel_name, - buf, PURPLE_MESSAGE_SYSTEM, time(NULL)); - break; - - case SILC_NOTIFY_TYPE_CUMODE_CHANGE: - { - PurpleConvChatBuddyFlags flags = PURPLE_CBFLAGS_NONE; - idtype = va_arg(va, int); - entry = va_arg(va, void *); - mode = va_arg(va, SilcUInt32); - client_entry2 = va_arg(va, SilcClientEntry); - channel = va_arg(va, SilcChannelEntry); - - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - channel->channel_name, sg->account); - if (!convo) - break; - - if (idtype == SILC_ID_CLIENT) - name = ((SilcClientEntry)entry)->nickname; - else if (idtype == SILC_ID_SERVER) - name = ((SilcServerEntry)entry)->server_name; - else - name = ((SilcChannelEntry)entry)->channel_name; - if (!name) - break; - - if (mode) { - silcpurple_get_chumode_string(mode, buf2, sizeof(buf2)); - g_snprintf(buf, sizeof(buf), - _("%s set %s's modes to: %s"), name, - client_entry2->nickname, buf2); - if (mode & SILC_CHANNEL_UMODE_CHANFO) - flags |= PURPLE_CBFLAGS_FOUNDER; - if (mode & SILC_CHANNEL_UMODE_CHANOP) - flags |= PURPLE_CBFLAGS_OP; - } else { - g_snprintf(buf, sizeof(buf), - _("%s removed all %s's modes"), name, - client_entry2->nickname); - } - purple_conv_chat_write(PURPLE_CONV_CHAT(convo), channel->channel_name, - buf, PURPLE_MESSAGE_SYSTEM, time(NULL)); - purple_conv_chat_user_set_flags(PURPLE_CONV_CHAT(convo), client_entry2->nickname, flags); - break; - } - - case SILC_NOTIFY_TYPE_MOTD: - tmp = va_arg(va, char *); - silc_free(sg->motd); - sg->motd = silc_memdup(tmp, strlen(tmp)); - break; - - case SILC_NOTIFY_TYPE_KICKED: - client_entry = va_arg(va, SilcClientEntry); - tmp = va_arg(va, char *); - client_entry2 = va_arg(va, SilcClientEntry); - channel = va_arg(va, SilcChannelEntry); - - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - channel->channel_name, sg->account); - if (!convo) - break; - - if (client_entry == conn->local_entry) { - /* Remove us from channel */ - g_snprintf(buf, sizeof(buf), - _("You have been kicked off %s by %s (%s)"), - channel->channel_name, client_entry2->nickname, - tmp ? tmp : ""); - purple_conv_chat_write(PURPLE_CONV_CHAT(convo), client_entry->nickname, - buf, PURPLE_MESSAGE_SYSTEM, time(NULL)); - serv_got_chat_left(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo))); - } else { - /* Remove user from channel */ - g_snprintf(buf, sizeof(buf), _("Kicked by %s (%s)"), - client_entry2->nickname, tmp ? tmp : ""); - purple_conv_chat_remove_user(PURPLE_CONV_CHAT(convo), - client_entry->nickname, - buf); - } - - break; - - case SILC_NOTIFY_TYPE_KILLED: - client_entry = va_arg(va, SilcClientEntry); - tmp = va_arg(va, char *); - idtype = va_arg(va, int); - entry = va_arg(va, SilcClientEntry); - - if (!client_entry->nickname) - break; - - if (client_entry == conn->local_entry) { - if (idtype == SILC_ID_CLIENT) { - client_entry2 = (SilcClientEntry)entry; - g_snprintf(buf, sizeof(buf), - _("You have been killed by %s (%s)"), - client_entry2->nickname, tmp ? tmp : ""); - } else if (idtype == SILC_ID_SERVER) { - server_entry = (SilcServerEntry)entry; - g_snprintf(buf, sizeof(buf), - _("You have been killed by %s (%s)"), - server_entry->server_name, tmp ? tmp : ""); - } else if (idtype == SILC_ID_CHANNEL) { - channel = (SilcChannelEntry)entry; - g_snprintf(buf, sizeof(buf), - _("You have been killed by %s (%s)"), - channel->channel_name, tmp ? tmp : ""); - } - - /* Remove us from all channels */ - silc_hash_table_list(client_entry->channels, &htl); - while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - chu->channel->channel_name, sg->account); - if (!convo) - continue; - purple_conv_chat_write(PURPLE_CONV_CHAT(convo), client_entry->nickname, - buf, PURPLE_MESSAGE_SYSTEM, time(NULL)); - serv_got_chat_left(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo))); - } - silc_hash_table_list_reset(&htl); - - } else { - if (idtype == SILC_ID_CLIENT) { - client_entry2 = (SilcClientEntry)entry; - g_snprintf(buf, sizeof(buf), - _("Killed by %s (%s)"), - client_entry2->nickname, tmp ? tmp : ""); - } else if (idtype == SILC_ID_SERVER) { - server_entry = (SilcServerEntry)entry; - g_snprintf(buf, sizeof(buf), - _("Killed by %s (%s)"), - server_entry->server_name, tmp ? tmp : ""); - } else if (idtype == SILC_ID_CHANNEL) { - channel = (SilcChannelEntry)entry; - g_snprintf(buf, sizeof(buf), - _("Killed by %s (%s)"), - channel->channel_name, tmp ? tmp : ""); - } - - /* Remove user from all channels */ - silc_hash_table_list(client_entry->channels, &htl); - while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - chu->channel->channel_name, sg->account); - if (!convo) - continue; - purple_conv_chat_remove_user(PURPLE_CONV_CHAT(convo), - client_entry->nickname, tmp); - } - silc_hash_table_list_reset(&htl); - } - - break; - - case SILC_NOTIFY_TYPE_CHANNEL_CHANGE: - break; - - case SILC_NOTIFY_TYPE_SERVER_SIGNOFF: - { - int i; - SilcClientEntry *clients; - SilcUInt32 clients_count; - - (void)va_arg(va, void *); - clients = va_arg(va, SilcClientEntry *); - clients_count = va_arg(va, SilcUInt32); - - for (i = 0; i < clients_count; i++) { - if (!clients[i]->nickname) - break; - - /* Remove from all channels */ - silc_hash_table_list(clients[i]->channels, &htl); - while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { - convo = - purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - chu->channel->channel_name, sg->account); - if (!convo) - continue; - purple_conv_chat_remove_user(PURPLE_CONV_CHAT(convo), - clients[i]->nickname, - _("Server signoff")); - } - silc_hash_table_list_reset(&htl); - } - } - break; - - case SILC_NOTIFY_TYPE_ERROR: - { - SilcStatus error = va_arg(va, int); - purple_notify_error(gc, "Error Notify", - silc_get_status_message(error), - NULL); - } - break; - - case SILC_NOTIFY_TYPE_WATCH: - { - SilcPublicKey public_key; - unsigned char *pk; - SilcUInt32 pk_len; - char *fingerprint; - - client_entry = va_arg(va, SilcClientEntry); - (void)va_arg(va, char *); - mode = va_arg(va, SilcUInt32); - notify = va_arg(va, int); - public_key = va_arg(va, SilcPublicKey); - - b = NULL; - if (public_key) { - PurpleBlistNode *gnode, *cnode, *bnode; - const char *f; - - pk = silc_pkcs_public_key_encode(public_key, &pk_len); - if (!pk) - break; - fingerprint = silc_hash_fingerprint(NULL, pk, pk_len); - for (i = 0; i < strlen(fingerprint); i++) - if (fingerprint[i] == ' ') - fingerprint[i] = '_'; - g_snprintf(buf, sizeof(buf) - 1, - "%s" G_DIR_SEPARATOR_S "clientkeys" - G_DIR_SEPARATOR_S "clientkey_%s.pub", - silcpurple_silcdir(), fingerprint); - silc_free(fingerprint); - silc_free(pk); - - /* Find buddy by associated public key */ - for (gnode = purple_get_blist()->root; gnode; - gnode = gnode->next) { - if (!PURPLE_BLIST_NODE_IS_GROUP(gnode)) - continue; - for (cnode = gnode->child; cnode; cnode = cnode->next) { - if( !PURPLE_BLIST_NODE_IS_CONTACT(cnode)) - continue; - for (bnode = cnode->child; bnode; - bnode = bnode->next) { - if (!PURPLE_BLIST_NODE_IS_BUDDY(bnode)) - continue; - b = (PurpleBuddy *)bnode; - if (b->account != gc->account) - continue; - f = purple_blist_node_get_string(bnode, "public-key"); - if (f && !strcmp(f, buf)) - goto cont; - b = NULL; - } - } - } - } - cont: - if (!b) { - /* Find buddy by nickname */ - b = purple_find_buddy(sg->account, client_entry->nickname); - if (!b) { - purple_debug_warning("silc", "WATCH for %s, unknown buddy\n", - client_entry->nickname); - break; - } - } - - silc_free(b->proto_data); - b->proto_data = silc_memdup(client_entry->id, - sizeof(*client_entry->id)); - if (notify == SILC_NOTIFY_TYPE_NICK_CHANGE) { - break; - } else if (notify == SILC_NOTIFY_TYPE_UMODE_CHANGE) { - /* See if client was away and is now present */ - if (!(mode & (SILC_UMODE_GONE | SILC_UMODE_INDISPOSED | - SILC_UMODE_BUSY | SILC_UMODE_PAGE | - SILC_UMODE_DETACHED)) && - (client_entry->mode & SILC_UMODE_GONE || - client_entry->mode & SILC_UMODE_INDISPOSED || - client_entry->mode & SILC_UMODE_BUSY || - client_entry->mode & SILC_UMODE_PAGE || - client_entry->mode & SILC_UMODE_DETACHED)) { - client_entry->mode = mode; - purple_prpl_got_user_status(purple_buddy_get_account(b), purple_buddy_get_name(b), SILCPURPLE_STATUS_ID_AVAILABLE, NULL); - } - else if ((mode & SILC_UMODE_GONE) || - (mode & SILC_UMODE_INDISPOSED) || - (mode & SILC_UMODE_BUSY) || - (mode & SILC_UMODE_PAGE) || - (mode & SILC_UMODE_DETACHED)) { - client_entry->mode = mode; - purple_prpl_got_user_status(purple_buddy_get_account(b), purple_buddy_get_name(b), SILCPURPLE_STATUS_ID_OFFLINE, NULL); - } - } else if (notify == SILC_NOTIFY_TYPE_SIGNOFF || - notify == SILC_NOTIFY_TYPE_SERVER_SIGNOFF || - notify == SILC_NOTIFY_TYPE_KILLED) { - client_entry->mode = mode; - purple_prpl_got_user_status(purple_buddy_get_account(b), purple_buddy_get_name(b), SILCPURPLE_STATUS_ID_OFFLINE, NULL); - } else if (notify == SILC_NOTIFY_TYPE_NONE) { - client_entry->mode = mode; - purple_prpl_got_user_status(purple_buddy_get_account(b), purple_buddy_get_name(b), SILCPURPLE_STATUS_ID_AVAILABLE, NULL); - } - } - break; - - default: - purple_debug_info("silc", "Unhandled notification: %d\n", type); - break; - } - - va_end(va); -} - - -/* Command handler. This function is called always in the command function. - If error occurs it will be called as well. `conn' is the associated - client connection. `cmd_context' is the command context that was - originally sent to the command. `success' is FALSE if error occurred - during command. `command' is the command being processed. It must be - noted that this is not reply from server. This is merely called just - after application has called the command. Just to tell application - that the command really was processed. */ - -static void -silc_command(SilcClient client, SilcClientConnection conn, - SilcClientCommandContext cmd_context, bool success, - SilcCommand command, SilcStatus status) -{ - PurpleConnection *gc = client->application; - SilcPurple sg = gc->proto_data; - - switch (command) { - - case SILC_COMMAND_CMODE: - if (cmd_context->argc == 3 && - !strcmp((char *)cmd_context->argv[2], "+C")) - sg->chpk = TRUE; - else - sg->chpk = FALSE; - break; - - default: - break; - } -} - -#if 0 -static void -silcpurple_whois_more(SilcClientEntry client_entry, gint id) -{ - SilcAttributePayload attr; - SilcAttribute attribute; - char *buf; - GString *s; - SilcVCardStruct vcard; - int i; - - if (id != 0) - return; - - memset(&vcard, 0, sizeof(vcard)); - - s = g_string_new(""); - - silc_dlist_start(client_entry->attrs); - while ((attr = silc_dlist_get(client_entry->attrs)) != SILC_LIST_END) { - attribute = silc_attribute_get_attribute(attr); - switch (attribute) { - - case SILC_ATTRIBUTE_USER_INFO: - if (!silc_attribute_get_object(attr, (void *)&vcard, - sizeof(vcard))) - continue; - g_string_append_printf(s, "%s:\n\n", _("Personal Information")); - if (vcard.full_name) - g_string_append_printf(s, "%s:\t\t%s\n", - _("Full Name"), - vcard.full_name); - if (vcard.first_name) - g_string_append_printf(s, "%s:\t%s\n", - _("First Name"), - vcard.first_name); - if (vcard.middle_names) - g_string_append_printf(s, "%s:\t%s\n", - _("Middle Name"), - vcard.middle_names); - if (vcard.family_name) - g_string_append_printf(s, "%s:\t%s\n", - _("Family Name"), - vcard.family_name); - if (vcard.nickname) - g_string_append_printf(s, "%s:\t\t%s\n", - _("Nickname"), - vcard.nickname); - if (vcard.bday) - g_string_append_printf(s, "%s:\t\t%s\n", - _("Birth Day"), - vcard.bday); - if (vcard.title) - g_string_append_printf(s, "%s:\t\t%s\n", - _("Job Title"), - vcard.title); - if (vcard.role) - g_string_append_printf(s, "%s:\t\t%s\n", - _("Job Role"), - vcard.role); - if (vcard.org_name) - g_string_append_printf(s, "%s:\t%s\n", - _("Organization"), - vcard.org_name); - if (vcard.org_unit) - g_string_append_printf(s, "%s:\t\t%s\n", - _("Unit"), - vcard.org_unit); - if (vcard.url) - g_string_append_printf(s, "%s:\t%s\n", - _("Homepage"), - vcard.url); - if (vcard.label) - g_string_append_printf(s, "%s:\t%s\n", - _("Address"), - vcard.label); - for (i = 0; i < vcard.num_tels; i++) { - if (vcard.tels[i].telnum) - g_string_append_printf(s, "%s:\t\t\t%s\n", - _("Phone"), - vcard.tels[i].telnum); - } - for (i = 0; i < vcard.num_emails; i++) { - if (vcard.emails[i].address) - g_string_append_printf(s, "%s:\t\t%s\n", - _("Email"), - vcard.emails[i].address); - } - if (vcard.note) - g_string_append_printf(s, "\n%s:\t\t%s\n", - _("Note"), - vcard.note); - break; - } - } - - buf = g_string_free(s, FALSE); - purple_notify_info(NULL, _("User Information"), _("User Information"), - buf); - g_free(buf); -} -#endif - -/* Command reply handler. This function is called always in the command reply - function. If error occurs it will be called as well. Normal scenario - is that it will be called after the received command data has been parsed - and processed. The function is used to pass the received command data to - the application. - - `conn' is the associated client connection. `cmd_payload' is the command - payload data received from server and it can be ignored. It is provided - if the application would like to re-parse the received command data, - however, it must be noted that the data is parsed already by the library - thus the payload can be ignored. `success' is FALSE if error occurred. - In this case arguments are not sent to the application. The `status' is - the command reply status server returned. The `command' is the command - reply being processed. The function has variable argument list and each - command defines the number and type of arguments it passes to the - application (on error they are not sent). */ - -static void -silc_command_reply(SilcClient client, SilcClientConnection conn, - SilcCommandPayload cmd_payload, bool success, - SilcCommand command, SilcStatus status, ...) -{ - PurpleConnection *gc = client->application; - SilcPurple sg = gc->proto_data; - PurpleConversation *convo; - va_list vp; - - va_start(vp, status); - - switch (command) { - case SILC_COMMAND_JOIN: - { - SilcChannelEntry channel_entry; - - if (!success) { - purple_notify_error(gc, _("Join Chat"), _("Cannot join channel"), - silc_get_status_message(status)); - return; - } - - (void)va_arg(vp, char *); - channel_entry = va_arg(vp, SilcChannelEntry); - - /* Resolve users on channel */ - silc_client_get_clients_by_channel(client, conn, channel_entry, - silcpurple_chat_join_done, - channel_entry); - } - break; - - case SILC_COMMAND_LEAVE: - break; - - case SILC_COMMAND_USERS: - break; - - case SILC_COMMAND_WHOIS: - { - SilcUInt32 idle, mode; - SilcBuffer channels, user_modes; - SilcClientEntry client_entry; - char tmp[1024], *tmp2; - char *moodstr, *statusstr, *contactstr, *langstr, *devicestr, *tzstr, *geostr; - PurpleNotifyUserInfo *user_info; - - if (!success) { - purple_notify_error(gc, _("User Information"), - _("Cannot get user information"), - silc_get_status_message(status)); - break; - } - - client_entry = va_arg(vp, SilcClientEntry); - if (!client_entry->nickname) - break; - (void)va_arg(vp, char *); - (void)va_arg(vp, char *); - (void)va_arg(vp, char *); - channels = va_arg(vp, SilcBuffer); - mode = va_arg(vp, SilcUInt32); - idle = va_arg(vp, SilcUInt32); - (void)va_arg(vp, unsigned char *); - user_modes = va_arg(vp, SilcBuffer); - - user_info = purple_notify_user_info_new(); - tmp2 = g_markup_escape_text(client_entry->nickname, -1); - purple_notify_user_info_add_pair(user_info, _("Nickname"), tmp2); - g_free(tmp2); - if (client_entry->realname) { - tmp2 = g_markup_escape_text(client_entry->realname, -1); - purple_notify_user_info_add_pair(user_info, _("Real Name"), tmp2); - g_free(tmp2); - } - if (client_entry->username) { - tmp2 = g_markup_escape_text(client_entry->username, -1); - if (client_entry->hostname) { - gchar *tmp3; - tmp3 = g_strdup_printf("%s@%s", tmp2, client_entry->hostname); - purple_notify_user_info_add_pair(user_info, _("Username"), tmp3); - g_free(tmp3); - } else - purple_notify_user_info_add_pair(user_info, _("Username"), tmp2); - g_free(tmp2); - } - - if (client_entry->mode) { - memset(tmp, 0, sizeof(tmp)); - silcpurple_get_umode_string(client_entry->mode, - tmp, sizeof(tmp) - strlen(tmp)); - purple_notify_user_info_add_pair(user_info, _("User Modes"), tmp); - } - - silcpurple_parse_attrs(client_entry->attrs, &moodstr, &statusstr, &contactstr, &langstr, &devicestr, &tzstr, &geostr); - if (moodstr) { - purple_notify_user_info_add_pair(user_info, _("Mood"), moodstr); - g_free(moodstr); - } - - if (statusstr) { - tmp2 = g_markup_escape_text(statusstr, -1); - purple_notify_user_info_add_pair(user_info, _("Status Text"), tmp2); - g_free(statusstr); - g_free(tmp2); - } - - if (contactstr) { - purple_notify_user_info_add_pair(user_info, _("Preferred Contact"), contactstr); - g_free(contactstr); - } - - if (langstr) { - purple_notify_user_info_add_pair(user_info, _("Preferred Language"), langstr); - g_free(langstr); - } - - if (devicestr) { - purple_notify_user_info_add_pair(user_info, _("Device"), devicestr); - g_free(devicestr); - } - - if (tzstr) { - purple_notify_user_info_add_pair(user_info, _("Timezone"), tzstr); - g_free(tzstr); - } - - if (geostr) { - purple_notify_user_info_add_pair(user_info, _("Geolocation"), geostr); - g_free(geostr); - } - - if (client_entry->server) - purple_notify_user_info_add_pair(user_info, _("Server"), client_entry->server); - - if (channels && user_modes) { - SilcUInt32 *umodes; - SilcDList list = - silc_channel_payload_parse_list(channels->data, - channels->len); - if (list && silc_get_mode_list(user_modes, - silc_dlist_count(list), - &umodes)) { - SilcChannelPayload entry; - int i = 0; - - memset(tmp, 0, sizeof(tmp)); - silc_dlist_start(list); - while ((entry = silc_dlist_get(list)) - != SILC_LIST_END) { - SilcUInt32 name_len; - char *m = silc_client_chumode_char(umodes[i++]); - char *name = (char *)silc_channel_get_name(entry, &name_len); - if (m) - silc_strncat(tmp, sizeof(tmp) - 1, m, strlen(m)); - silc_strncat(tmp, sizeof(tmp) - 1, name, name_len); - silc_strncat(tmp, sizeof(tmp) - 1, " ", 1); - silc_free(m); - - } - tmp2 = g_markup_escape_text(tmp, -1); - purple_notify_user_info_add_pair(user_info, _("Currently on"), tmp2); - g_free(tmp2); - silc_free(umodes); - } - } - - if (client_entry->public_key) { - char *fingerprint, *babbleprint; - unsigned char *pk; - SilcUInt32 pk_len; - pk = silc_pkcs_public_key_encode(client_entry->public_key, &pk_len); - fingerprint = silc_hash_fingerprint(NULL, pk, pk_len); - babbleprint = silc_hash_babbleprint(NULL, pk, pk_len); - purple_notify_user_info_add_pair(user_info, _("Public Key Fingerprint"), fingerprint); - purple_notify_user_info_add_pair(user_info, _("Public Key Babbleprint"), babbleprint); - silc_free(fingerprint); - silc_free(babbleprint); - silc_free(pk); - } - -#if 0 /* XXX for now, let's not show attrs here */ - if (client_entry->attrs) - purple_request_action(gc, _("User Information"), - _("User Information"), - buf, 1, client_entry, 2, - _("OK"), G_CALLBACK(silcpurple_whois_more), - _("_More..."), G_CALLBACK(silcpurple_whois_more), gc->account, NULL, NULL); - else -#endif - purple_notify_userinfo(gc, client_entry->nickname, user_info, NULL, NULL); - purple_notify_user_info_destroy(user_info); - } - break; - - case SILC_COMMAND_WHOWAS: - { - SilcClientEntry client_entry; - char *nickname, *realname, *username, *tmp; - PurpleNotifyUserInfo *user_info; - - if (!success) { - purple_notify_error(gc, _("User Information"), - _("Cannot get user information"), - silc_get_status_message(status)); - break; - } - - client_entry = va_arg(vp, SilcClientEntry); - nickname = va_arg(vp, char *); - username = va_arg(vp, char *); - realname = va_arg(vp, char *); - if (!nickname) - break; - - user_info = purple_notify_user_info_new(); - tmp = g_markup_escape_text(nickname, -1); - purple_notify_user_info_add_pair(user_info, _("Nickname"), tmp); - g_free(tmp); - if (realname) { - tmp = g_markup_escape_text(realname, -1); - purple_notify_user_info_add_pair(user_info, _("Real Name"), tmp); - g_free(tmp); - } - if (username) { - tmp = g_markup_escape_text(username, -1); - if (client_entry && client_entry->hostname) { - gchar *tmp3; - tmp3 = g_strdup_printf("%s@%s", tmp, client_entry->hostname); - purple_notify_user_info_add_pair(user_info, _("Username"), tmp3); - g_free(tmp3); - } else - purple_notify_user_info_add_pair(user_info, _("Username"), tmp); - g_free(tmp); - } - if (client_entry && client_entry->server) - purple_notify_user_info_add_pair(user_info, _("Server"), client_entry->server); - - - if (client_entry && client_entry->public_key) { - char *fingerprint, *babbleprint; - unsigned char *pk; - SilcUInt32 pk_len; - pk = silc_pkcs_public_key_encode(client_entry->public_key, &pk_len); - fingerprint = silc_hash_fingerprint(NULL, pk, pk_len); - babbleprint = silc_hash_babbleprint(NULL, pk, pk_len); - purple_notify_user_info_add_pair(user_info, _("Public Key Fingerprint"), fingerprint); - purple_notify_user_info_add_pair(user_info, _("Public Key Babbleprint"), babbleprint); - silc_free(fingerprint); - silc_free(babbleprint); - silc_free(pk); - } - - purple_notify_userinfo(gc, nickname, user_info, NULL, NULL); - purple_notify_user_info_destroy(user_info); - } - break; - - case SILC_COMMAND_DETACH: - if (!success) { - purple_notify_error(gc, _("Detach From Server"), _("Cannot detach"), - silc_get_status_message(status)); - return; - } - break; - - case SILC_COMMAND_TOPIC: - { - SilcChannelEntry channel; - - if (!success) { - purple_notify_error(gc, _("Topic"), _("Cannot set topic"), - silc_get_status_message(status)); - return; - } - - channel = va_arg(vp, SilcChannelEntry); - - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - channel->channel_name, sg->account); - if (!convo) { - purple_debug_error("silc", "Got a topic for %s, which doesn't exist\n", - channel->channel_name); - break; - } - - /* Set topic */ - if (channel->topic) - purple_conv_chat_set_topic(PURPLE_CONV_CHAT(convo), NULL, channel->topic); - } - break; - - case SILC_COMMAND_NICK: - { - /* I don't think we should need to do this because the server should - * be sending a SILC_NOTIFY_TYPE_NICK_CHANGE when we change our own - * nick, but it isn't, so we deal with it here instead. Stu. */ - SilcClientEntry local_entry; - SilcHashTableList htl; - SilcChannelUser chu; - const char *oldnick; - - if (!success) { - purple_notify_error(gc, _("Nick"), _("Failed to change nickname"), - silc_get_status_message(status)); - return; - } - - local_entry = va_arg(vp, SilcClientEntry); - - /* Change nick on all channels */ - silc_hash_table_list(local_entry->channels, &htl); - while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - chu->channel->channel_name, sg->account); - if (!convo) - continue; - oldnick = purple_conv_chat_get_nick(PURPLE_CONV_CHAT(convo)); - if (strcmp(oldnick, purple_normalize(purple_conversation_get_account(convo), local_entry->nickname))) { - purple_conv_chat_rename_user(PURPLE_CONV_CHAT(convo), - oldnick, local_entry->nickname); - purple_conv_chat_set_nick(PURPLE_CONV_CHAT(convo), local_entry->nickname); - } - } - silc_hash_table_list_reset(&htl); - - purple_connection_set_display_name(gc, local_entry->nickname); - } - break; - - case SILC_COMMAND_LIST: - { - char *topic, *name; - int usercount; - PurpleRoomlistRoom *room; - - if (sg->roomlist_cancelled) - break; - - if (!success) { - purple_notify_error(gc, _("Error"), _("Error retrieving room list"), - silc_get_status_message(status)); - purple_roomlist_set_in_progress(sg->roomlist, FALSE); - purple_roomlist_unref(sg->roomlist); - sg->roomlist = NULL; - return; - } - - (void)va_arg(vp, SilcChannelEntry); - name = va_arg(vp, char *); - if (!name) { - purple_notify_error(gc, _("Roomlist"), _("Cannot get room list"), - silc_get_status_message(status)); - purple_roomlist_set_in_progress(sg->roomlist, FALSE); - purple_roomlist_unref(sg->roomlist); - sg->roomlist = NULL; - return; - } - topic = va_arg(vp, char *); - usercount = va_arg(vp, int); - - room = purple_roomlist_room_new(PURPLE_ROOMLIST_ROOMTYPE_ROOM, name, NULL); - purple_roomlist_room_add_field(sg->roomlist, room, name); - purple_roomlist_room_add_field(sg->roomlist, room, - SILC_32_TO_PTR(usercount)); - purple_roomlist_room_add_field(sg->roomlist, room, - topic ? topic : ""); - purple_roomlist_room_add(sg->roomlist, room); - - if (status == SILC_STATUS_LIST_END || - status == SILC_STATUS_OK) { - purple_roomlist_set_in_progress(sg->roomlist, FALSE); - purple_roomlist_unref(sg->roomlist); - sg->roomlist = NULL; - } - } - break; - - case SILC_COMMAND_GETKEY: - { - SilcPublicKey public_key; - - if (!success) { - purple_notify_error(gc, _("Get Public Key"), - _("Cannot fetch the public key"), - silc_get_status_message(status)); - return; - } - - (void)va_arg(vp, SilcUInt32); - (void)va_arg(vp, void *); - public_key = va_arg(vp, SilcPublicKey); - - if (!public_key) - purple_notify_error(gc, _("Get Public Key"), - _("Cannot fetch the public key"), - _("No public key was received")); - } - break; - - case SILC_COMMAND_INFO: - { - - char *server_name; - char *server_info; - char tmp[256]; - - if (!success) { - purple_notify_error(gc, _("Server Information"), - _("Cannot get server information"), - silc_get_status_message(status)); - return; - } - - (void)va_arg(vp, SilcServerEntry); - server_name = va_arg(vp, char *); - server_info = va_arg(vp, char *); - - if (server_name && server_info) { - g_snprintf(tmp, sizeof(tmp), "Server: %s\n%s", - server_name, server_info); - purple_notify_info(gc, NULL, _("Server Information"), tmp); - } - } - break; - - case SILC_COMMAND_STATS: - { - SilcUInt32 starttime, uptime, my_clients, my_channels, my_server_ops, - my_router_ops, cell_clients, cell_channels, cell_servers, - clients, channels, servers, routers, server_ops, router_ops; - SilcUInt32 buffer_length; - SilcBufferStruct buf; - - unsigned char *server_stats; - char *msg; - - if (!success) { - purple_notify_error(gc, _("Server Statistics"), - _("Cannot get server statistics"), - silc_get_status_message(status)); - return; - } - - server_stats = va_arg(vp, unsigned char *); - buffer_length = va_arg(vp, SilcUInt32); - if (!server_stats || !buffer_length) { - purple_notify_error(gc, _("Server Statistics"), - _("No server statistics available"), NULL); - break; - } - silc_buffer_set(&buf, server_stats, buffer_length); - silc_buffer_unformat(&buf, - SILC_STR_UI_INT(&starttime), - SILC_STR_UI_INT(&uptime), - SILC_STR_UI_INT(&my_clients), - SILC_STR_UI_INT(&my_channels), - SILC_STR_UI_INT(&my_server_ops), - SILC_STR_UI_INT(&my_router_ops), - SILC_STR_UI_INT(&cell_clients), - SILC_STR_UI_INT(&cell_channels), - SILC_STR_UI_INT(&cell_servers), - SILC_STR_UI_INT(&clients), - SILC_STR_UI_INT(&channels), - SILC_STR_UI_INT(&servers), - SILC_STR_UI_INT(&routers), - SILC_STR_UI_INT(&server_ops), - SILC_STR_UI_INT(&router_ops), - SILC_STR_END); - - msg = g_strdup_printf(_("Local server start time: %s\n" - "Local server uptime: %s\n" - "Local server clients: %d\n" - "Local server channels: %d\n" - "Local server operators: %d\n" - "Local router operators: %d\n" - "Local cell clients: %d\n" - "Local cell channels: %d\n" - "Local cell servers: %d\n" - "Total clients: %d\n" - "Total channels: %d\n" - "Total servers: %d\n" - "Total routers: %d\n" - "Total server operators: %d\n" - "Total router operators: %d\n"), - silc_get_time(starttime), - purple_str_seconds_to_string((int)uptime), - (int)my_clients, (int)my_channels, (int)my_server_ops, (int)my_router_ops, - (int)cell_clients, (int)cell_channels, (int)cell_servers, - (int)clients, (int)channels, (int)servers, (int)routers, - (int)server_ops, (int)router_ops); - - purple_notify_info(gc, NULL, - _("Network Statistics"), msg); - g_free(msg); - } - break; - - case SILC_COMMAND_PING: - { - if (!success) { - purple_notify_error(gc, _("Ping"), _("Ping failed"), - silc_get_status_message(status)); - return; - } - - purple_notify_info(gc, _("Ping"), _("Ping reply received from server"), - NULL); - } - break; - - case SILC_COMMAND_KILL: - if (!success) { - purple_notify_error(gc, _("Kill User"), - _("Could not kill user"), - silc_get_status_message(status)); - return; - } - break; - - case SILC_COMMAND_CMODE: - { - SilcChannelEntry channel_entry; - SilcBuffer channel_pubkeys; - - if (!success) - return; - - channel_entry = va_arg(vp, SilcChannelEntry); - (void)va_arg(vp, SilcUInt32); - (void)va_arg(vp, SilcPublicKey); - channel_pubkeys = va_arg(vp, SilcBuffer); - - if (sg->chpk) - silcpurple_chat_chauth_show(sg, channel_entry, channel_pubkeys); - } - break; - - default: - if (success) - purple_debug_info("silc", "Unhandled command: %d (succeeded)\n", command); - else - purple_debug_info("silc", "Unhandled command: %d (failed: %s)\n", command, - silc_get_status_message(status)); - break; - } - - va_end(vp); -} - - -/* Called to indicate that connection was either successfully established - or connecting failed. This is also the first time application receives - the SilcClientConnection object which it should save somewhere. - If the `success' is FALSE the application must always call the function - silc_client_close_connection. */ - -static void -silc_connected(SilcClient client, SilcClientConnection conn, - SilcClientConnectionStatus status) -{ - PurpleConnection *gc = client->application; - SilcPurple sg; - - if (gc == NULL) { - silc_client_close_connection(client, conn); - return; - } - sg = gc->proto_data; - - switch (status) { - case SILC_CLIENT_CONN_SUCCESS: - case SILC_CLIENT_CONN_SUCCESS_RESUME: - purple_connection_set_state(gc, PURPLE_CONNECTED); - - /* Send the server our buddy list */ - silcpurple_send_buddylist(gc); - - g_unlink(silcpurple_session_file(purple_account_get_username(sg->account))); - - /* Send any UMODEs configured for account */ - if (purple_account_get_bool(sg->account, "block-ims", FALSE)) { - silc_client_command_call(sg->client, sg->conn, NULL, - "UMODE", "+P", NULL); - } - - return; - break; - case SILC_CLIENT_CONN_ERROR: - purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, - _("Error during connecting to SILC Server")); - g_unlink(silcpurple_session_file(purple_account_get_username(sg->account))); - break; - - case SILC_CLIENT_CONN_ERROR_KE: - purple_connection_error(gc, PURPLE_CONNECTION_ERROR_ENCRYPTION_ERROR, - _("Key Exchange failed")); - break; - - case SILC_CLIENT_CONN_ERROR_AUTH: - purple_connection_error(gc, - PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, - _("Authentication failed")); - break; - - case SILC_CLIENT_CONN_ERROR_RESUME: - purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, - _("Resuming detached session failed. " - "Press Reconnect to create new connection.")); - g_unlink(silcpurple_session_file(purple_account_get_username(sg->account))); - break; - - case SILC_CLIENT_CONN_ERROR_TIMEOUT: - purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, - _("Connection timed out")); - break; - } - - /* Error */ - sg->conn = NULL; - silc_client_close_connection(client, conn); -} - - -/* Called to indicate that connection was disconnected to the server. - The `status' may tell the reason of the disconnection, and if the - `message' is non-NULL it may include the disconnection message - received from server. */ - -static void -silc_disconnected(SilcClient client, SilcClientConnection conn, - SilcStatus status, const char *message) -{ - PurpleConnection *gc = client->application; - SilcPurple sg = gc->proto_data; - - if (sg->resuming && !sg->detaching) - g_unlink(silcpurple_session_file(purple_account_get_username(sg->account))); - - sg->conn = NULL; - - /* Close the connection */ - if (!sg->detaching) - purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, - _("Disconnected by server")); - else - /* TODO: Does this work correctly? Maybe we need to set wants_to_die? */ - purple_account_disconnect(purple_connection_get_account(gc)); -} - - -typedef struct { - SilcGetAuthMeth completion; - void *context; -} *SilcPurpleGetAuthMethod; - -/* Callback called when we've received the authentication method information - from the server after we've requested it. */ - -static void silc_get_auth_method_callback(SilcClient client, - SilcClientConnection conn, - SilcAuthMethod auth_meth, - void *context) -{ - SilcPurpleGetAuthMethod internal = context; - - switch (auth_meth) { - case SILC_AUTH_NONE: - /* No authentication required. */ - (*internal->completion)(TRUE, auth_meth, NULL, 0, internal->context); - break; - - case SILC_AUTH_PASSWORD: - /* By returning NULL here the library will ask the passphrase from us - by calling the silc_ask_passphrase. */ - (*internal->completion)(TRUE, auth_meth, NULL, 0, internal->context); - break; - - case SILC_AUTH_PUBLIC_KEY: - /* Do not get the authentication data now, the library will generate - it using our default key, if we do not provide it here. */ - (*internal->completion)(TRUE, auth_meth, NULL, 0, internal->context); - break; - } - - silc_free(internal); -} - -/* Find authentication method and authentication data by hostname and - port. The hostname may be IP address as well. When the authentication - method has been resolved the `completion' callback with the found - authentication method and authentication data is called. The `conn' - may be NULL. */ - -static void -silc_get_auth_method(SilcClient client, SilcClientConnection conn, - char *hostname, SilcUInt16 port, - SilcGetAuthMeth completion, void *context) -{ - PurpleConnection *gc = client->application; - SilcPurple sg = gc->proto_data; - SilcPurpleGetAuthMethod internal; - const char *password; - - /* Progress */ - if (sg->resuming) - purple_connection_update_progress(gc, _("Resuming session"), 4, 5); - else - purple_connection_update_progress(gc, _("Authenticating connection"), 4, 5); - - /* Check configuration if we have this connection configured. If we - have then return that data immediately, as it's faster way. */ - if (purple_account_get_bool(sg->account, "pubkey-auth", FALSE)) { - completion(TRUE, SILC_AUTH_PUBLIC_KEY, NULL, 0, context); - return; - } - password = purple_connection_get_password(gc); - if (password && *password) { - completion(TRUE, SILC_AUTH_PASSWORD, (unsigned char *)password, strlen(password), context); - return; - } - - /* Resolve the authentication method from server, as we may not know it. */ - internal = silc_calloc(1, sizeof(*internal)); - if (!internal) - return; - internal->completion = completion; - internal->context = context; - silc_client_request_authentication_method(client, conn, - silc_get_auth_method_callback, - internal); -} - - -/* Verifies received public key. The `conn_type' indicates which entity - (server, client etc.) has sent the public key. If user decides to trust - the application may save the key as trusted public key for later - use. The `completion' must be called after the public key has been - verified. */ - -static void -silc_verify_public_key(SilcClient client, SilcClientConnection conn, - SilcSocketType conn_type, unsigned char *pk, - SilcUInt32 pk_len, SilcSKEPKType pk_type, - SilcVerifyPublicKey completion, void *context) -{ - PurpleConnection *gc = client->application; - SilcPurple sg = gc->proto_data; - - if (!sg->conn && (conn_type == SILC_SOCKET_TYPE_SERVER || - conn_type == SILC_SOCKET_TYPE_ROUTER)) { - /* Progress */ - if (sg->resuming) - purple_connection_update_progress(gc, _("Resuming session"), 3, 5); - else - purple_connection_update_progress(gc, _("Verifying server public key"), - 3, 5); - } - - /* Verify public key */ - silcpurple_verify_public_key(client, conn, NULL, conn_type, pk, - pk_len, pk_type, completion, context); -} - -typedef struct { - SilcAskPassphrase completion; - void *context; -} *SilcPurpleAskPassphrase; - -static void -silc_ask_passphrase_cb(SilcPurpleAskPassphrase internal, const char *passphrase) -{ - if (!passphrase || !(*passphrase)) - internal->completion(NULL, 0, internal->context); - else - internal->completion((unsigned char *)passphrase, - strlen(passphrase), internal->context); - silc_free(internal); -} - -/* Ask (interact, that is) a passphrase from user. The passphrase is - returned to the library by calling the `completion' callback with - the `context'. The returned passphrase SHOULD be in UTF-8 encoded, - if not then the library will attempt to encode. */ - -static void -silc_ask_passphrase(SilcClient client, SilcClientConnection conn, - SilcAskPassphrase completion, void *context) -{ - PurpleConnection *gc = client->application; - SilcPurpleAskPassphrase internal = silc_calloc(1, sizeof(*internal)); - - if (!internal) - return; - internal->completion = completion; - internal->context = context; - purple_request_input(gc, _("Passphrase"), NULL, - _("Passphrase required"), NULL, FALSE, TRUE, NULL, - _("OK"), G_CALLBACK(silc_ask_passphrase_cb), - _("Cancel"), G_CALLBACK(silc_ask_passphrase_cb), - purple_connection_get_account(gc), NULL, NULL, internal); -} - - -/* Notifies application that failure packet was received. This is called - if there is some protocol active in the client. The `protocol' is the - protocol context. The `failure' is opaque pointer to the failure - indication. Note, that the `failure' is protocol dependant and - application must explicitly cast it to correct type. Usually `failure' - is 32 bit failure type (see protocol specs for all protocol failure - types). */ - -static void -silc_failure(SilcClient client, SilcClientConnection conn, - SilcProtocol protocol, void *failure) -{ - PurpleConnection *gc = client->application; - char buf[128]; - - memset(buf, 0, sizeof(buf)); - - if (protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE) { - SilcSKEStatus status = (SilcSKEStatus)SILC_PTR_TO_32(failure); - - if (status == SILC_SKE_STATUS_BAD_VERSION) - g_snprintf(buf, sizeof(buf), - _("Failure: Version mismatch, upgrade your client")); - if (status == SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY) - g_snprintf(buf, sizeof(buf), - _("Failure: Remote does not trust/support your public key")); - if (status == SILC_SKE_STATUS_UNKNOWN_GROUP) - g_snprintf(buf, sizeof(buf), - _("Failure: Remote does not support proposed KE group")); - if (status == SILC_SKE_STATUS_UNKNOWN_CIPHER) - g_snprintf(buf, sizeof(buf), - _("Failure: Remote does not support proposed cipher")); - if (status == SILC_SKE_STATUS_UNKNOWN_PKCS) - g_snprintf(buf, sizeof(buf), - _("Failure: Remote does not support proposed PKCS")); - if (status == SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION) - g_snprintf(buf, sizeof(buf), - _("Failure: Remote does not support proposed hash function")); - if (status == SILC_SKE_STATUS_UNKNOWN_HMAC) - g_snprintf(buf, sizeof(buf), - _("Failure: Remote does not support proposed HMAC")); - if (status == SILC_SKE_STATUS_INCORRECT_SIGNATURE) - g_snprintf(buf, sizeof(buf), _("Failure: Incorrect signature")); - if (status == SILC_SKE_STATUS_INVALID_COOKIE) - g_snprintf(buf, sizeof(buf), _("Failure: Invalid cookie")); - - /* Show the error on the progress bar. A more generic error message - is going to be showed to user after this in the silc_connected. */ - purple_connection_update_progress(gc, buf, 2, 5); - } - - if (protocol->protocol->type == SILC_PROTOCOL_CLIENT_CONNECTION_AUTH) { - SilcUInt32 err = SILC_PTR_TO_32(failure); - - if (err == SILC_AUTH_FAILED) - g_snprintf(buf, sizeof(buf), _("Failure: Authentication failed")); - - /* Show the error on the progress bar. A more generic error message - is going to be showed to user after this in the silc_connected. */ - purple_connection_update_progress(gc, buf, 4, 5); - } -} - -/* Asks whether the user would like to perform the key agreement protocol. - This is called after we have received an key agreement packet or an - reply to our key agreement packet. This returns TRUE if the user wants - the library to perform the key agreement protocol and FALSE if it is not - desired (application may start it later by calling the function - silc_client_perform_key_agreement). If TRUE is returned also the - `completion' and `context' arguments must be set by the application. */ - -static bool -silc_key_agreement(SilcClient client, SilcClientConnection conn, - SilcClientEntry client_entry, const char *hostname, - SilcUInt16 port, SilcKeyAgreementCallback *completion, - void **context) -{ - silcpurple_buddy_keyagr_request(client, conn, client_entry, hostname, port); - *completion = NULL; - *context = NULL; - return FALSE; -} - - -/* Notifies application that file transfer protocol session is being - requested by the remote client indicated by the `client_entry' from - the `hostname' and `port'. The `session_id' is the file transfer - session and it can be used to either accept or reject the file - transfer request, by calling the silc_client_file_receive or - silc_client_file_close, respectively. */ - -static void -silc_ftp(SilcClient client, SilcClientConnection conn, - SilcClientEntry client_entry, SilcUInt32 session_id, - const char *hostname, SilcUInt16 port) -{ - silcpurple_ftp_request(client, conn, client_entry, session_id, - hostname, port); -} - - -/* Delivers SILC session detachment data indicated by `detach_data' to the - application. If application has issued SILC_COMMAND_DETACH command - the client session in the SILC network is not quit. The client remains - in the network but is detached. The detachment data may be used later - to resume the session in the SILC Network. The appliation is - responsible of saving the `detach_data', to for example in a file. - - The detachment data can be given as argument to the functions - silc_client_connect_to_server, or silc_client_add_connection when - creating connection to remote server, inside SilcClientConnectionParams - structure. If it is provided the client library will attempt to resume - the session in the network. After the connection is created - successfully, the application is responsible of setting the user - interface for user into the same state it was before detaching (showing - same channels, channel modes, etc). It can do this by fetching the - information (like joined channels) from the client library. */ - -static void -silc_detach(SilcClient client, SilcClientConnection conn, - const unsigned char *detach_data, SilcUInt32 detach_data_len) -{ - PurpleConnection *gc = client->application; - SilcPurple sg = gc->proto_data; - const char *file; - - /* Save the detachment data to file. */ - file = silcpurple_session_file(purple_account_get_username(sg->account)); - g_unlink(file); - silc_file_writefile(file, (char *)detach_data, detach_data_len); -} - -SilcClientOperations ops = { - silc_say, - silc_channel_message, - silc_private_message, - silc_notify, - silc_command, - silc_command_reply, - silc_connected, - silc_disconnected, - silc_get_auth_method, - silc_verify_public_key, - silc_ask_passphrase, - silc_failure, - silc_key_agreement, - silc_ftp, - silc_detach -}; diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/silc10/pk.c --- a/libpurple/protocols/silc10/pk.c Mon Aug 22 11:20:05 2011 +0900 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,274 +0,0 @@ -/* - - silcpurple_pk.c - - Author: Pekka Riikonen - - Copyright (C) 2004 Pekka Riikonen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - -*/ - -#include "silcincludes.h" -#include "silcclient.h" -#include "silcpurple.h" - -/************************* Public Key Verification ***************************/ - -typedef struct { - SilcClient client; - SilcClientConnection conn; - char *filename; - char *entity; - char *entity_name; - char *fingerprint; - char *babbleprint; - unsigned char *pk; - SilcUInt32 pk_len; - SilcSKEPKType pk_type; - SilcVerifyPublicKey completion; - void *context; - gboolean changed; -} *PublicKeyVerify; - -static void silcpurple_verify_ask(const char *entity, - const char *fingerprint, - const char *babbleprint, - PublicKeyVerify verify); - -static void silcpurple_verify_cb(PublicKeyVerify verify, gint id) -{ - if (id != 2) { - if (verify->completion) - verify->completion(FALSE, verify->context); - } else { - if (verify->completion) - verify->completion(TRUE, verify->context); - - /* Save the key for future checking */ - silc_pkcs_save_public_key_data(verify->filename, verify->pk, - verify->pk_len, SILC_PKCS_FILE_PEM); - } - - silc_free(verify->filename); - silc_free(verify->entity); - silc_free(verify->entity_name); - silc_free(verify->fingerprint); - silc_free(verify->babbleprint); - silc_free(verify->pk); - silc_free(verify); -} - -static void silcpurple_verify_details_cb(PublicKeyVerify verify) -{ - /* What a hack. We have to display the accept dialog _again_ - because Purple closes the dialog after you press the button. Purple - should have option for the dialogs whether the buttons close them - or not. */ - silcpurple_verify_ask(verify->entity, verify->fingerprint, - verify->babbleprint, verify); -} - -static void silcpurple_verify_details(PublicKeyVerify verify, gint id) -{ - SilcPublicKey public_key; - PurpleConnection *gc = verify->client->application; - SilcPurple sg = gc->proto_data; - - silc_pkcs_public_key_decode(verify->pk, verify->pk_len, - &public_key); - silcpurple_show_public_key(sg, verify->entity_name, public_key, - G_CALLBACK(silcpurple_verify_details_cb), - verify); - silc_pkcs_public_key_free(public_key); -} - -static void silcpurple_verify_ask(const char *entity, - const char *fingerprint, - const char *babbleprint, - PublicKeyVerify verify) -{ - PurpleConnection *gc = verify->client->application; - char tmp[256], tmp2[256]; - - if (verify->changed) { - g_snprintf(tmp, sizeof(tmp), - _("Received %s's public key. Your local copy does not match this " - "key. Would you still like to accept this public key?"), - entity); - } else { - g_snprintf(tmp, sizeof(tmp), - _("Received %s's public key. Would you like to accept this " - "public key?"), entity); - } - g_snprintf(tmp2, sizeof(tmp2), - _("Fingerprint and babbleprint for the %s key are:\n\n" - "%s\n%s\n"), entity, fingerprint, babbleprint); - - purple_request_action(gc, _("Verify Public Key"), tmp, tmp2, - PURPLE_DEFAULT_ACTION_NONE, - purple_connection_get_account(gc), entity, NULL, verify, 3, - _("Yes"), G_CALLBACK(silcpurple_verify_cb), - _("No"), G_CALLBACK(silcpurple_verify_cb), - _("_View..."), G_CALLBACK(silcpurple_verify_details)); -} - -void silcpurple_verify_public_key(SilcClient client, SilcClientConnection conn, - const char *name, SilcSocketType conn_type, - unsigned char *pk, SilcUInt32 pk_len, - SilcSKEPKType pk_type, - SilcVerifyPublicKey completion, void *context) -{ - PurpleConnection *gc = client->application; - int i; - char file[256], filename[256], filename2[256], *ipf, *hostf = NULL; - char *fingerprint, *babbleprint; - struct passwd *pw; - struct stat st; - char *entity = ((conn_type == SILC_SOCKET_TYPE_SERVER || - conn_type == SILC_SOCKET_TYPE_ROUTER) ? - "server" : "client"); - PublicKeyVerify verify; - - if (pk_type != SILC_SKE_PK_TYPE_SILC) { - purple_notify_error(gc, _("Verify Public Key"), - _("Unsupported public key type"), NULL); - if (completion) - completion(FALSE, context); - return; - } - - pw = getpwuid(getuid()); - if (!pw) { - if (completion) - completion(FALSE, context); - return; - } - - memset(filename, 0, sizeof(filename)); - memset(filename2, 0, sizeof(filename2)); - memset(file, 0, sizeof(file)); - - if (conn_type == SILC_SOCKET_TYPE_SERVER || - conn_type == SILC_SOCKET_TYPE_ROUTER) { - if (!name) { - g_snprintf(file, sizeof(file) - 1, "%skey_%s_%d.pub", entity, - conn->sock->ip, conn->sock->port); - g_snprintf(filename, sizeof(filename) - 1, - "%s" G_DIR_SEPARATOR_S "%skeys" G_DIR_SEPARATOR_S "%s", - silcpurple_silcdir(), entity, file); - - g_snprintf(file, sizeof(file) - 1, "%skey_%s_%d.pub", entity, - conn->sock->hostname, conn->sock->port); - g_snprintf(filename2, sizeof(filename2) - 1, - "%s" G_DIR_SEPARATOR_S "%skeys" G_DIR_SEPARATOR_S "%s", - silcpurple_silcdir(), entity, file); - - ipf = filename; - hostf = filename2; - } else { - g_snprintf(file, sizeof(file) - 1, "%skey_%s_%d.pub", entity, - name, conn->sock->port); - g_snprintf(filename, sizeof(filename) - 1, - "%s" G_DIR_SEPARATOR_S "%skeys" G_DIR_SEPARATOR_S "%s", - silcpurple_silcdir(), entity, file); - - ipf = filename; - } - } else { - /* Replace all whitespaces with `_'. */ - fingerprint = silc_hash_fingerprint(NULL, pk, pk_len); - for (i = 0; i < strlen(fingerprint); i++) - if (fingerprint[i] == ' ') - fingerprint[i] = '_'; - - g_snprintf(file, sizeof(file) - 1, "%skey_%s.pub", entity, fingerprint); - g_snprintf(filename, sizeof(filename) - 1, - "%s" G_DIR_SEPARATOR_S "%skeys" G_DIR_SEPARATOR_S "%s", - silcpurple_silcdir(), entity, file); - silc_free(fingerprint); - - ipf = filename; - } - - verify = silc_calloc(1, sizeof(*verify)); - if (!verify) - return; - verify->client = client; - verify->conn = conn; - verify->filename = strdup(ipf); - verify->entity = strdup(entity); - verify->entity_name = (conn_type != SILC_SOCKET_TYPE_CLIENT ? - (name ? strdup(name) : strdup(conn->sock->hostname)) - : NULL); - verify->pk = silc_memdup(pk, pk_len); - verify->pk_len = pk_len; - verify->pk_type = pk_type; - verify->completion = completion; - verify->context = context; - fingerprint = verify->fingerprint = silc_hash_fingerprint(NULL, pk, pk_len); - babbleprint = verify->babbleprint = silc_hash_babbleprint(NULL, pk, pk_len); - - /* Check whether this key already exists */ - if (g_stat(ipf, &st) < 0 && (!hostf || g_stat(hostf, &st) < 0)) { - /* Key does not exist, ask user to verify the key and save it */ - silcpurple_verify_ask(name ? name : entity, - fingerprint, babbleprint, verify); - return; - } else { - /* The key already exists, verify it. */ - SilcPublicKey public_key; - unsigned char *encpk; - SilcUInt32 encpk_len; - - /* Load the key file, try for both IP filename and hostname filename */ - if (!silc_pkcs_load_public_key(ipf, &public_key, - SILC_PKCS_FILE_PEM) && - !silc_pkcs_load_public_key(ipf, &public_key, - SILC_PKCS_FILE_BIN) && - (!hostf || (!silc_pkcs_load_public_key(hostf, &public_key, - SILC_PKCS_FILE_PEM) && - !silc_pkcs_load_public_key(hostf, &public_key, - SILC_PKCS_FILE_BIN)))) { - silcpurple_verify_ask(name ? name : entity, - fingerprint, babbleprint, verify); - return; - } - - /* Encode the key data */ - encpk = silc_pkcs_public_key_encode(public_key, &encpk_len); - if (!encpk) { - silcpurple_verify_ask(name ? name : entity, - fingerprint, babbleprint, verify); - return; - } - - /* Compare the keys */ - if (memcmp(encpk, pk, encpk_len)) { - /* Ask user to verify the key and save it */ - verify->changed = TRUE; - silcpurple_verify_ask(name ? name : entity, - fingerprint, babbleprint, verify); - return; - } - - /* Local copy matched */ - if (completion) - completion(TRUE, context); - silc_free(verify->filename); - silc_free(verify->entity); - silc_free(verify->entity_name); - silc_free(verify->pk); - silc_free(verify->fingerprint); - silc_free(verify->babbleprint); - silc_free(verify); - } -} diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/silc10/silc.c --- a/libpurple/protocols/silc10/silc.c Mon Aug 22 11:20:05 2011 +0900 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1965 +0,0 @@ -/* - - silcpurple.c - - Author: Pekka Riikonen - - Copyright (C) 2004 - 2005 Pekka Riikonen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - -*/ - -#include "silcincludes.h" -#include "silcclient.h" -#include "silcpurple.h" -#include "version.h" -#include "wb.h" -#include "core.h" - -extern SilcClientOperations ops; -static PurplePlugin *silc_plugin = NULL; - -static const char * -silcpurple_list_icon(PurpleAccount *a, PurpleBuddy *b) -{ - return (const char *)"silc"; -} - -static GList * -silcpurple_away_states(PurpleAccount *account) -{ - PurpleStatusType *type; - GList *types = NULL; - - type = purple_status_type_new_full(PURPLE_STATUS_AVAILABLE, SILCPURPLE_STATUS_ID_AVAILABLE, NULL, TRUE, TRUE, FALSE); - types = g_list_append(types, type); - type = purple_status_type_new_full(PURPLE_STATUS_AVAILABLE, SILCPURPLE_STATUS_ID_HYPER, _("Hyper Active"), TRUE, TRUE, FALSE); - types = g_list_append(types, type); - type = purple_status_type_new_full(PURPLE_STATUS_AWAY, SILCPURPLE_STATUS_ID_AWAY, NULL, TRUE, TRUE, FALSE); - types = g_list_append(types, type); - type = purple_status_type_new_full(PURPLE_STATUS_UNAVAILABLE, SILCPURPLE_STATUS_ID_BUSY, _("Busy"), TRUE, TRUE, FALSE); - types = g_list_append(types, type); - type = purple_status_type_new_full(PURPLE_STATUS_AWAY, SILCPURPLE_STATUS_ID_INDISPOSED, _("Indisposed"), TRUE, TRUE, FALSE); - types = g_list_append(types, type); - type = purple_status_type_new_full(PURPLE_STATUS_AWAY, SILCPURPLE_STATUS_ID_PAGE, _("Wake Me Up"), TRUE, TRUE, FALSE); - types = g_list_append(types, type); - type = purple_status_type_new_full(PURPLE_STATUS_OFFLINE, SILCPURPLE_STATUS_ID_OFFLINE, NULL, TRUE, TRUE, FALSE); - types = g_list_append(types, type); - - return types; -} - -static void -silcpurple_set_status(PurpleAccount *account, PurpleStatus *status) -{ - PurpleConnection *gc = purple_account_get_connection(account); - SilcPurple sg = NULL; - SilcUInt32 mode; - SilcBuffer idp; - unsigned char mb[4]; - const char *state; - - if (gc != NULL) - sg = gc->proto_data; - - if (status == NULL) - return; - - state = purple_status_get_id(status); - - if (state == NULL) - return; - - if ((sg == NULL) || (sg->conn == NULL)) - return; - - mode = sg->conn->local_entry->mode; - mode &= ~(SILC_UMODE_GONE | - SILC_UMODE_HYPER | - SILC_UMODE_BUSY | - SILC_UMODE_INDISPOSED | - SILC_UMODE_PAGE); - - if (!strcmp(state, "hyper")) - mode |= SILC_UMODE_HYPER; - else if (!strcmp(state, "away")) - mode |= SILC_UMODE_GONE; - else if (!strcmp(state, "busy")) - mode |= SILC_UMODE_BUSY; - else if (!strcmp(state, "indisposed")) - mode |= SILC_UMODE_INDISPOSED; - else if (!strcmp(state, "page")) - mode |= SILC_UMODE_PAGE; - - /* Send UMODE */ - idp = silc_id_payload_encode(sg->conn->local_id, SILC_ID_CLIENT); - SILC_PUT32_MSB(mode, mb); - silc_client_command_send(sg->client, sg->conn, SILC_COMMAND_UMODE, - ++sg->conn->cmd_ident, 2, - 1, idp->data, idp->len, - 2, mb, sizeof(mb)); - silc_buffer_free(idp); -} - - -/*************************** Connection Routines *****************************/ - -static void -silcpurple_keepalive(PurpleConnection *gc) -{ - SilcPurple sg = gc->proto_data; - silc_client_send_packet(sg->client, sg->conn, SILC_PACKET_HEARTBEAT, - NULL, 0); -} - -static gboolean -silcpurple_scheduler(gpointer *context) -{ - SilcPurple sg = (SilcPurple)context; - silc_client_run_one(sg->client); - return TRUE; -} - -static void -silcpurple_nickname_parse(const char *nickname, - char **ret_nickname) -{ - silc_parse_userfqdn(nickname, ret_nickname, NULL); -} - -static void -silcpurple_login_connected(gpointer data, gint source, const gchar *error_message) -{ - PurpleConnection *gc = data; - SilcPurple sg; - SilcClient client; - SilcClientConnection conn; - PurpleAccount *account; - SilcClientConnectionParams params; - SilcUInt32 mask; - const char *dfile, *tmp; -#ifdef SILC_ATTRIBUTE_USER_ICON - PurpleStoredImage *img; -#endif -#ifdef HAVE_SYS_UTSNAME_H - struct utsname u; -#endif - - - g_return_if_fail(gc != NULL); - - sg = gc->proto_data; - - if (source < 0) { - purple_connection_error(gc, - PURPLE_CONNECTION_ERROR_NETWORK_ERROR, - _("Connection failed")); - return; - } - - client = sg->client; - account = sg->account; - - /* Get session detachment data, if available */ - memset(¶ms, 0, sizeof(params)); - dfile = silcpurple_session_file(purple_account_get_username(sg->account)); - params.detach_data = (unsigned char *)silc_file_readfile(dfile, ¶ms.detach_data_len); - if (params.detach_data) - params.detach_data[params.detach_data_len] = 0; - - /* Add connection to SILC client library */ - conn = silc_client_add_connection( - sg->client, ¶ms, - (char *)purple_account_get_string(account, "server", - "silc.silcnet.org"), - purple_account_get_int(account, "port", 706), sg); - if (!conn) { - purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, - _("Unable to initialize SILC Client connection")); - gc->proto_data = NULL; - return; - } - sg->conn = conn; - - /* Progress */ - if (params.detach_data) { - purple_connection_update_progress(gc, _("Resuming session"), 2, 5); - sg->resuming = TRUE; - } else { - purple_connection_update_progress(gc, _("Performing key exchange"), 2, 5); - } - - /* Perform SILC Key Exchange. The "silc_connected" will be called - eventually. */ - silc_client_start_key_exchange(sg->client, sg->conn, source); - - /* Set default attributes */ - mask = SILC_ATTRIBUTE_MOOD_NORMAL; - silc_client_attribute_add(client, conn, - SILC_ATTRIBUTE_STATUS_MOOD, - SILC_32_TO_PTR(mask), - sizeof(SilcUInt32)); - mask = SILC_ATTRIBUTE_CONTACT_CHAT; - silc_client_attribute_add(client, conn, - SILC_ATTRIBUTE_PREFERRED_CONTACT, - SILC_32_TO_PTR(mask), - sizeof(SilcUInt32)); -#ifdef HAVE_SYS_UTSNAME_H - if (!uname(&u)) { - SilcAttributeObjDevice dev; - memset(&dev, 0, sizeof(dev)); - dev.type = SILC_ATTRIBUTE_DEVICE_COMPUTER; - dev.version = u.release; - dev.model = u.sysname; - silc_client_attribute_add(client, conn, - SILC_ATTRIBUTE_DEVICE_INFO, - (void *)&dev, sizeof(dev)); - } -#endif -#ifdef _WIN32 - tmp = _tzname[0]; -#else - tmp = tzname[0]; -#endif - silc_client_attribute_add(client, conn, - SILC_ATTRIBUTE_TIMEZONE, - (void *)tmp, strlen(tmp)); - -#ifdef SILC_ATTRIBUTE_USER_ICON - /* Set our buddy icon */ - img = purple_buddy_icons_find_account_icon(account); - silcpurple_buddy_set_icon(gc, img); - purple_imgstore_unref(img); -#endif - - silc_free(params.detach_data); -} - -static void -silcpurple_login(PurpleAccount *account) -{ - SilcPurple sg; - SilcClient client; - SilcClientParams params; - PurpleConnection *gc; - char pkd[256], prd[256]; - const char *cipher, *hmac; - char *realname; - int i; - - gc = account->gc; - if (!gc) - return; - gc->proto_data = NULL; - - memset(¶ms, 0, sizeof(params)); - strcat(params.nickname_format, "%n@%h%a"); - params.nickname_parse = silcpurple_nickname_parse; - params.ignore_requested_attributes = FALSE; - - /* Allocate SILC client */ - client = silc_client_alloc(&ops, ¶ms, gc, NULL); - if (!client) { - purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, - _("Out of memory")); - return; - } - - /* Get username, real name and local hostname for SILC library */ - if (purple_account_get_username(account)) { - const char *u = purple_account_get_username(account); - char **up = g_strsplit(u, "@", 2); - client->username = strdup(up[0]); - g_strfreev(up); - } else { - client->username = silc_get_username(); - purple_account_set_username(account, client->username); - } - realname = silc_get_real_name(); - if (purple_account_get_user_info(account)) { - client->realname = strdup(purple_account_get_user_info(account)); - free(realname); - } else if ((silc_get_real_name() != NULL) && (*realname != '\0')) { - client->realname = realname; - purple_account_set_user_info(account, client->realname); - } else { - free(realname); - client->realname = strdup(_("John Noname")); - } - client->hostname = silc_net_localhost(); - - purple_connection_set_display_name(gc, client->username); - - /* Register requested cipher and HMAC */ - cipher = purple_account_get_string(account, "cipher", SILC_DEFAULT_CIPHER); - for (i = 0; silc_default_ciphers[i].name; i++) - if (!strcmp(silc_default_ciphers[i].name, cipher)) { - silc_cipher_register(&(silc_default_ciphers[i])); - break; - } - hmac = purple_account_get_string(account, "hmac", SILC_DEFAULT_HMAC); - for (i = 0; silc_default_hmacs[i].name; i++) - if (!strcmp(silc_default_hmacs[i].name, hmac)) { - silc_hmac_register(&(silc_default_hmacs[i])); - break; - } - - /* Init SILC client */ - if (!silc_client_init(client)) { - purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, - _("Unable to initialize SILC protocol")); - return; - } - - /* Check the ~/.silc dir and create it, and new key pair if necessary. */ - if (!silcpurple_check_silc_dir(gc)) { - purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, - _("Error loading SILC key pair")); - return; - } - - /* Progress */ - purple_connection_update_progress(gc, _("Connecting to SILC Server"), 1, 5); - - /* Load SILC key pair */ - g_snprintf(pkd, sizeof(pkd), "%s" G_DIR_SEPARATOR_S "public_key.pub", silcpurple_silcdir()); - g_snprintf(prd, sizeof(prd), "%s" G_DIR_SEPARATOR_S "private_key.prv", silcpurple_silcdir()); - if (!silc_load_key_pair((char *)purple_account_get_string(account, "public-key", pkd), - (char *)purple_account_get_string(account, "private-key", prd), - (gc->password == NULL) ? "" : gc->password, &client->pkcs, - &client->public_key, &client->private_key)) { - g_snprintf(pkd, sizeof(pkd), _("Unable to load SILC key pair: %s"), g_strerror(errno)); - purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, - pkd); - return; - } - - sg = silc_calloc(1, sizeof(*sg)); - if (!sg) - return; - memset(sg, 0, sizeof(*sg)); - sg->client = client; - sg->gc = gc; - sg->account = account; - gc->proto_data = sg; - - /* Connect to the SILC server */ - if (purple_proxy_connect(gc, account, - purple_account_get_string(account, "server", - "silc.silcnet.org"), - purple_account_get_int(account, "port", 706), - silcpurple_login_connected, gc) == NULL) - { - purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, - _("Unable to create connection")); - return; - } - - /* Schedule SILC using Glib's event loop */ - sg->scheduler = purple_timeout_add(300, (GSourceFunc)silcpurple_scheduler, sg); -} - -static int -silcpurple_close_final(gpointer *context) -{ - SilcPurple sg = (SilcPurple)context; - silc_client_stop(sg->client); - silc_client_free(sg->client); -#ifdef HAVE_SILCMIME_H - if (sg->mimeass) - silc_mime_assembler_free(sg->mimeass); -#endif - silc_free(sg); - return 0; -} - -static void -silcpurple_close(PurpleConnection *gc) -{ - SilcPurple sg = gc->proto_data; - GHashTable *ui_info; - const char *ui_name = NULL, *ui_website = NULL; - char *quit_msg; - - g_return_if_fail(sg != NULL); - - ui_info = purple_core_get_ui_info(); - - if(ui_info) { - ui_name = g_hash_table_lookup(ui_info, "name"); - ui_website = g_hash_table_lookup(ui_info, "website"); - } - - if(!ui_name || !ui_website) { - ui_name = "Pidgin"; - ui_website = PURPLE_WEBSITE; - } - quit_msg = g_strdup_printf(_("Download %s: %s"), - ui_name, ui_website); - - /* Send QUIT */ - silc_client_command_call(sg->client, sg->conn, NULL, - "QUIT", quit_msg, NULL); - g_free(quit_msg); - - if (sg->conn) - silc_client_close_connection(sg->client, sg->conn); - - purple_timeout_remove(sg->scheduler); - purple_timeout_add(1, (GSourceFunc)silcpurple_close_final, sg); -} - - -/****************************** Protocol Actions *****************************/ - -static void -silcpurple_attrs_cancel(PurpleConnection *gc, PurpleRequestFields *fields) -{ - /* Nothing */ -} - -static void -silcpurple_attrs_cb(PurpleConnection *gc, PurpleRequestFields *fields) -{ - SilcPurple sg = gc->proto_data; - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - PurpleRequestField *f; - char *tmp; - SilcUInt32 tmp_len, mask; - SilcAttributeObjService service; - SilcAttributeObjDevice dev; - SilcVCardStruct vcard; - const char *val; - - sg = gc->proto_data; - if (!sg) - return; - - memset(&service, 0, sizeof(service)); - memset(&dev, 0, sizeof(dev)); - memset(&vcard, 0, sizeof(vcard)); - - silc_client_attribute_del(client, conn, - SILC_ATTRIBUTE_USER_INFO, NULL); - silc_client_attribute_del(client, conn, - SILC_ATTRIBUTE_SERVICE, NULL); - silc_client_attribute_del(client, conn, - SILC_ATTRIBUTE_STATUS_MOOD, NULL); - silc_client_attribute_del(client, conn, - SILC_ATTRIBUTE_STATUS_FREETEXT, NULL); - silc_client_attribute_del(client, conn, - SILC_ATTRIBUTE_STATUS_MESSAGE, NULL); - silc_client_attribute_del(client, conn, - SILC_ATTRIBUTE_PREFERRED_LANGUAGE, NULL); - silc_client_attribute_del(client, conn, - SILC_ATTRIBUTE_PREFERRED_CONTACT, NULL); - silc_client_attribute_del(client, conn, - SILC_ATTRIBUTE_TIMEZONE, NULL); - silc_client_attribute_del(client, conn, - SILC_ATTRIBUTE_GEOLOCATION, NULL); - silc_client_attribute_del(client, conn, - SILC_ATTRIBUTE_DEVICE_INFO, NULL); - - /* Set mood */ - mask = 0; - f = purple_request_fields_get_field(fields, "mood_normal"); - if (f && purple_request_field_bool_get_value(f)) - mask |= SILC_ATTRIBUTE_MOOD_NORMAL; - f = purple_request_fields_get_field(fields, "mood_happy"); - if (f && purple_request_field_bool_get_value(f)) - mask |= SILC_ATTRIBUTE_MOOD_HAPPY; - f = purple_request_fields_get_field(fields, "mood_sad"); - if (f && purple_request_field_bool_get_value(f)) - mask |= SILC_ATTRIBUTE_MOOD_SAD; - f = purple_request_fields_get_field(fields, "mood_angry"); - if (f && purple_request_field_bool_get_value(f)) - mask |= SILC_ATTRIBUTE_MOOD_ANGRY; - f = purple_request_fields_get_field(fields, "mood_jealous"); - if (f && purple_request_field_bool_get_value(f)) - mask |= SILC_ATTRIBUTE_MOOD_JEALOUS; - f = purple_request_fields_get_field(fields, "mood_ashamed"); - if (f && purple_request_field_bool_get_value(f)) - mask |= SILC_ATTRIBUTE_MOOD_ASHAMED; - f = purple_request_fields_get_field(fields, "mood_invincible"); - if (f && purple_request_field_bool_get_value(f)) - mask |= SILC_ATTRIBUTE_MOOD_INVINCIBLE; - f = purple_request_fields_get_field(fields, "mood_inlove"); - if (f && purple_request_field_bool_get_value(f)) - mask |= SILC_ATTRIBUTE_MOOD_INLOVE; - f = purple_request_fields_get_field(fields, "mood_sleepy"); - if (f && purple_request_field_bool_get_value(f)) - mask |= SILC_ATTRIBUTE_MOOD_SLEEPY; - f = purple_request_fields_get_field(fields, "mood_bored"); - if (f && purple_request_field_bool_get_value(f)) - mask |= SILC_ATTRIBUTE_MOOD_BORED; - f = purple_request_fields_get_field(fields, "mood_excited"); - if (f && purple_request_field_bool_get_value(f)) - mask |= SILC_ATTRIBUTE_MOOD_EXCITED; - f = purple_request_fields_get_field(fields, "mood_anxious"); - if (f && purple_request_field_bool_get_value(f)) - mask |= SILC_ATTRIBUTE_MOOD_ANXIOUS; - silc_client_attribute_add(client, conn, - SILC_ATTRIBUTE_STATUS_MOOD, - SILC_32_TO_PTR(mask), - sizeof(SilcUInt32)); - - /* Set preferred contact */ - mask = 0; - f = purple_request_fields_get_field(fields, "contact_chat"); - if (f && purple_request_field_bool_get_value(f)) - mask |= SILC_ATTRIBUTE_CONTACT_CHAT; - f = purple_request_fields_get_field(fields, "contact_email"); - if (f && purple_request_field_bool_get_value(f)) - mask |= SILC_ATTRIBUTE_CONTACT_EMAIL; - f = purple_request_fields_get_field(fields, "contact_call"); - if (f && purple_request_field_bool_get_value(f)) - mask |= SILC_ATTRIBUTE_CONTACT_CALL; - f = purple_request_fields_get_field(fields, "contact_sms"); - if (f && purple_request_field_bool_get_value(f)) - mask |= SILC_ATTRIBUTE_CONTACT_SMS; - f = purple_request_fields_get_field(fields, "contact_mms"); - if (f && purple_request_field_bool_get_value(f)) - mask |= SILC_ATTRIBUTE_CONTACT_MMS; - f = purple_request_fields_get_field(fields, "contact_video"); - if (f && purple_request_field_bool_get_value(f)) - mask |= SILC_ATTRIBUTE_CONTACT_VIDEO; - if (mask) - silc_client_attribute_add(client, conn, - SILC_ATTRIBUTE_PREFERRED_CONTACT, - SILC_32_TO_PTR(mask), - sizeof(SilcUInt32)); - - /* Set status text */ - val = NULL; - f = purple_request_fields_get_field(fields, "status_text"); - if (f) - val = purple_request_field_string_get_value(f); - if (val && *val) - silc_client_attribute_add(client, conn, - SILC_ATTRIBUTE_STATUS_FREETEXT, - (void *)val, strlen(val)); - - /* Set vcard */ - val = NULL; - f = purple_request_fields_get_field(fields, "vcard"); - if (f) - val = purple_request_field_string_get_value(f); - if (val && *val) { - purple_account_set_string(sg->account, "vcard", val); - tmp = silc_file_readfile(val, &tmp_len); - if (tmp) { - tmp[tmp_len] = 0; - if (silc_vcard_decode((unsigned char *)tmp, tmp_len, &vcard)) - silc_client_attribute_add(client, conn, - SILC_ATTRIBUTE_USER_INFO, - (void *)&vcard, - sizeof(vcard)); - } - silc_vcard_free(&vcard); - silc_free(tmp); - } else { - purple_account_set_string(sg->account, "vcard", ""); - } - -#ifdef HAVE_SYS_UTSNAME_H - /* Set device info */ - f = purple_request_fields_get_field(fields, "device"); - if (f && purple_request_field_bool_get_value(f)) { - struct utsname u; - if (!uname(&u)) { - dev.type = SILC_ATTRIBUTE_DEVICE_COMPUTER; - dev.version = u.release; - dev.model = u.sysname; - silc_client_attribute_add(client, conn, - SILC_ATTRIBUTE_DEVICE_INFO, - (void *)&dev, sizeof(dev)); - } - } -#endif - - /* Set timezone */ - val = NULL; - f = purple_request_fields_get_field(fields, "timezone"); - if (f) - val = purple_request_field_string_get_value(f); - if (val && *val) - silc_client_attribute_add(client, conn, - SILC_ATTRIBUTE_TIMEZONE, - (void *)val, strlen(val)); -} - -static void -silcpurple_attrs(PurplePluginAction *action) -{ - PurpleConnection *gc = (PurpleConnection *) action->context; - SilcPurple sg = gc->proto_data; - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - PurpleRequestFields *fields; - PurpleRequestFieldGroup *g; - PurpleRequestField *f; - SilcHashTable attrs; - SilcAttributePayload attr; - gboolean mnormal = TRUE, mhappy = FALSE, msad = FALSE, - mangry = FALSE, mjealous = FALSE, mashamed = FALSE, - minvincible = FALSE, minlove = FALSE, msleepy = FALSE, - mbored = FALSE, mexcited = FALSE, manxious = FALSE; - gboolean cemail = FALSE, ccall = FALSE, csms = FALSE, - cmms = FALSE, cchat = TRUE, cvideo = FALSE; - gboolean device = TRUE; - char status[1024]; - - sg = gc->proto_data; - if (!sg) - return; - - memset(status, 0, sizeof(status)); - - attrs = silc_client_attributes_get(client, conn); - if (attrs) { - if (silc_hash_table_find(attrs, - SILC_32_TO_PTR(SILC_ATTRIBUTE_STATUS_MOOD), - NULL, (void *)&attr)) { - SilcUInt32 mood = 0; - silc_attribute_get_object(attr, &mood, sizeof(mood)); - mnormal = !mood; - mhappy = (mood & SILC_ATTRIBUTE_MOOD_HAPPY); - msad = (mood & SILC_ATTRIBUTE_MOOD_SAD); - mangry = (mood & SILC_ATTRIBUTE_MOOD_ANGRY); - mjealous = (mood & SILC_ATTRIBUTE_MOOD_JEALOUS); - mashamed = (mood & SILC_ATTRIBUTE_MOOD_ASHAMED); - minvincible = (mood & SILC_ATTRIBUTE_MOOD_INVINCIBLE); - minlove = (mood & SILC_ATTRIBUTE_MOOD_INLOVE); - msleepy = (mood & SILC_ATTRIBUTE_MOOD_SLEEPY); - mbored = (mood & SILC_ATTRIBUTE_MOOD_BORED); - mexcited = (mood & SILC_ATTRIBUTE_MOOD_EXCITED); - manxious = (mood & SILC_ATTRIBUTE_MOOD_ANXIOUS); - } - - if (silc_hash_table_find(attrs, - SILC_32_TO_PTR(SILC_ATTRIBUTE_PREFERRED_CONTACT), - NULL, (void *)&attr)) { - SilcUInt32 contact = 0; - silc_attribute_get_object(attr, &contact, sizeof(contact)); - cemail = (contact & SILC_ATTRIBUTE_CONTACT_EMAIL); - ccall = (contact & SILC_ATTRIBUTE_CONTACT_CALL); - csms = (contact & SILC_ATTRIBUTE_CONTACT_SMS); - cmms = (contact & SILC_ATTRIBUTE_CONTACT_MMS); - cchat = (contact & SILC_ATTRIBUTE_CONTACT_CHAT); - cvideo = (contact & SILC_ATTRIBUTE_CONTACT_VIDEO); - } - - if (silc_hash_table_find(attrs, - SILC_32_TO_PTR(SILC_ATTRIBUTE_STATUS_FREETEXT), - NULL, (void *)&attr)) - silc_attribute_get_object(attr, &status, sizeof(status)); - - if (!silc_hash_table_find(attrs, - SILC_32_TO_PTR(SILC_ATTRIBUTE_DEVICE_INFO), - NULL, (void *)&attr)) - device = FALSE; - } - - fields = purple_request_fields_new(); - - g = purple_request_field_group_new(NULL); - f = purple_request_field_label_new("l3", _("Your Current Mood")); - purple_request_field_group_add_field(g, f); - f = purple_request_field_bool_new("mood_normal", _("Normal"), mnormal); - purple_request_field_group_add_field(g, f); - f = purple_request_field_bool_new("mood_happy", _("Happy"), mhappy); - purple_request_field_group_add_field(g, f); - f = purple_request_field_bool_new("mood_sad", _("Sad"), msad); - purple_request_field_group_add_field(g, f); - f = purple_request_field_bool_new("mood_angry", _("Angry"), mangry); - purple_request_field_group_add_field(g, f); - f = purple_request_field_bool_new("mood_jealous", _("Jealous"), mjealous); - purple_request_field_group_add_field(g, f); - f = purple_request_field_bool_new("mood_ashamed", _("Ashamed"), mashamed); - purple_request_field_group_add_field(g, f); - f = purple_request_field_bool_new("mood_invincible", _("Invincible"), minvincible); - purple_request_field_group_add_field(g, f); - f = purple_request_field_bool_new("mood_inlove", _("In love"), minlove); - purple_request_field_group_add_field(g, f); - f = purple_request_field_bool_new("mood_sleepy", _("Sleepy"), msleepy); - purple_request_field_group_add_field(g, f); - f = purple_request_field_bool_new("mood_bored", _("Bored"), mbored); - purple_request_field_group_add_field(g, f); - f = purple_request_field_bool_new("mood_excited", _("Excited"), mexcited); - purple_request_field_group_add_field(g, f); - f = purple_request_field_bool_new("mood_anxious", _("Anxious"), manxious); - purple_request_field_group_add_field(g, f); - - f = purple_request_field_label_new("l4", _("\nYour Preferred Contact Methods")); - purple_request_field_group_add_field(g, f); - f = purple_request_field_bool_new("contact_chat", _("Chat"), cchat); - purple_request_field_group_add_field(g, f); - f = purple_request_field_bool_new("contact_email", _("Email"), cemail); - purple_request_field_group_add_field(g, f); - f = purple_request_field_bool_new("contact_call", _("Phone"), ccall); - purple_request_field_group_add_field(g, f); - f = purple_request_field_bool_new("contact_sms", _("SMS"), csms); - purple_request_field_group_add_field(g, f); - f = purple_request_field_bool_new("contact_mms", _("MMS"), cmms); - purple_request_field_group_add_field(g, f); - f = purple_request_field_bool_new("contact_video", _("Video conferencing"), cvideo); - purple_request_field_group_add_field(g, f); - purple_request_fields_add_group(fields, g); - - g = purple_request_field_group_new(NULL); - f = purple_request_field_string_new("status_text", _("Your Current Status"), - status[0] ? status : NULL, TRUE); - purple_request_field_group_add_field(g, f); - purple_request_fields_add_group(fields, g); - - g = purple_request_field_group_new(NULL); -#if 0 - f = purple_request_field_label_new("l2", _("Online Services")); - purple_request_field_group_add_field(g, f); - f = purple_request_field_bool_new("services", - _("Let others see what services you are using"), - TRUE); - purple_request_field_group_add_field(g, f); -#endif -#ifdef HAVE_SYS_UTSNAME_H - f = purple_request_field_bool_new("device", - _("Let others see what computer you are using"), - device); - purple_request_field_group_add_field(g, f); -#endif - purple_request_fields_add_group(fields, g); - - g = purple_request_field_group_new(NULL); - f = purple_request_field_string_new("vcard", _("Your VCard File"), - purple_account_get_string(sg->account, "vcard", ""), - FALSE); - purple_request_field_group_add_field(g, f); -#ifdef _WIN32 - f = purple_request_field_string_new("timezone", _("Timezone"), _tzname[0], FALSE); -#else - f = purple_request_field_string_new("timezone", _("Timezone"), tzname[0], FALSE); -#endif - purple_request_field_group_add_field(g, f); - purple_request_fields_add_group(fields, g); - - purple_request_fields(gc, _("User Online Status Attributes"), - _("User Online Status Attributes"), - _("You can let other users see your online status information " - "and your personal information. Please fill the information " - "you would like other users to see about yourself."), - fields, - _("OK"), G_CALLBACK(silcpurple_attrs_cb), - _("Cancel"), G_CALLBACK(silcpurple_attrs_cancel), - gc->account, NULL, NULL, gc); -} - -static void -silcpurple_detach(PurplePluginAction *action) -{ - PurpleConnection *gc = (PurpleConnection *) action->context; - SilcPurple sg; - - if (!gc) - return; - sg = gc->proto_data; - if (!sg) - return; - - /* Call DETACH */ - silc_client_command_call(sg->client, sg->conn, "DETACH"); - sg->detaching = TRUE; -} - -static void -silcpurple_view_motd(PurplePluginAction *action) -{ - PurpleConnection *gc = (PurpleConnection *) action->context; - SilcPurple sg; - char *tmp; - - if (!gc) - return; - sg = gc->proto_data; - if (!sg) - return; - - if (!sg->motd) { - purple_notify_error( - gc, _("Message of the Day"), _("No Message of the Day available"), - _("There is no Message of the Day associated with this connection")); - return; - } - - tmp = g_markup_escape_text(sg->motd, -1); - purple_notify_formatted(gc, NULL, _("Message of the Day"), NULL, - tmp, NULL, NULL); - g_free(tmp); -} - -static void -silcpurple_create_keypair_cancel(PurpleConnection *gc, PurpleRequestFields *fields) -{ - /* Nothing */ -} - -static void -silcpurple_create_keypair_cb(PurpleConnection *gc, PurpleRequestFields *fields) -{ - SilcPurple sg = gc->proto_data; - PurpleRequestField *f; - const char *val, *pkfile = NULL, *prfile = NULL; - const char *pass1 = NULL, *pass2 = NULL, *un = NULL, *hn = NULL; - const char *rn = NULL, *e = NULL, *o = NULL, *c = NULL; - char *identifier; - int keylen = SILCPURPLE_DEF_PKCS_LEN; - SilcPublicKey public_key; - - sg = gc->proto_data; - if (!sg) - return; - - val = NULL; - f = purple_request_fields_get_field(fields, "pass1"); - if (f) - val = purple_request_field_string_get_value(f); - if (val && *val) - pass1 = val; - else - pass1 = ""; - val = NULL; - f = purple_request_fields_get_field(fields, "pass2"); - if (f) - val = purple_request_field_string_get_value(f); - if (val && *val) - pass2 = val; - else - pass2 = ""; - - if (strcmp(pass1, pass2)) { - purple_notify_error( - gc, _("Create New SILC Key Pair"), _("Passphrases do not match"), NULL); - return; - } - - val = NULL; - f = purple_request_fields_get_field(fields, "key"); - if (f) - val = purple_request_field_string_get_value(f); - if (val && *val) - keylen = atoi(val); - f = purple_request_fields_get_field(fields, "pkfile"); - if (f) - pkfile = purple_request_field_string_get_value(f); - f = purple_request_fields_get_field(fields, "prfile"); - if (f) - prfile = purple_request_field_string_get_value(f); - - f = purple_request_fields_get_field(fields, "un"); - if (f) - un = purple_request_field_string_get_value(f); - f = purple_request_fields_get_field(fields, "hn"); - if (f) - hn = purple_request_field_string_get_value(f); - f = purple_request_fields_get_field(fields, "rn"); - if (f) - rn = purple_request_field_string_get_value(f); - f = purple_request_fields_get_field(fields, "e"); - if (f) - e = purple_request_field_string_get_value(f); - f = purple_request_fields_get_field(fields, "o"); - if (f) - o = purple_request_field_string_get_value(f); - f = purple_request_fields_get_field(fields, "c"); - if (f) - c = purple_request_field_string_get_value(f); - - identifier = silc_pkcs_encode_identifier((char *)un, (char *)hn, - (char *)rn, (char *)e, (char *)o, (char *)c); - - /* Create the key pair */ - if (!silc_create_key_pair(SILCPURPLE_DEF_PKCS, keylen, pkfile, prfile, - identifier, pass1, NULL, &public_key, NULL, - FALSE)) { - purple_notify_error( - gc, _("Create New SILC Key Pair"), _("Key Pair Generation failed"), NULL); - return; - } - - silcpurple_show_public_key(sg, NULL, public_key, NULL, NULL); - - silc_pkcs_public_key_free(public_key); - silc_free(identifier); -} - -static void -silcpurple_create_keypair(PurplePluginAction *action) -{ - PurpleConnection *gc = (PurpleConnection *) action->context; - SilcPurple sg = gc->proto_data; - PurpleRequestFields *fields; - PurpleRequestFieldGroup *g; - PurpleRequestField *f; - const char *username, *realname; - char *hostname, **u; - char tmp[256], pkd[256], pkd2[256], prd[256], prd2[256]; - - username = purple_account_get_username(sg->account); - u = g_strsplit(username, "@", 2); - username = u[0]; - realname = purple_account_get_user_info(sg->account); - hostname = silc_net_localhost(); - g_snprintf(tmp, sizeof(tmp), "%s@%s", username, hostname); - - g_snprintf(pkd2, sizeof(pkd2), "%s" G_DIR_SEPARATOR_S"public_key.pub", silcpurple_silcdir()); - g_snprintf(prd2, sizeof(prd2), "%s" G_DIR_SEPARATOR_S"private_key.prv", silcpurple_silcdir()); - g_snprintf(pkd, sizeof(pkd) - 1, "%s", - purple_account_get_string(gc->account, "public-key", pkd2)); - g_snprintf(prd, sizeof(prd) - 1, "%s", - purple_account_get_string(gc->account, "private-key", prd2)); - - fields = purple_request_fields_new(); - - g = purple_request_field_group_new(NULL); - f = purple_request_field_string_new("key", _("Key length"), "2048", FALSE); - purple_request_field_group_add_field(g, f); - f = purple_request_field_string_new("pkfile", _("Public key file"), pkd, FALSE); - purple_request_field_group_add_field(g, f); - f = purple_request_field_string_new("prfile", _("Private key file"), prd, FALSE); - purple_request_field_group_add_field(g, f); - purple_request_fields_add_group(fields, g); - - g = purple_request_field_group_new(NULL); - f = purple_request_field_string_new("un", _("Username"), username ? username : "", FALSE); - purple_request_field_group_add_field(g, f); - f = purple_request_field_string_new("hn", _("Hostname"), hostname ? hostname : "", FALSE); - purple_request_field_group_add_field(g, f); - f = purple_request_field_string_new("rn", _("Real name"), realname ? realname : "", FALSE); - purple_request_field_group_add_field(g, f); - f = purple_request_field_string_new("e", _("Email"), tmp, FALSE); - purple_request_field_group_add_field(g, f); - f = purple_request_field_string_new("o", _("Organization"), "", FALSE); - purple_request_field_group_add_field(g, f); - f = purple_request_field_string_new("c", _("Country"), "", FALSE); - purple_request_field_group_add_field(g, f); - purple_request_fields_add_group(fields, g); - - g = purple_request_field_group_new(NULL); - f = purple_request_field_string_new("pass1", _("Passphrase"), "", FALSE); - purple_request_field_string_set_masked(f, TRUE); - purple_request_field_group_add_field(g, f); - f = purple_request_field_string_new("pass2", _("Passphrase (retype)"), "", FALSE); - purple_request_field_string_set_masked(f, TRUE); - purple_request_field_group_add_field(g, f); - purple_request_fields_add_group(fields, g); - - purple_request_fields(gc, _("Create New SILC Key Pair"), - _("Create New SILC Key Pair"), NULL, fields, - _("Generate Key Pair"), G_CALLBACK(silcpurple_create_keypair_cb), - _("Cancel"), G_CALLBACK(silcpurple_create_keypair_cancel), - gc->account, NULL, NULL, gc); - - g_strfreev(u); - silc_free(hostname); -} - -static void -silcpurple_change_pass(PurplePluginAction *action) -{ - PurpleConnection *gc = (PurpleConnection *) action->context; - purple_account_request_change_password(purple_connection_get_account(gc)); -} - -static void -silcpurple_change_passwd(PurpleConnection *gc, const char *old, const char *new) -{ - char prd[256]; - g_snprintf(prd, sizeof(prd), "%s" G_DIR_SEPARATOR_S "private_key.pub", silcpurple_silcdir()); - silc_change_private_key_passphrase(purple_account_get_string(gc->account, - "private-key", - prd), old ? old : "", new ? new : ""); -} - -static void -silcpurple_show_set_info(PurplePluginAction *action) -{ - PurpleConnection *gc = (PurpleConnection *) action->context; - purple_account_request_change_user_info(purple_connection_get_account(gc)); -} - -static void -silcpurple_set_info(PurpleConnection *gc, const char *text) -{ -} - -static GList * -silcpurple_actions(PurplePlugin *plugin, gpointer context) -{ - GList *list = NULL; - PurplePluginAction *act; - - act = purple_plugin_action_new(_("Online Status"), - silcpurple_attrs); - list = g_list_append(list, act); - - act = purple_plugin_action_new(_("Detach From Server"), - silcpurple_detach); - list = g_list_append(list, act); - - act = purple_plugin_action_new(_("View Message of the Day"), - silcpurple_view_motd); - list = g_list_append(list, act); - - act = purple_plugin_action_new(_("Create SILC Key Pair..."), - silcpurple_create_keypair); - list = g_list_append(list, act); - - act = purple_plugin_action_new(_("Change Password..."), - silcpurple_change_pass); - list = g_list_append(list, act); - - act = purple_plugin_action_new(_("Set User Info..."), - silcpurple_show_set_info); - list = g_list_append(list, act); - - return list; -} - - -/******************************* IM Routines *********************************/ - -typedef struct { - char *nick; - char *message; - SilcUInt32 message_len; - SilcMessageFlags flags; - PurpleMessageFlags gflags; -} *SilcPurpleIM; - -static void -silcpurple_send_im_resolved(SilcClient client, - SilcClientConnection conn, - SilcClientEntry *clients, - SilcUInt32 clients_count, - void *context) -{ - PurpleConnection *gc = client->application; - SilcPurple sg = gc->proto_data; - SilcPurpleIM im = context; - PurpleConversation *convo; - char tmp[256], *nickname = NULL; - SilcClientEntry client_entry; -#ifdef HAVE_SILCMIME_H - SilcDList list; -#endif - - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, im->nick, - sg->account); - if (!convo) - return; - - if (!clients) - goto err; - - if (clients_count > 1) { - silc_parse_userfqdn(im->nick, &nickname, NULL); - - /* Find the correct one. The im->nick might be a formatted nick - so this will find the correct one. */ - clients = silc_client_get_clients_local(client, conn, - nickname, im->nick, - &clients_count); - if (!clients) - goto err; - client_entry = clients[0]; - silc_free(clients); - } else { - client_entry = clients[0]; - } - -#ifdef HAVE_SILCMIME_H - /* Check for images */ - if (im->gflags & PURPLE_MESSAGE_IMAGES) { - list = silcpurple_image_message(im->message, (SilcUInt32 *)&im->flags); - if (list) { - /* Send one or more MIME message. If more than one, they - are MIME fragments due to over large message */ - SilcBuffer buf; - - silc_dlist_start(list); - while ((buf = silc_dlist_get(list)) != SILC_LIST_END) - silc_client_send_private_message(client, conn, - client_entry, im->flags, - buf->data, buf->len, - TRUE); - silc_mime_partial_free(list); - purple_conv_im_write(PURPLE_CONV_IM(convo), conn->local_entry->nickname, - im->message, 0, time(NULL)); - goto out; - } - } -#endif - - /* Send the message */ - silc_client_send_private_message(client, conn, client_entry, im->flags, - (unsigned char *)im->message, im->message_len, TRUE); - purple_conv_im_write(PURPLE_CONV_IM(convo), conn->local_entry->nickname, - im->message, 0, time(NULL)); - goto out; - - err: - g_snprintf(tmp, sizeof(tmp), - _("User %s is not present in the network"), im->nick); - purple_conversation_write(convo, NULL, tmp, PURPLE_MESSAGE_SYSTEM, time(NULL)); - - out: - g_free(im->nick); - g_free(im->message); - silc_free(im); - silc_free(nickname); -} - -static int -silcpurple_send_im(PurpleConnection *gc, const char *who, const char *message, - PurpleMessageFlags flags) -{ - SilcPurple sg = gc->proto_data; - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - SilcClientEntry *clients; - SilcUInt32 clients_count, mflags; - char *nickname, *msg, *tmp; - int ret = 0; - gboolean sign = purple_account_get_bool(sg->account, "sign-verify", FALSE); -#ifdef HAVE_SILCMIME_H - SilcDList list; -#endif - - if (!who || !message) - return 0; - - mflags = SILC_MESSAGE_FLAG_UTF8; - - tmp = msg = purple_unescape_html(message); - - if (!g_ascii_strncasecmp(msg, "/me ", 4)) { - msg += 4; - if (!*msg) { - g_free(tmp); - return 0; - } - mflags |= SILC_MESSAGE_FLAG_ACTION; - } else if (strlen(msg) > 1 && msg[0] == '/') { - if (!silc_client_command_call(client, conn, msg + 1)) - purple_notify_error(gc, _("Call Command"), _("Cannot call command"), - _("Unknown command")); - g_free(tmp); - return 0; - } - - - if (!silc_parse_userfqdn(who, &nickname, NULL)) { - g_free(tmp); - return 0; - } - - if (sign) - mflags |= SILC_MESSAGE_FLAG_SIGNED; - - /* Find client entry */ - clients = silc_client_get_clients_local(client, conn, nickname, who, - &clients_count); - if (!clients) { - /* Resolve unknown user */ - SilcPurpleIM im = silc_calloc(1, sizeof(*im)); - if (!im) { - g_free(tmp); - return 0; - } - im->nick = g_strdup(who); - im->message = g_strdup(message); - im->message_len = strlen(im->message); - im->flags = mflags; - im->gflags = flags; - silc_client_get_clients(client, conn, nickname, NULL, - silcpurple_send_im_resolved, im); - silc_free(nickname); - g_free(tmp); - return 0; - } - -#ifdef HAVE_SILCMIME_H - /* Check for images */ - if (flags & PURPLE_MESSAGE_IMAGES) { - list = silcpurple_image_message(message, &mflags); - if (list) { - /* Send one or more MIME message. If more than one, they - are MIME fragments due to over large message */ - SilcBuffer buf; - - silc_dlist_start(list); - while ((buf = silc_dlist_get(list)) != SILC_LIST_END) - ret = - silc_client_send_private_message(client, conn, - clients[0], mflags, - buf->data, buf->len, - TRUE); - silc_mime_partial_free(list); - g_free(tmp); - silc_free(nickname); - silc_free(clients); - return ret; - } - } -#endif - - /* Send private message directly */ - ret = silc_client_send_private_message(client, conn, clients[0], - mflags, - (unsigned char *)msg, - strlen(msg), TRUE); - - g_free(tmp); - silc_free(nickname); - silc_free(clients); - return ret; -} - - -static GList *silcpurple_blist_node_menu(PurpleBlistNode *node) { - /* split this single menu building function back into the two - original: one for buddies and one for chats */ - - if(PURPLE_BLIST_NODE_IS_CHAT(node)) { - return silcpurple_chat_menu((PurpleChat *) node); - } else if(PURPLE_BLIST_NODE_IS_BUDDY(node)) { - return silcpurple_buddy_menu((PurpleBuddy *) node); - } else { - g_return_val_if_reached(NULL); - } -} - -/********************************* Commands **********************************/ - -static PurpleCmdRet silcpurple_cmd_chat_part(PurpleConversation *conv, - const char *cmd, char **args, char **error, void *data) -{ - PurpleConnection *gc; - PurpleConversation *convo = conv; - int id = 0; - - gc = purple_conversation_get_gc(conv); - - if (gc == NULL) - return PURPLE_CMD_RET_FAILED; - - if(args && args[0]) - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, args[0], - gc->account); - - if (convo != NULL) - id = purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo)); - - if (id == 0) - return PURPLE_CMD_RET_FAILED; - - silcpurple_chat_leave(gc, id); - - return PURPLE_CMD_RET_OK; - -} - -static PurpleCmdRet silcpurple_cmd_chat_topic(PurpleConversation *conv, - const char *cmd, char **args, char **error, void *data) -{ - PurpleConnection *gc; - int id = 0; - char *buf, *tmp, *tmp2; - const char *topic; - - gc = purple_conversation_get_gc(conv); - id = purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)); - - if (gc == NULL || id == 0) - return PURPLE_CMD_RET_FAILED; - - if (!args || !args[0]) { - topic = purple_conv_chat_get_topic (PURPLE_CONV_CHAT(conv)); - if (topic) { - tmp = g_markup_escape_text(topic, -1); - tmp2 = purple_markup_linkify(tmp); - buf = g_strdup_printf(_("current topic is: %s"), tmp2); - g_free(tmp); - g_free(tmp2); - } else - buf = g_strdup(_("No topic is set")); - purple_conv_chat_write(PURPLE_CONV_CHAT(conv), gc->account->username, buf, - PURPLE_MESSAGE_SYSTEM|PURPLE_MESSAGE_NO_LOG, time(NULL)); - g_free(buf); - - } - - if (args && args[0] && (strlen(args[0]) > 255)) { - *error = g_strdup(_("Topic too long")); - return PURPLE_CMD_RET_FAILED; - } - - silcpurple_chat_set_topic(gc, id, args ? args[0] : NULL); - - return PURPLE_CMD_RET_OK; -} - -static PurpleCmdRet silcpurple_cmd_chat_join(PurpleConversation *conv, - const char *cmd, char **args, char **error, void *data) -{ - GHashTable *comp; - - if(!args || !args[0]) - return PURPLE_CMD_RET_FAILED; - - comp = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL); - - g_hash_table_replace(comp, "channel", args[0]); - if(args[1]) - g_hash_table_replace(comp, "passphrase", args[1]); - - silcpurple_chat_join(purple_conversation_get_gc(conv), comp); - - g_hash_table_destroy(comp); - return PURPLE_CMD_RET_OK; -} - -static PurpleCmdRet silcpurple_cmd_chat_list(PurpleConversation *conv, - const char *cmd, char **args, char **error, void *data) -{ - PurpleConnection *gc; - gc = purple_conversation_get_gc(conv); - purple_roomlist_show_with_account(purple_connection_get_account(gc)); - return PURPLE_CMD_RET_OK; -} - -static PurpleCmdRet silcpurple_cmd_whois(PurpleConversation *conv, - const char *cmd, char **args, char **error, void *data) -{ - PurpleConnection *gc; - - gc = purple_conversation_get_gc(conv); - - if (gc == NULL) - return PURPLE_CMD_RET_FAILED; - - silcpurple_get_info(gc, args[0]); - - return PURPLE_CMD_RET_OK; -} - -static PurpleCmdRet silcpurple_cmd_msg(PurpleConversation *conv, - const char *cmd, char **args, char **error, void *data) -{ - int ret; - PurpleConnection *gc; - - gc = purple_conversation_get_gc(conv); - - if (gc == NULL) - return PURPLE_CMD_RET_FAILED; - - ret = silcpurple_send_im(gc, args[0], args[1], PURPLE_MESSAGE_SEND); - - if (ret) - return PURPLE_CMD_RET_OK; - else - return PURPLE_CMD_RET_FAILED; -} - -static PurpleCmdRet silcpurple_cmd_query(PurpleConversation *conv, - const char *cmd, char **args, char **error, void *data) -{ - int ret = 1; - PurpleConversation *convo; - PurpleConnection *gc; - PurpleAccount *account; - - if (!args || !args[0]) { - *error = g_strdup(_("You must specify a nick")); - return PURPLE_CMD_RET_FAILED; - } - - gc = purple_conversation_get_gc(conv); - - if (gc == NULL) - return PURPLE_CMD_RET_FAILED; - - account = purple_connection_get_account(gc); - - convo = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, args[0]); - - if (args[1]) { - ret = silcpurple_send_im(gc, args[0], args[1], PURPLE_MESSAGE_SEND); - purple_conv_im_write(PURPLE_CONV_IM(convo), purple_connection_get_display_name(gc), - args[1], PURPLE_MESSAGE_SEND, time(NULL)); - } - - if (ret) - return PURPLE_CMD_RET_OK; - else - return PURPLE_CMD_RET_FAILED; -} - -static PurpleCmdRet silcpurple_cmd_motd(PurpleConversation *conv, - const char *cmd, char **args, char **error, void *data) -{ - PurpleConnection *gc; - SilcPurple sg; - char *tmp; - - gc = purple_conversation_get_gc(conv); - - if (gc == NULL) - return PURPLE_CMD_RET_FAILED; - - sg = gc->proto_data; - - if (sg == NULL) - return PURPLE_CMD_RET_FAILED; - - if (!sg->motd) { - *error = g_strdup(_("There is no Message of the Day associated with this connection")); - return PURPLE_CMD_RET_FAILED; - } - - tmp = g_markup_escape_text(sg->motd, -1); - purple_notify_formatted(gc, NULL, _("Message of the Day"), NULL, - tmp, NULL, NULL); - g_free(tmp); - - return PURPLE_CMD_RET_OK; -} - -static PurpleCmdRet silcpurple_cmd_detach(PurpleConversation *conv, - const char *cmd, char **args, char **error, void *data) -{ - PurpleConnection *gc; - SilcPurple sg; - - gc = purple_conversation_get_gc(conv); - - if (gc == NULL) - return PURPLE_CMD_RET_FAILED; - - sg = gc->proto_data; - - if (sg == NULL) - return PURPLE_CMD_RET_FAILED; - - silc_client_command_call(sg->client, sg->conn, "DETACH"); - sg->detaching = TRUE; - - return PURPLE_CMD_RET_OK; -} - -static PurpleCmdRet silcpurple_cmd_cmode(PurpleConversation *conv, - const char *cmd, char **args, char **error, void *data) -{ - PurpleConnection *gc; - SilcPurple sg; - SilcChannelEntry channel; - char *silccmd, *silcargs, *msg, tmp[256]; - const char *chname; - - gc = purple_conversation_get_gc(conv); - - if (gc == NULL || !args || gc->proto_data == NULL) - return PURPLE_CMD_RET_FAILED; - - sg = gc->proto_data; - - if (args[0]) - chname = args[0]; - else - chname = purple_conversation_get_name(conv); - - if (!args[1]) { - channel = silc_client_get_channel(sg->client, sg->conn, - (char *)chname); - if (!channel) { - *error = g_strdup_printf(_("channel %s not found"), chname); - return PURPLE_CMD_RET_FAILED; - } - if (channel->mode) { - silcpurple_get_chmode_string(channel->mode, tmp, sizeof(tmp)); - msg = g_strdup_printf(_("channel modes for %s: %s"), chname, tmp); - } else { - msg = g_strdup_printf(_("no channel modes are set on %s"), chname); - } - purple_conv_chat_write(PURPLE_CONV_CHAT(conv), "", - msg, PURPLE_MESSAGE_SYSTEM|PURPLE_MESSAGE_NO_LOG, time(NULL)); - g_free(msg); - return PURPLE_CMD_RET_OK; - } - - silcargs = g_strjoinv(" ", args); - silccmd = g_strconcat(cmd, " ", args ? silcargs : NULL, NULL); - g_free(silcargs); - if (!silc_client_command_call(sg->client, sg->conn, silccmd)) { - g_free(silccmd); - *error = g_strdup_printf(_("Failed to set cmodes for %s"), args[0]); - return PURPLE_CMD_RET_FAILED; - } - g_free(silccmd); - - return PURPLE_CMD_RET_OK; -} - -static PurpleCmdRet silcpurple_cmd_generic(PurpleConversation *conv, - const char *cmd, char **args, char **error, void *data) -{ - PurpleConnection *gc; - SilcPurple sg; - char *silccmd, *silcargs; - - gc = purple_conversation_get_gc(conv); - - if (gc == NULL) - return PURPLE_CMD_RET_FAILED; - - sg = gc->proto_data; - - if (sg == NULL) - return PURPLE_CMD_RET_FAILED; - - silcargs = g_strjoinv(" ", args); - silccmd = g_strconcat(cmd, " ", args ? silcargs : NULL, NULL); - g_free(silcargs); - if (!silc_client_command_call(sg->client, sg->conn, silccmd)) { - g_free(silccmd); - *error = g_strdup_printf(_("Unknown command: %s, (may be a client bug)"), cmd); - return PURPLE_CMD_RET_FAILED; - } - g_free(silccmd); - - return PURPLE_CMD_RET_OK; -} - -static PurpleCmdRet silcpurple_cmd_quit(PurpleConversation *conv, - const char *cmd, char **args, char **error, void *data) -{ - PurpleConnection *gc; - SilcPurple sg; - GHashTable *ui_info; - const char *ui_name = NULL, *ui_website = NULL; - char *quit_msg; - - gc = purple_conversation_get_gc(conv); - - if (gc == NULL) - return PURPLE_CMD_RET_FAILED; - - sg = gc->proto_data; - - if (sg == NULL) - return PURPLE_CMD_RET_FAILED; - - ui_info = purple_core_get_ui_info(); - - if(ui_info) { - ui_name = g_hash_table_lookup(ui_info, "name"); - ui_website = g_hash_table_lookup(ui_info, "website"); - } - - if(!ui_name || !ui_website) { - ui_name = "Pidgin"; - ui_website = PURPLE_WEBSITE; - } - quit_msg = g_strdup_printf(_("Download %s: %s"), - ui_name, ui_website); - - silc_client_command_call(sg->client, sg->conn, NULL, - "QUIT", (args && args[0]) ? args[0] : quit_msg, NULL); - g_free(quit_msg); - - return PURPLE_CMD_RET_OK; -} - -static PurpleCmdRet silcpurple_cmd_call(PurpleConversation *conv, - const char *cmd, char **args, char **error, void *data) -{ - PurpleConnection *gc; - SilcPurple sg; - - gc = purple_conversation_get_gc(conv); - - if (gc == NULL) - return PURPLE_CMD_RET_FAILED; - - sg = gc->proto_data; - - if (sg == NULL) - return PURPLE_CMD_RET_FAILED; - - if (!silc_client_command_call(sg->client, sg->conn, args[0])) { - *error = g_strdup_printf(_("Unknown command: %s"), args[0]); - return PURPLE_CMD_RET_FAILED; - } - - return PURPLE_CMD_RET_OK; -} - - -/************************** Plugin Initialization ****************************/ - -static void -silcpurple_register_commands(void) -{ - purple_cmd_register("part", "w", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | - PURPLE_CMD_FLAG_PRPL_ONLY | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, - "prpl-silc", silcpurple_cmd_chat_part, _("part [channel]: Leave the chat"), NULL); - purple_cmd_register("leave", "w", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | - PURPLE_CMD_FLAG_PRPL_ONLY | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, - "prpl-silc", silcpurple_cmd_chat_part, _("leave [channel]: Leave the chat"), NULL); - purple_cmd_register("topic", "s", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | - PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", - silcpurple_cmd_chat_topic, _("topic [<new topic>]: View or change the topic"), NULL); - purple_cmd_register("join", "ws", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | - PURPLE_CMD_FLAG_PRPL_ONLY | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, - "prpl-silc", silcpurple_cmd_chat_join, - _("join <channel> [<password>]: Join a chat on this network"), NULL); - purple_cmd_register("list", "", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | - PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", - silcpurple_cmd_chat_list, _("list: List channels on this network"), NULL); - purple_cmd_register("whois", "w", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY, - "prpl-silc", - silcpurple_cmd_whois, _("whois <nick>: View nick's information"), NULL); - purple_cmd_register("msg", "ws", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY, - "prpl-silc", silcpurple_cmd_msg, - _("msg <nick> <message>: Send a private message to a user"), NULL); - purple_cmd_register("query", "ws", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | - PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_query, - _("query <nick> [<message>]: Send a private message to a user"), NULL); - purple_cmd_register("motd", "", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | - PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_motd, - _("motd: View the server's Message Of The Day"), NULL); - purple_cmd_register("detach", "", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY, - "prpl-silc", silcpurple_cmd_detach, - _("detach: Detach this session"), NULL); - purple_cmd_register("quit", "s", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | - PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_quit, - _("quit [message]: Disconnect from the server, with an optional message"), NULL); - purple_cmd_register("call", "s", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY, - "prpl-silc", silcpurple_cmd_call, - _("call <command>: Call any silc client command"), NULL); - /* These below just get passed through for the silc client library to deal - * with */ - purple_cmd_register("kill", "ws", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | - PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_generic, - _("kill <nick> [-pubkey|<reason>]: Kill nick"), NULL); - purple_cmd_register("nick", "w", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY, - "prpl-silc", silcpurple_cmd_generic, - _("nick <newnick>: Change your nickname"), NULL); - purple_cmd_register("whowas", "ww", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | - PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_generic, - _("whowas <nick>: View nick's information"), NULL); - purple_cmd_register("cmode", "wws", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | - PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_cmode, - _("cmode <channel> [+|-<modes>] [arguments]: Change or display channel modes"), NULL); - purple_cmd_register("cumode", "wws", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | - PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_generic, - _("cumode <channel> +|-<modes> <nick>: Change nick's modes on channel"), NULL); - purple_cmd_register("umode", "w", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY, - "prpl-silc", silcpurple_cmd_generic, - _("umode <usermodes>: Set your modes in the network"), NULL); - purple_cmd_register("oper", "s", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY, - "prpl-silc", silcpurple_cmd_generic, - _("oper <nick> [-pubkey]: Get server operator privileges"), NULL); - purple_cmd_register("invite", "ws", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | - PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_generic, - _("invite <channel> [-|+]<nick>: invite nick or add/remove from channel invite list"), NULL); - purple_cmd_register("kick", "wws", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | - PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_generic, - _("kick <channel> <nick> [comment]: Kick client from channel"), NULL); - purple_cmd_register("info", "w", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | - PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_generic, - _("info [server]: View server administrative details"), NULL); - purple_cmd_register("ban", "ww", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | - PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_generic, - _("ban [<channel> +|-<nick>]: Ban client from channel"), NULL); - purple_cmd_register("getkey", "w", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY, - "prpl-silc", silcpurple_cmd_generic, - _("getkey <nick|server>: Retrieve client's or server's public key"), NULL); - purple_cmd_register("stats", "", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY, - "prpl-silc", silcpurple_cmd_generic, - _("stats: View server and network statistics"), NULL); - purple_cmd_register("ping", "", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY, - "prpl-silc", silcpurple_cmd_generic, - _("ping: Send PING to the connected server"), NULL); -#if 0 /* Purple doesn't handle these yet */ - purple_cmd_register("users", "w", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY, - "prpl-silc", silcpurple_cmd_users, - _("users <channel>: List users in channel")); - purple_cmd_register("names", "ww", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | - PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_names, - _("names [-count|-ops|-halfops|-voices|-normal] <channel(s)>: List specific users in channel(s)")); -#endif -} - -static PurpleWhiteboardPrplOps silcpurple_wb_ops = -{ - silcpurple_wb_start, - silcpurple_wb_end, - silcpurple_wb_get_dimensions, - silcpurple_wb_set_dimensions, - silcpurple_wb_get_brush, - silcpurple_wb_set_brush, - silcpurple_wb_send, - silcpurple_wb_clear, - - /* padding */ - NULL, - NULL, - NULL, - NULL -}; - -static PurplePluginProtocolInfo prpl_info = -{ -#ifdef HAVE_SILCMIME_H - OPT_PROTO_CHAT_TOPIC | OPT_PROTO_UNIQUE_CHATNAME | - OPT_PROTO_PASSWORD_OPTIONAL | OPT_PROTO_IM_IMAGE | - OPT_PROTO_SLASH_COMMANDS_NATIVE, -#else - OPT_PROTO_CHAT_TOPIC | OPT_PROTO_UNIQUE_CHATNAME | - OPT_PROTO_PASSWORD_OPTIONAL | - OPT_PROTO_SLASH_COMMANDS_NATIVE, -#endif - NULL, /* user_splits */ - NULL, /* protocol_options */ -#ifdef SILC_ATTRIBUTE_USER_ICON - {"jpeg,gif,png,bmp", 0, 0, 96, 96, 0, PURPLE_ICON_SCALE_DISPLAY}, /* icon_spec */ -#else - NO_BUDDY_ICONS, -#endif - silcpurple_list_icon, /* list_icon */ - NULL, /* list_emblems */ - silcpurple_status_text, /* status_text */ - silcpurple_tooltip_text, /* tooltip_text */ - silcpurple_away_states, /* away_states */ - silcpurple_blist_node_menu, /* blist_node_menu */ - silcpurple_chat_info, /* chat_info */ - silcpurple_chat_info_defaults,/* chat_info_defaults */ - silcpurple_login, /* login */ - silcpurple_close, /* close */ - silcpurple_send_im, /* send_im */ - silcpurple_set_info, /* set_info */ - NULL, /* send_typing */ - silcpurple_get_info, /* get_info */ - silcpurple_set_status, /* set_status */ - silcpurple_idle_set, /* set_idle */ - silcpurple_change_passwd, /* change_passwd */ - silcpurple_add_buddy, /* add_buddy */ - NULL, /* add_buddies */ - silcpurple_remove_buddy, /* remove_buddy */ - NULL, /* remove_buddies */ - NULL, /* add_permit */ - NULL, /* add_deny */ - NULL, /* rem_permit */ - NULL, /* rem_deny */ - NULL, /* set_permit_deny */ - silcpurple_chat_join, /* join_chat */ - NULL, /* reject_chat */ - silcpurple_get_chat_name, /* get_chat_name */ - silcpurple_chat_invite, /* chat_invite */ - silcpurple_chat_leave, /* chat_leave */ - NULL, /* chat_whisper */ - silcpurple_chat_send, /* chat_send */ - silcpurple_keepalive, /* keepalive */ - NULL, /* register_user */ - NULL, /* get_cb_info */ - NULL, /* get_cb_away */ - NULL, /* alias_buddy */ - NULL, /* group_buddy */ - NULL, /* rename_group */ - NULL, /* buddy_free */ - NULL, /* convo_closed */ - NULL, /* normalize */ -#ifdef SILC_ATTRIBUTE_USER_ICON - silcpurple_buddy_set_icon, /* set_buddy_icon */ -#else - NULL, -#endif - NULL, /* remove_group */ - NULL, /* get_cb_real_name */ - silcpurple_chat_set_topic, /* set_chat_topic */ - NULL, /* find_blist_chat */ - silcpurple_roomlist_get_list, /* roomlist_get_list */ - silcpurple_roomlist_cancel, /* roomlist_cancel */ - NULL, /* roomlist_expand_category */ - NULL, /* can_receive_file */ - silcpurple_ftp_send_file, /* send_file */ - silcpurple_ftp_new_xfer, /* new_xfer */ - NULL, /* offline_message */ - &silcpurple_wb_ops, /* whiteboard_prpl_ops */ - NULL, /* send_raw */ - NULL, /* roomlist_room_serialize */ - NULL, /* unregister_user */ - NULL, /* send_attention */ - NULL, /* get_attention_types */ - sizeof(PurplePluginProtocolInfo), /* struct_size */ - NULL, /* get_account_text_table */ - NULL, /* initiate_media */ - NULL, /* get_media_caps */ - NULL, /* get_moods */ - NULL, /* set_public_alias */ - NULL, /* get_public_alias */ - NULL, /* add_buddy_with_invite */ - NULL /* add_buddies_with_invite */ -}; - -static PurplePluginInfo info = -{ - PURPLE_PLUGIN_MAGIC, - PURPLE_MAJOR_VERSION, - PURPLE_MINOR_VERSION, - PURPLE_PLUGIN_PROTOCOL, /**< type */ - NULL, /**< ui_requirement */ - 0, /**< flags */ - NULL, /**< dependencies */ - PURPLE_PRIORITY_DEFAULT, /**< priority */ - - "prpl-silc", /**< id */ - "SILC", /**< name */ - "1.0", /**< version */ - /** summary */ - N_("SILC Protocol Plugin"), - /** description */ - N_("Secure Internet Live Conferencing (SILC) Protocol"), - "Pekka Riikonen", /**< author */ - "http://silcnet.org/", /**< homepage */ - - NULL, /**< load */ - NULL, /**< unload */ - NULL, /**< destroy */ - - NULL, /**< ui_info */ - &prpl_info, /**< extra_info */ - NULL, /**< prefs_info */ - silcpurple_actions, - - /* padding */ - NULL, - NULL, - NULL, - NULL -}; - -static void -init_plugin(PurplePlugin *plugin) -{ - PurpleAccountOption *option; - PurpleAccountUserSplit *split; - char tmp[256]; - int i; - PurpleKeyValuePair *kvp; - GList *list = NULL; - - silc_plugin = plugin; - - split = purple_account_user_split_new(_("Network"), "silcnet.org", '@'); - prpl_info.user_splits = g_list_append(prpl_info.user_splits, split); - - /* Account options */ - option = purple_account_option_string_new(_("Connect server"), - "server", - "silc.silcnet.org"); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); - option = purple_account_option_int_new(_("Port"), "port", 706); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); - g_snprintf(tmp, sizeof(tmp), "%s" G_DIR_SEPARATOR_S "public_key.pub", silcpurple_silcdir()); - option = purple_account_option_string_new(_("Public Key file"), - "public-key", tmp); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); - g_snprintf(tmp, sizeof(tmp), "%s" G_DIR_SEPARATOR_S "private_key.prv", silcpurple_silcdir()); - option = purple_account_option_string_new(_("Private Key file"), - "private-key", tmp); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); - - for (i = 0; silc_default_ciphers[i].name; i++) { - kvp = g_new0(PurpleKeyValuePair, 1); - kvp->key = g_strdup(silc_default_ciphers[i].name); - kvp->value = g_strdup(silc_default_ciphers[i].name); - list = g_list_append(list, kvp); - } - option = purple_account_option_list_new(_("Cipher"), "cipher", list); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); - - list = NULL; - for (i = 0; silc_default_hmacs[i].name; i++) { - kvp = g_new0(PurpleKeyValuePair, 1); - kvp->key = g_strdup(silc_default_hmacs[i].name); - kvp->value = g_strdup(silc_default_hmacs[i].name); - list = g_list_append(list, kvp); - } - option = purple_account_option_list_new(_("HMAC"), "hmac", list); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); - - option = purple_account_option_bool_new(_("Public key authentication"), - "pubkey-auth", FALSE); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); - option = purple_account_option_bool_new(_("Block IMs without Key Exchange"), - "block-ims", FALSE); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); - option = purple_account_option_bool_new(_("Block messages to whiteboard"), - "block-wb", FALSE); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); - option = purple_account_option_bool_new(_("Automatically open whiteboard"), - "open-wb", FALSE); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); - option = purple_account_option_bool_new(_("Digitally sign and verify all messages"), - "sign-verify", FALSE); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); - - purple_prefs_remove("/plugins/prpl/silc"); - - silcpurple_register_commands(); - -#ifdef _WIN32 - silc_net_win32_init(); -#endif -} - -PURPLE_INIT_PLUGIN(silc10, init_plugin, info); diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/silc10/silcpurple.h --- a/libpurple/protocols/silc10/silcpurple.h Mon Aug 22 11:20:05 2011 +0900 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,173 +0,0 @@ -/* - - silcpurple.h - - Author: Pekka Riikonen - - Copyright (C) 2004 Pekka Riikonen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - -*/ - -#ifndef SILCPURPLE_H -#define SILCPURPLE_H - -/* Purple includes */ -#include "internal.h" -#include "account.h" -#include "accountopt.h" -#include "cmds.h" -#include "conversation.h" -#include "debug.h" -#include "ft.h" -#include "notify.h" -#include "prpl.h" -#include "request.h" -#include "roomlist.h" -#include "server.h" -#include "util.h" - -/* Default public and private key file names */ -#define SILCPURPLE_PUBLIC_KEY_NAME "public_key.pub" -#define SILCPURPLE_PRIVATE_KEY_NAME "private_key.prv" - -/* Default settings for creating key pair */ -#define SILCPURPLE_DEF_PKCS "rsa" -#define SILCPURPLE_DEF_PKCS_LEN 2048 - -#define SILCPURPLE_PRVGRP 0x001fffff - -/* Status IDs */ -#define SILCPURPLE_STATUS_ID_OFFLINE "offline" -#define SILCPURPLE_STATUS_ID_AVAILABLE "available" -#define SILCPURPLE_STATUS_ID_HYPER "hyper" -#define SILCPURPLE_STATUS_ID_AWAY "away" -#define SILCPURPLE_STATUS_ID_BUSY "busy" -#define SILCPURPLE_STATUS_ID_INDISPOSED "indisposed" -#define SILCPURPLE_STATUS_ID_PAGE "page" - -typedef struct { - unsigned long id; - const char *channel; - unsigned long chid; - const char *parentch; - SilcChannelPrivateKey key; -} *SilcPurplePrvgrp; - -/* The SILC Purple plugin context */ -typedef struct SilcPurpleStruct { - SilcClient client; - SilcClientConnection conn; - - guint scheduler; - PurpleConnection *gc; - PurpleAccount *account; - unsigned long channel_ids; - GList *grps; - - char *motd; - PurpleRoomlist *roomlist; -#ifdef HAVE_SILCMIME_H - SilcMimeAssembler mimeass; -#endif - unsigned int detaching : 1; - unsigned int resuming : 1; - unsigned int roomlist_cancelled : 1; - unsigned int chpk : 1; -} *SilcPurple; - - -gboolean silcpurple_check_silc_dir(PurpleConnection *gc); -void silcpurple_chat_join_done(SilcClient client, - SilcClientConnection conn, - SilcClientEntry *clients, - SilcUInt32 clients_count, - void *context); -const char *silcpurple_silcdir(void); -const char *silcpurple_session_file(const char *account); -void silcpurple_verify_public_key(SilcClient client, SilcClientConnection conn, - const char *name, SilcSocketType conn_type, - unsigned char *pk, SilcUInt32 pk_len, - SilcSKEPKType pk_type, - SilcVerifyPublicKey completion, void *context); -GList *silcpurple_buddy_menu(PurpleBuddy *buddy); -void silcpurple_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group); -void silcpurple_send_buddylist(PurpleConnection *gc); -void silcpurple_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group); -void silcpurple_buddy_keyagr_request(SilcClient client, - SilcClientConnection conn, - SilcClientEntry client_entry, - const char *hostname, SilcUInt16 port); -void silcpurple_idle_set(PurpleConnection *gc, int idle); -void silcpurple_tooltip_text(PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboolean full); -char *silcpurple_status_text(PurpleBuddy *b); -gboolean silcpurple_ip_is_private(const char *ip); -void silcpurple_ftp_send_file(PurpleConnection *gc, const char *name, const char *file); -PurpleXfer *silcpurple_ftp_new_xfer(PurpleConnection *gc, const char *name); -void silcpurple_ftp_request(SilcClient client, SilcClientConnection conn, - SilcClientEntry client_entry, SilcUInt32 session_id, - const char *hostname, SilcUInt16 port); -void silcpurple_show_public_key(SilcPurple sg, - const char *name, SilcPublicKey public_key, - GCallback callback, void *context); -void silcpurple_get_info(PurpleConnection *gc, const char *who); -SilcAttributePayload -silcpurple_get_attr(SilcDList attrs, SilcAttribute attribute); -void silcpurple_get_umode_string(SilcUInt32 mode, char *buf, - SilcUInt32 buf_size); -void silcpurple_get_chmode_string(SilcUInt32 mode, char *buf, - SilcUInt32 buf_size); -void silcpurple_get_chumode_string(SilcUInt32 mode, char *buf, - SilcUInt32 buf_size); -GList *silcpurple_chat_info(PurpleConnection *gc); -GHashTable *silcpurple_chat_info_defaults(PurpleConnection *gc, const char *chat_name); -GList *silcpurple_chat_menu(PurpleChat *); -void silcpurple_chat_join(PurpleConnection *gc, GHashTable *data); -char *silcpurple_get_chat_name(GHashTable *data); -void silcpurple_chat_invite(PurpleConnection *gc, int id, const char *msg, - const char *name); -void silcpurple_chat_leave(PurpleConnection *gc, int id); -int silcpurple_chat_send(PurpleConnection *gc, int id, const char *msg, PurpleMessageFlags flags); -void silcpurple_chat_set_topic(PurpleConnection *gc, int id, const char *topic); -PurpleRoomlist *silcpurple_roomlist_get_list(PurpleConnection *gc); -void silcpurple_roomlist_cancel(PurpleRoomlist *list); -void silcpurple_chat_chauth_show(SilcPurple sg, SilcChannelEntry channel, - SilcBuffer channel_pubkeys); -void silcpurple_parse_attrs(SilcDList attrs, char **moodstr, char **statusstr, - char **contactstr, char **langstr, char **devicestr, - char **tzstr, char **geostr); -#ifdef SILC_ATTRIBUTE_USER_ICON -void silcpurple_buddy_set_icon(PurpleConnection *gc, PurpleStoredImage *img); -#endif -#ifdef HAVE_SILCMIME_H -char *silcpurple_file2mime(const char *filename); -SilcDList silcpurple_image_message(const char *msg, SilcUInt32 *mflags); -#endif - -#ifdef _WIN32 -typedef int uid_t; - -struct passwd { - char *pw_name; /* user name */ - char *pw_passwd; /* user password */ - int pw_uid; /* user id */ - int pw_gid; /* group id */ - char *pw_gecos; /* real name */ - char *pw_dir; /* home directory */ - char *pw_shell; /* shell program */ -}; - -struct passwd *getpwuid(int uid); -int getuid(void); -int geteuid(void); -#endif - -#endif /* SILCPURPLE_H */ diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/silc10/util.c --- a/libpurple/protocols/silc10/util.c Mon Aug 22 11:20:05 2011 +0900 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,776 +0,0 @@ -/* - - silcpurple_util.c - - Author: Pekka Riikonen - - Copyright (C) 2004 - 2005 Pekka Riikonen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - -*/ - -#include "silcincludes.h" -#include "silcclient.h" -#include "silcpurple.h" -#include "imgstore.h" - -/**************************** Utility Routines *******************************/ - -static char str[256], str2[256]; - -const char *silcpurple_silcdir(void) -{ - const char *hd = purple_home_dir(); - memset(str, 0, sizeof(str)); - g_snprintf(str, sizeof(str) - 1, "%s" G_DIR_SEPARATOR_S ".silc", hd ? hd : "/tmp"); - return (const char *)str; -} - -const char *silcpurple_session_file(const char *account) -{ - memset(str2, 0, sizeof(str2)); - g_snprintf(str2, sizeof(str2) - 1, "%s" G_DIR_SEPARATOR_S "%s_session", - silcpurple_silcdir(), account); - return (const char *)str2; -} - -gboolean silcpurple_ip_is_private(const char *ip) -{ - if (silc_net_is_ip4(ip)) { - if (!strncmp(ip, "10.", 3)) { - return TRUE; - } else if (!strncmp(ip, "172.", 4) && strlen(ip) > 6) { - char tmp[3]; - int s; - memset(tmp, 0, sizeof(tmp)); - strncpy(tmp, ip + 4, 2); - s = atoi(tmp); - if (s >= 16 && s <= 31) - return TRUE; - } else if (!strncmp(ip, "192.168.", 8)) { - return TRUE; - } - } - - return FALSE; -} - -/* This checks stats for various SILC files and directories. First it - checks if ~/.silc directory exist and is owned by the correct user. If - it doesn't exist, it will create the directory. After that it checks if - user's Public and Private key files exists and creates them if needed. */ - -gboolean silcpurple_check_silc_dir(PurpleConnection *gc) -{ - char filename[256], file_public_key[256], file_private_key[256]; - char servfilename[256], clientfilename[256], friendsfilename[256]; - char pkd[256], prd[256]; - struct stat st; - struct passwd *pw; - int fd; - - pw = getpwuid(getuid()); - if (!pw) { - purple_debug_error("silc", "silc: %s\n", g_strerror(errno)); - return FALSE; - } - - g_snprintf(filename, sizeof(filename) - 1, "%s", silcpurple_silcdir()); - g_snprintf(servfilename, sizeof(servfilename) - 1, "%s" G_DIR_SEPARATOR_S "serverkeys", - silcpurple_silcdir()); - g_snprintf(clientfilename, sizeof(clientfilename) - 1, "%s" G_DIR_SEPARATOR_S "clientkeys", - silcpurple_silcdir()); - g_snprintf(friendsfilename, sizeof(friendsfilename) - 1, "%s" G_DIR_SEPARATOR_S "friends", - silcpurple_silcdir()); - - /* - * Check ~/.silc directory - */ - if ((g_stat(filename, &st)) == -1) { - /* If dir doesn't exist */ - if (errno == ENOENT) { - if (pw->pw_uid == geteuid()) { - if ((g_mkdir(filename, 0755)) == -1) { - purple_debug_error("silc", "Couldn't create '%s' directory\n", filename); - return FALSE; - } - } else { - purple_debug_error("silc", "Couldn't create '%s' directory due to a wrong uid!\n", - filename); - return FALSE; - } - } else { - purple_debug_error("silc", "Couldn't stat '%s' directory, error: %s\n", filename, g_strerror(errno)); - return FALSE; - } - } else { -#ifndef _WIN32 - /* Check the owner of the dir */ - if (st.st_uid != 0 && st.st_uid != pw->pw_uid) { - purple_debug_error("silc", "You don't seem to own '%s' directory\n", - filename); - return FALSE; - } -#endif - } - - /* - * Check ~./silc/serverkeys directory - */ - if ((g_stat(servfilename, &st)) == -1) { - /* If dir doesn't exist */ - if (errno == ENOENT) { - if (pw->pw_uid == geteuid()) { - if ((g_mkdir(servfilename, 0755)) == -1) { - purple_debug_error("silc", "Couldn't create '%s' directory\n", servfilename); - return FALSE; - } - } else { - purple_debug_error("silc", "Couldn't create '%s' directory due to a wrong uid!\n", - servfilename); - return FALSE; - } - } else { - purple_debug_error("silc", "Couldn't stat '%s' directory, error: %s\n", - servfilename, g_strerror(errno)); - return FALSE; - } - } - - /* - * Check ~./silc/clientkeys directory - */ - if ((g_stat(clientfilename, &st)) == -1) { - /* If dir doesn't exist */ - if (errno == ENOENT) { - if (pw->pw_uid == geteuid()) { - if ((g_mkdir(clientfilename, 0755)) == -1) { - purple_debug_error("silc", "Couldn't create '%s' directory\n", clientfilename); - return FALSE; - } - } else { - purple_debug_error("silc", "Couldn't create '%s' directory due to a wrong uid!\n", - clientfilename); - return FALSE; - } - } else { - purple_debug_error("silc", "Couldn't stat '%s' directory, error: %s\n", - clientfilename, g_strerror(errno)); - return FALSE; - } - } - - /* - * Check ~./silc/friends directory - */ - if ((g_stat(friendsfilename, &st)) == -1) { - /* If dir doesn't exist */ - if (errno == ENOENT) { - if (pw->pw_uid == geteuid()) { - if ((g_mkdir(friendsfilename, 0755)) == -1) { - purple_debug_error("silc", "Couldn't create '%s' directory\n", friendsfilename); - return FALSE; - } - } else { - purple_debug_error("silc", "Couldn't create '%s' directory due to a wrong uid!\n", - friendsfilename); - return FALSE; - } - } else { - purple_debug_error("silc", "Couldn't stat '%s' directory, error: %s\n", - friendsfilename, g_strerror(errno)); - return FALSE; - } - } - - /* - * Check Public and Private keys - */ - g_snprintf(pkd, sizeof(pkd), "%s" G_DIR_SEPARATOR_S "public_key.pub", silcpurple_silcdir()); - g_snprintf(prd, sizeof(prd), "%s" G_DIR_SEPARATOR_S "private_key.prv", silcpurple_silcdir()); - g_snprintf(file_public_key, sizeof(file_public_key) - 1, "%s", - purple_account_get_string(gc->account, "public-key", pkd)); - g_snprintf(file_private_key, sizeof(file_public_key) - 1, "%s", - purple_account_get_string(gc->account, "private-key", prd)); - - if ((g_stat(file_public_key, &st)) == -1) { - /* If file doesn't exist */ - if (errno == ENOENT) { - purple_connection_update_progress(gc, _("Creating SILC key pair..."), 1, 5); - if (!silc_create_key_pair(SILCPURPLE_DEF_PKCS, - SILCPURPLE_DEF_PKCS_LEN, - file_public_key, file_private_key, NULL, - (gc->password == NULL) ? "" : gc->password, - NULL, NULL, NULL, FALSE)) { - purple_debug_error("silc", "Couldn't create key pair\n"); - return FALSE; - } - - if ((g_stat(file_public_key, &st)) == -1) { - purple_debug_error("silc", "Couldn't stat '%s' public key, error: %s\n", - file_public_key, g_strerror(errno)); - return FALSE; - } - } else { - purple_debug_error("silc", "Couldn't stat '%s' public key, error: %s\n", - file_public_key, g_strerror(errno)); - return FALSE; - } - } - -#ifndef _WIN32 - /* Check the owner of the public key */ - if (st.st_uid != 0 && st.st_uid != pw->pw_uid) { - purple_debug_error("silc", "You don't seem to own your public key!?\n"); - return FALSE; - } -#endif - - if ((fd = g_open(file_private_key, O_RDONLY, 0)) != -1) { - if ((fstat(fd, &st)) == -1) { - purple_debug_error("silc", "Couldn't stat '%s' private key, error: %s\n", - file_private_key, g_strerror(errno)); - close(fd); - return FALSE; - } - } else if ((g_stat(file_private_key, &st)) == -1) { - /* If file doesn't exist */ - if (errno == ENOENT) { - purple_connection_update_progress(gc, _("Creating SILC key pair..."), 1, 5); - if (!silc_create_key_pair(SILCPURPLE_DEF_PKCS, - SILCPURPLE_DEF_PKCS_LEN, - file_public_key, file_private_key, NULL, - (gc->password == NULL) ? "" : gc->password, - NULL, NULL, NULL, FALSE)) { - purple_debug_error("silc", "Couldn't create key pair\n"); - return FALSE; - } - - if ((fd = g_open(file_private_key, O_RDONLY, 0)) != -1) { - if ((fstat(fd, &st)) == -1) { - purple_debug_error("silc", "Couldn't stat '%s' private key, error: %s\n", - file_private_key, g_strerror(errno)); - close(fd); - return FALSE; - } - } - /* This shouldn't really happen because silc_create_key_pair() - * will set the permissions */ - else if ((g_stat(file_private_key, &st)) == -1) { - purple_debug_error("silc", "Couldn't stat '%s' private key, error: %s\n", - file_private_key, g_strerror(errno)); - return FALSE; - } - } else { - purple_debug_error("silc", "Couldn't stat '%s' private key, error: %s\n", - file_private_key, g_strerror(errno)); - return FALSE; - } - } - -#ifndef _WIN32 - /* Check the owner of the private key */ - if (st.st_uid != 0 && st.st_uid != pw->pw_uid) { - purple_debug_error("silc", "You don't seem to own your private key!?\n"); - if (fd != -1) - close(fd); - return FALSE; - } - - /* Check the permissions for the private key */ - if ((st.st_mode & 0777) != 0600) { - purple_debug_warning("silc", "Wrong permissions in your private key file `%s'!\n" - "Trying to change them ...\n", file_private_key); - if ((fd == -1) || (fchmod(fd, S_IRUSR | S_IWUSR)) == -1) { - purple_debug_error("silc", - "Failed to change permissions for private key file!\n" - "Permissions for your private key file must be 0600.\n"); - if (fd != -1) - close(fd); - return FALSE; - } - purple_debug_warning("silc", "Done.\n\n"); - } -#endif - - if (fd != -1) - close(fd); - - return TRUE; -} - -#ifdef _WIN32 -struct passwd *getpwuid(uid_t uid) { - struct passwd *pwd = calloc(1, sizeof(struct passwd)); - return pwd; -} - -uid_t getuid() { - return 0; -} - -uid_t geteuid() { - return 0; -} -#endif - -void silcpurple_show_public_key(SilcPurple sg, - const char *name, SilcPublicKey public_key, - GCallback callback, void *context) -{ - SilcPublicKeyIdentifier ident; - SilcPKCS pkcs; - char *fingerprint, *babbleprint; - unsigned char *pk; - SilcUInt32 pk_len, key_len = 0; - GString *s; - char *buf; - - ident = silc_pkcs_decode_identifier(public_key->identifier); - if (!ident) - return; - - pk = silc_pkcs_public_key_encode(public_key, &pk_len); - fingerprint = silc_hash_fingerprint(NULL, pk, pk_len); - babbleprint = silc_hash_babbleprint(NULL, pk, pk_len); - - if (silc_pkcs_alloc((unsigned char *)public_key->name, &pkcs)) { - key_len = silc_pkcs_public_key_set(pkcs, public_key); - silc_pkcs_free(pkcs); - } - - s = g_string_new(""); - if (ident->realname) - /* Hint for translators: Please check the tabulator width here and in - the next strings (short strings: 2 tabs, longer strings 1 tab, - sum: 3 tabs or 24 characters) */ - g_string_append_printf(s, _("Real Name: \t%s\n"), ident->realname); - if (ident->username) - g_string_append_printf(s, _("User Name: \t%s\n"), ident->username); - if (ident->email) - g_string_append_printf(s, _("Email: \t\t%s\n"), ident->email); - if (ident->host) - g_string_append_printf(s, _("Host Name: \t%s\n"), ident->host); - if (ident->org) - g_string_append_printf(s, _("Organization: \t%s\n"), ident->org); - if (ident->country) - g_string_append_printf(s, _("Country: \t%s\n"), ident->country); - g_string_append_printf(s, _("Algorithm: \t%s\n"), public_key->name); - g_string_append_printf(s, _("Key Length: \t%d bits\n"), (int)key_len); - g_string_append_printf(s, "\n"); - g_string_append_printf(s, _("Public Key Fingerprint:\n%s\n\n"), fingerprint); - g_string_append_printf(s, _("Public Key Babbleprint:\n%s"), babbleprint); - - buf = g_string_free(s, FALSE); - - purple_request_action(sg->gc, _("Public Key Information"), - _("Public Key Information"), - buf, 0, purple_connection_get_account(sg->gc), - NULL, NULL, context, 1, _("Close"), callback); - - g_free(buf); - silc_free(fingerprint); - silc_free(babbleprint); - silc_free(pk); - silc_pkcs_free_identifier(ident); -} - -SilcAttributePayload -silcpurple_get_attr(SilcDList attrs, SilcAttribute attribute) -{ - SilcAttributePayload attr = NULL; - - if (!attrs) - return NULL; - - silc_dlist_start(attrs); - while ((attr = silc_dlist_get(attrs)) != SILC_LIST_END) - if (attribute == silc_attribute_get_attribute(attr)) - break; - - return attr; -} - -void silcpurple_get_umode_string(SilcUInt32 mode, char *buf, - SilcUInt32 buf_size) -{ - memset(buf, 0, buf_size); - if ((mode & SILC_UMODE_SERVER_OPERATOR) || - (mode & SILC_UMODE_ROUTER_OPERATOR)) { - strcat(buf, (mode & SILC_UMODE_SERVER_OPERATOR) ? - "[server operator] " : - (mode & SILC_UMODE_ROUTER_OPERATOR) ? - "[SILC operator] " : "[unknown mode] "); - } - if (mode & SILC_UMODE_GONE) - strcat(buf, "[away] "); - if (mode & SILC_UMODE_INDISPOSED) - strcat(buf, "[indisposed] "); - if (mode & SILC_UMODE_BUSY) - strcat(buf, "[busy] "); - if (mode & SILC_UMODE_PAGE) - strcat(buf, "[wake me up] "); - if (mode & SILC_UMODE_HYPER) - strcat(buf, "[hyperactive] "); - if (mode & SILC_UMODE_ROBOT) - strcat(buf, "[robot] "); - if (mode & SILC_UMODE_ANONYMOUS) - strcat(buf, "[anonymous] "); - if (mode & SILC_UMODE_BLOCK_PRIVMSG) - strcat(buf, "[blocks private messages] "); - if (mode & SILC_UMODE_DETACHED) - strcat(buf, "[detached] "); - if (mode & SILC_UMODE_REJECT_WATCHING) - strcat(buf, "[rejects watching] "); - if (mode & SILC_UMODE_BLOCK_INVITE) - strcat(buf, "[blocks invites] "); - g_strchomp(buf); -} - -void silcpurple_get_chmode_string(SilcUInt32 mode, char *buf, - SilcUInt32 buf_size) -{ - memset(buf, 0, buf_size); - if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) - strcat(buf, "[permanent] "); - if (mode & SILC_CHANNEL_MODE_PRIVATE) - strcat(buf, "[private] "); - if (mode & SILC_CHANNEL_MODE_SECRET) - strcat(buf, "[secret] "); - if (mode & SILC_CHANNEL_MODE_PRIVKEY) - strcat(buf, "[private key] "); - if (mode & SILC_CHANNEL_MODE_INVITE) - strcat(buf, "[invite only] "); - if (mode & SILC_CHANNEL_MODE_TOPIC) - strcat(buf, "[topic restricted] "); - if (mode & SILC_CHANNEL_MODE_ULIMIT) - strcat(buf, "[user count limit] "); - if (mode & SILC_CHANNEL_MODE_PASSPHRASE) - strcat(buf, "[passphrase auth] "); - if (mode & SILC_CHANNEL_MODE_CHANNEL_AUTH) - strcat(buf, "[public key auth] "); - if (mode & SILC_CHANNEL_MODE_SILENCE_USERS) - strcat(buf, "[users silenced] "); - if (mode & SILC_CHANNEL_MODE_SILENCE_OPERS) - strcat(buf, "[operators silenced] "); - g_strchomp(buf); -} - -void silcpurple_get_chumode_string(SilcUInt32 mode, char *buf, - SilcUInt32 buf_size) -{ - memset(buf, 0, buf_size); - if (mode & SILC_CHANNEL_UMODE_CHANFO) - strcat(buf, "[founder] "); - if (mode & SILC_CHANNEL_UMODE_CHANOP) - strcat(buf, "[operator] "); - if (mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) - strcat(buf, "[blocks messages] "); - if (mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) - strcat(buf, "[blocks user messages] "); - if (mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) - strcat(buf, "[blocks robot messages] "); - if (mode & SILC_CHANNEL_UMODE_QUIET) - strcat(buf, "[quieted] "); - g_strchomp(buf); -} - -void -silcpurple_parse_attrs(SilcDList attrs, char **moodstr, char **statusstr, - char **contactstr, char **langstr, char **devicestr, - char **tzstr, char **geostr) -{ - SilcAttributePayload attr; - SilcAttributeMood mood = 0; - SilcAttributeContact contact; - SilcAttributeObjDevice device; - SilcAttributeObjGeo geo; - - char tmp[1024]; - GString *s; - - *moodstr = NULL; - *statusstr = NULL; - *contactstr = NULL; - *langstr = NULL; - *devicestr = NULL; - *tzstr = NULL; - *geostr = NULL; - - if (!attrs) - return; - - s = g_string_new(""); - attr = silcpurple_get_attr(attrs, SILC_ATTRIBUTE_STATUS_MOOD); - if (attr && silc_attribute_get_object(attr, &mood, sizeof(mood))) { - if (mood & SILC_ATTRIBUTE_MOOD_HAPPY) - g_string_append_printf(s, "[%s] ", _("Happy")); - if (mood & SILC_ATTRIBUTE_MOOD_SAD) - g_string_append_printf(s, "[%s] ", _("Sad")); - if (mood & SILC_ATTRIBUTE_MOOD_ANGRY) - g_string_append_printf(s, "[%s] ", _("Angry")); - if (mood & SILC_ATTRIBUTE_MOOD_JEALOUS) - g_string_append_printf(s, "[%s] ", _("Jealous")); - if (mood & SILC_ATTRIBUTE_MOOD_ASHAMED) - g_string_append_printf(s, "[%s] ", _("Ashamed")); - if (mood & SILC_ATTRIBUTE_MOOD_INVINCIBLE) - g_string_append_printf(s, "[%s] ", _("Invincible")); - if (mood & SILC_ATTRIBUTE_MOOD_INLOVE) - g_string_append_printf(s, "[%s] ", _("In Love")); - if (mood & SILC_ATTRIBUTE_MOOD_SLEEPY) - g_string_append_printf(s, "[%s] ", _("Sleepy")); - if (mood & SILC_ATTRIBUTE_MOOD_BORED) - g_string_append_printf(s, "[%s] ", _("Bored")); - if (mood & SILC_ATTRIBUTE_MOOD_EXCITED) - g_string_append_printf(s, "[%s] ", _("Excited")); - if (mood & SILC_ATTRIBUTE_MOOD_ANXIOUS) - g_string_append_printf(s, "[%s] ", _("Anxious")); - } - if (strlen(s->str)) { - *moodstr = s->str; - g_string_free(s, FALSE); - g_strchomp(*moodstr); - } else - g_string_free(s, TRUE); - - attr = silcpurple_get_attr(attrs, SILC_ATTRIBUTE_STATUS_FREETEXT); - memset(tmp, 0, sizeof(tmp)); - if (attr && silc_attribute_get_object(attr, tmp, sizeof(tmp))) - *statusstr = g_strdup(tmp); - - s = g_string_new(""); - attr = silcpurple_get_attr(attrs, SILC_ATTRIBUTE_PREFERRED_CONTACT); - if (attr && silc_attribute_get_object(attr, &contact, sizeof(contact))) { - if (contact & SILC_ATTRIBUTE_CONTACT_CHAT) - g_string_append_printf(s, "[%s] ", _("Chat")); - if (contact & SILC_ATTRIBUTE_CONTACT_EMAIL) - g_string_append_printf(s, "[%s] ", _("Email")); - if (contact & SILC_ATTRIBUTE_CONTACT_CALL) - g_string_append_printf(s, "[%s] ", _("Phone")); - if (contact & SILC_ATTRIBUTE_CONTACT_PAGE) - g_string_append_printf(s, "[%s] ", _("Paging")); - if (contact & SILC_ATTRIBUTE_CONTACT_SMS) - g_string_append_printf(s, "[%s] ", _("SMS")); - if (contact & SILC_ATTRIBUTE_CONTACT_MMS) - g_string_append_printf(s, "[%s] ", _("MMS")); - if (contact & SILC_ATTRIBUTE_CONTACT_VIDEO) - g_string_append_printf(s, "[%s] ", _("Video Conferencing")); - } - if (strlen(s->str)) { - *contactstr = s->str; - g_string_free(s, FALSE); - g_strchomp(*contactstr); - } else - g_string_free(s, TRUE); - - attr = silcpurple_get_attr(attrs, SILC_ATTRIBUTE_PREFERRED_LANGUAGE); - memset(tmp, 0, sizeof(tmp)); - if (attr && silc_attribute_get_object(attr, tmp, sizeof(tmp))) - *langstr = g_strdup(tmp); - - s = g_string_new(""); - attr = silcpurple_get_attr(attrs, SILC_ATTRIBUTE_DEVICE_INFO); - memset(&device, 0, sizeof(device)); - if (attr && silc_attribute_get_object(attr, &device, sizeof(device))) { - if (device.type == SILC_ATTRIBUTE_DEVICE_COMPUTER) - g_string_append_printf(s, "%s: ", _("Computer")); - if (device.type == SILC_ATTRIBUTE_DEVICE_MOBILE_PHONE) - g_string_append_printf(s, "%s: ", _("Mobile Phone")); - if (device.type == SILC_ATTRIBUTE_DEVICE_PDA) - g_string_append_printf(s, "%s: ", _("PDA")); - if (device.type == SILC_ATTRIBUTE_DEVICE_TERMINAL) - g_string_append_printf(s, "%s: ", _("Terminal")); - g_string_append_printf(s, "%s %s %s %s", - device.manufacturer ? device.manufacturer : "", - device.version ? device.version : "", - device.model ? device.model : "", - device.language ? device.language : ""); - } - if (strlen(s->str)) { - *devicestr = s->str; - g_string_free(s, FALSE); - } else - g_string_free(s, TRUE); - - attr = silcpurple_get_attr(attrs, SILC_ATTRIBUTE_TIMEZONE); - memset(tmp, 0, sizeof(tmp)); - if (attr && silc_attribute_get_object(attr, tmp, sizeof(tmp))) - *tzstr = g_strdup(tmp); - - attr = silcpurple_get_attr(attrs, SILC_ATTRIBUTE_GEOLOCATION); - memset(&geo, 0, sizeof(geo)); - if (attr && silc_attribute_get_object(attr, &geo, sizeof(geo))) - *geostr = g_strdup_printf("%s %s %s (%s)", - geo.longitude ? geo.longitude : "", - geo.latitude ? geo.latitude : "", - geo.altitude ? geo.altitude : "", - geo.accuracy ? geo.accuracy : ""); -} - -#ifdef HAVE_SILCMIME_H -/* Returns MIME type of filetype */ - -char *silcpurple_file2mime(const char *filename) -{ - const char *ct; - - ct = strrchr(filename, '.'); - if (!ct) - return NULL; - else if (!g_ascii_strcasecmp(".png", ct)) - return strdup("image/png"); - else if (!g_ascii_strcasecmp(".jpg", ct)) - return strdup("image/jpeg"); - else if (!g_ascii_strcasecmp(".jpeg", ct)) - return strdup("image/jpeg"); - else if (!g_ascii_strcasecmp(".gif", ct)) - return strdup("image/gif"); - else if (!g_ascii_strcasecmp(".tiff", ct)) - return strdup("image/tiff"); - - return NULL; -} - -/* Checks if message has images, and assembles MIME message if it has. - If only one image is present, creates simple MIME image message. If - there are multiple images and/or text with images multipart MIME - message is created. */ - -SilcDList silcpurple_image_message(const char *msg, SilcUInt32 *mflags) -{ - SilcMime mime = NULL, p; - SilcDList list, parts = NULL; - const char *start, *end, *last; - GData *attribs; - char *type; - gboolean images = FALSE; - - last = msg; - while (last && *last && purple_markup_find_tag("img", last, &start, - &end, &attribs)) { - PurpleStoredImage *image = NULL; - const char *id; - - /* Check if there is text before image */ - if (start - last) { - char *text, *tmp; - p = silc_mime_alloc(); - - /* Add content type */ - silc_mime_add_field(p, "Content-Type", - "text/plain; charset=utf-8"); - - tmp = g_strndup(last, start - last); - text = purple_unescape_html(tmp); - g_free(tmp); - /* Add text */ - silc_mime_add_data(p, (unsigned char *)text, strlen(text)); - g_free(text); - - if (!parts) - parts = silc_dlist_init(); - silc_dlist_add(parts, p); - } - - id = g_datalist_get_data(&attribs, "id"); - if (id && (image = purple_imgstore_find_by_id(atoi(id)))) { - unsigned long imglen = purple_imgstore_get_size(image); - gconstpointer img = purple_imgstore_get_data(image); - - p = silc_mime_alloc(); - - /* Add content type */ - type = silcpurple_file2mime(purple_imgstore_get_filename(image)); - if (!type) { - g_datalist_clear(&attribs); - last = end + 1; - continue; - } - silc_mime_add_field(p, "Content-Type", type); - silc_free(type); - - /* Add content transfer encoding */ - silc_mime_add_field(p, "Content-Transfer-Encoding", "binary"); - - /* Add image data */ - silc_mime_add_data(p, img, imglen); - - if (!parts) - parts = silc_dlist_init(); - silc_dlist_add(parts, p); - images = TRUE; - } - - g_datalist_clear(&attribs); - - /* Continue after tag */ - last = end + 1; - } - - /* Check for text after the image(s) */ - if (images && last && *last) { - char *tmp = purple_unescape_html(last); - p = silc_mime_alloc(); - - /* Add content type */ - silc_mime_add_field(p, "Content-Type", - "text/plain; charset=utf-8"); - - /* Add text */ - silc_mime_add_data(p, (unsigned char *)tmp, strlen(tmp)); - g_free(tmp); - - if (!parts) - parts = silc_dlist_init(); - silc_dlist_add(parts, p); - } - - /* If there weren't any images, don't return anything. */ - if (!images) { - if (parts) - silc_dlist_uninit(parts); - return NULL; - } - - if (silc_dlist_count(parts) > 1) { - /* Multipart MIME message */ - char b[32]; - mime = silc_mime_alloc(); - silc_mime_add_field(mime, "MIME-Version", "1.0"); - g_snprintf(b, sizeof(b), "b%4X%4X", - (unsigned int)time(NULL), - silc_dlist_count(parts)); - silc_mime_set_multipart(mime, "mixed", b); - silc_dlist_start(parts); - while ((p = silc_dlist_get(parts)) != SILC_LIST_END) - silc_mime_add_multipart(mime, p); - } else { - /* Simple MIME message */ - silc_dlist_start(parts); - mime = silc_dlist_get(parts); - silc_mime_add_field(mime, "MIME-Version", "1.0"); - } - - *mflags &= ~SILC_MESSAGE_FLAG_UTF8; - *mflags |= SILC_MESSAGE_FLAG_DATA; - - /* Encode message. Fragment if it is too large */ - list = silc_mime_encode_partial(mime, 0xfc00); - - silc_dlist_uninit(parts); - - /* Added multiparts gets freed here */ - silc_mime_free(mime); - - return list; -} - -#endif /* HAVE_SILCMIME_H */ diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/silc10/wb.c --- a/libpurple/protocols/silc10/wb.c Mon Aug 22 11:20:05 2011 +0900 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,520 +0,0 @@ -/* - - wb.c - - Author: Pekka Riikonen - - Copyright (C) 2005 Pekka Riikonen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - -*/ - -#include "silcincludes.h" -#include "silcclient.h" -#include "silcpurple.h" -#include "wb.h" - -/* - SILC Whiteboard packet: - - 1 byte command - 2 bytes width - 2 bytes height - 4 bytes brush color - 2 bytes brush size - n bytes data - - Data: - - 4 bytes x - 4 bytes y - - Commands: - - 0x01 draw - 0x02 clear - - MIME: - - MIME-Version: 1.0 - Content-Type: application/x-wb - Content-Transfer-Encoding: binary - -*/ - -#define SILCPURPLE_WB_MIME "MIME-Version: 1.0\r\nContent-Type: application/x-wb\r\nContent-Transfer-Encoding: binary\r\n\r\n" -#define SILCPURPLE_WB_HEADER strlen(SILCPURPLE_WB_MIME) + 11 - -#define SILCPURPLE_WB_WIDTH 500 -#define SILCPURPLE_WB_HEIGHT 400 -#define SILCPURPLE_WB_WIDTH_MAX 1024 -#define SILCPURPLE_WB_HEIGHT_MAX 1024 - -/* Commands */ -typedef enum { - SILCPURPLE_WB_DRAW = 0x01, - SILCPURPLE_WB_CLEAR = 0x02 -} SilcPurpleWbCommand; - -/* Brush size */ -typedef enum { - SILCPURPLE_WB_BRUSH_SMALL = 2, - SILCPURPLE_WB_BRUSH_MEDIUM = 5, - SILCPURPLE_WB_BRUSH_LARGE = 10 -} SilcPurpleWbBrushSize; - -/* Brush color (XXX Purple should provide default colors) */ -typedef enum { - SILCPURPLE_WB_COLOR_BLACK = 0, - SILCPURPLE_WB_COLOR_RED = 13369344, - SILCPURPLE_WB_COLOR_GREEN = 52224, - SILCPURPLE_WB_COLOR_BLUE = 204, - SILCPURPLE_WB_COLOR_YELLOW = 15658496, - SILCPURPLE_WB_COLOR_ORANGE = 16737792, - SILCPURPLE_WB_COLOR_CYAN = 52428, - SILCPURPLE_WB_COLOR_VIOLET = 5381277, - SILCPURPLE_WB_COLOR_PURPLE = 13369548, - SILCPURPLE_WB_COLOR_TAN = 12093547, - SILCPURPLE_WB_COLOR_BROWN = 5256485, - SILCPURPLE_WB_COLOR_GREY = 11184810, - SILCPURPLE_WB_COLOR_WHITE = 16777215 -} SilcPurpleWbColor; - -typedef struct { - int type; /* 0 = buddy, 1 = channel */ - union { - SilcClientEntry client; - SilcChannelEntry channel; - } u; - int width; - int height; - int brush_size; - int brush_color; -} *SilcPurpleWb; - -/* Initialize whiteboard */ - -PurpleWhiteboard *silcpurple_wb_init(SilcPurple sg, SilcClientEntry client_entry) -{ - SilcClientConnection conn; - PurpleWhiteboard *wb; - SilcPurpleWb wbs; - - conn = sg->conn; - wb = purple_whiteboard_get_session(sg->account, client_entry->nickname); - if (!wb) - wb = purple_whiteboard_create(sg->account, client_entry->nickname, 0); - if (!wb) - return NULL; - - if (!wb->proto_data) { - wbs = silc_calloc(1, sizeof(*wbs)); - if (!wbs) - return NULL; - wbs->type = 0; - wbs->u.client = client_entry; - wbs->width = SILCPURPLE_WB_WIDTH; - wbs->height = SILCPURPLE_WB_HEIGHT; - wbs->brush_size = SILCPURPLE_WB_BRUSH_SMALL; - wbs->brush_color = SILCPURPLE_WB_COLOR_BLACK; - wb->proto_data = wbs; - - /* Start the whiteboard */ - purple_whiteboard_start(wb); - purple_whiteboard_clear(wb); - } - - return wb; -} - -PurpleWhiteboard *silcpurple_wb_init_ch(SilcPurple sg, SilcChannelEntry channel) -{ - PurpleWhiteboard *wb; - SilcPurpleWb wbs; - - wb = purple_whiteboard_get_session(sg->account, channel->channel_name); - if (!wb) - wb = purple_whiteboard_create(sg->account, channel->channel_name, 0); - if (!wb) - return NULL; - - if (!wb->proto_data) { - wbs = silc_calloc(1, sizeof(*wbs)); - if (!wbs) - return NULL; - wbs->type = 1; - wbs->u.channel = channel; - wbs->width = SILCPURPLE_WB_WIDTH; - wbs->height = SILCPURPLE_WB_HEIGHT; - wbs->brush_size = SILCPURPLE_WB_BRUSH_SMALL; - wbs->brush_color = SILCPURPLE_WB_COLOR_BLACK; - wb->proto_data = wbs; - - /* Start the whiteboard */ - purple_whiteboard_start(wb); - purple_whiteboard_clear(wb); - } - - return wb; -} - -static void -silcpurple_wb_parse(SilcPurpleWb wbs, PurpleWhiteboard *wb, - unsigned char *message, SilcUInt32 message_len) -{ - SilcUInt8 command; - SilcUInt16 width, height, brush_size; - SilcUInt32 brush_color, x, y, dx, dy; - SilcBufferStruct buf; - int ret; - - /* Parse the packet */ - silc_buffer_set(&buf, message, message_len); - ret = silc_buffer_unformat(&buf, - SILC_STR_UI_CHAR(&command), - SILC_STR_UI_SHORT(&width), - SILC_STR_UI_SHORT(&height), - SILC_STR_UI_INT(&brush_color), - SILC_STR_UI_SHORT(&brush_size), - SILC_STR_END); - if (ret < 0) - return; - silc_buffer_pull(&buf, ret); - - /* Update whiteboard if its dimensions changed */ - if (width != wbs->width || height != wbs->height) - silcpurple_wb_set_dimensions(wb, height, width); - - if (command == SILCPURPLE_WB_DRAW) { - /* Parse data and draw it */ - ret = silc_buffer_unformat(&buf, - SILC_STR_UI_INT(&dx), - SILC_STR_UI_INT(&dy), - SILC_STR_END); - if (ret < 0) - return; - silc_buffer_pull(&buf, 8); - x = dx; - y = dy; - while (buf.len > 0) { - ret = silc_buffer_unformat(&buf, - SILC_STR_UI_INT(&dx), - SILC_STR_UI_INT(&dy), - SILC_STR_END); - if (ret < 0) - return; - silc_buffer_pull(&buf, 8); - - purple_whiteboard_draw_line(wb, x, y, x + dx, y + dy, - brush_color, brush_size); - x += dx; - y += dy; - } - } - - if (command == SILCPURPLE_WB_CLEAR) - purple_whiteboard_clear(wb); -} - -typedef struct { - unsigned char *message; - SilcUInt32 message_len; - SilcPurple sg; - SilcClientEntry sender; - SilcChannelEntry channel; -} *SilcPurpleWbRequest; - -static void -silcpurple_wb_request_cb(SilcPurpleWbRequest req, gint id) -{ - PurpleWhiteboard *wb; - - if (id != 1) - goto out; - - if (!req->channel) - wb = silcpurple_wb_init(req->sg, req->sender); - else - wb = silcpurple_wb_init_ch(req->sg, req->channel); - - silcpurple_wb_parse(wb->proto_data, wb, req->message, req->message_len); - - out: - silc_free(req->message); - silc_free(req); -} - -static void -silcpurple_wb_request(SilcClient client, const unsigned char *message, - SilcUInt32 message_len, SilcClientEntry sender, - SilcChannelEntry channel) -{ - char tmp[128]; - SilcPurpleWbRequest req; - PurpleConnection *gc; - SilcPurple sg; - - gc = client->application; - sg = gc->proto_data; - - /* Open whiteboard automatically if requested */ - if (purple_account_get_bool(sg->account, "open-wb", FALSE)) { - PurpleWhiteboard *wb; - - if (!channel) - wb = silcpurple_wb_init(sg, sender); - else - wb = silcpurple_wb_init_ch(sg, channel); - - silcpurple_wb_parse(wb->proto_data, wb, (unsigned char *)message, - message_len); - return; - } - - /* Close any previous unaccepted requests */ - purple_request_close_with_handle(sender); - - if (!channel) { - g_snprintf(tmp, sizeof(tmp), - _("%s sent message to whiteboard. Would you like " - "to open the whiteboard?"), sender->nickname); - } else { - g_snprintf(tmp, sizeof(tmp), - _("%s sent message to whiteboard on %s channel. " - "Would you like to open the whiteboard?"), - sender->nickname, channel->channel_name); - } - - req = silc_calloc(1, sizeof(*req)); - if (!req) - return; - req->message = silc_memdup(message, message_len); - req->message_len = message_len; - req->sender = sender; - req->channel = channel; - req->sg = sg; - - purple_request_action(sender, _("Whiteboard"), tmp, NULL, 1, - sg->account, sender->nickname, NULL, req, 2, - _("Yes"), G_CALLBACK(silcpurple_wb_request_cb), - _("No"), G_CALLBACK(silcpurple_wb_request_cb)); -} - -/* Process incoming whiteboard message */ - -void silcpurple_wb_receive(SilcClient client, SilcClientConnection conn, - SilcClientEntry sender, SilcMessagePayload payload, - SilcMessageFlags flags, const unsigned char *message, - SilcUInt32 message_len) -{ - SilcPurple sg; - PurpleConnection *gc; - PurpleWhiteboard *wb; - SilcPurpleWb wbs; - - gc = client->application; - sg = gc->proto_data; - - wb = purple_whiteboard_get_session(sg->account, sender->nickname); - if (!wb) { - /* Ask user if they want to open the whiteboard */ - silcpurple_wb_request(client, message, message_len, - sender, NULL); - return; - } - - wbs = wb->proto_data; - silcpurple_wb_parse(wbs, wb, (unsigned char *)message, message_len); -} - -/* Process incoming whiteboard message on channel */ - -void silcpurple_wb_receive_ch(SilcClient client, SilcClientConnection conn, - SilcClientEntry sender, SilcChannelEntry channel, - SilcMessagePayload payload, - SilcMessageFlags flags, - const unsigned char *message, - SilcUInt32 message_len) -{ - SilcPurple sg; - PurpleConnection *gc; - PurpleWhiteboard *wb; - SilcPurpleWb wbs; - - gc = client->application; - sg = gc->proto_data; - - wb = purple_whiteboard_get_session(sg->account, channel->channel_name); - if (!wb) { - /* Ask user if they want to open the whiteboard */ - silcpurple_wb_request(client, message, message_len, - sender, channel); - return; - } - - wbs = wb->proto_data; - silcpurple_wb_parse(wbs, wb, (unsigned char *)message, message_len); -} - -/* Send whiteboard message */ - -void silcpurple_wb_send(PurpleWhiteboard *wb, GList *draw_list) -{ - SilcPurpleWb wbs = wb->proto_data; - SilcBuffer packet; - GList *list; - int len; - PurpleConnection *gc; - SilcPurple sg; - - g_return_if_fail(draw_list); - gc = purple_account_get_connection(wb->account); - g_return_if_fail(gc); - sg = gc->proto_data; - g_return_if_fail(sg); - - len = SILCPURPLE_WB_HEADER; - for (list = draw_list; list; list = list->next) - len += 4; - - packet = silc_buffer_alloc_size(len); - if (!packet) - return; - - /* Assmeble packet */ - silc_buffer_format(packet, - SILC_STR_UI32_STRING(SILCPURPLE_WB_MIME), - SILC_STR_UI_CHAR(SILCPURPLE_WB_DRAW), - SILC_STR_UI_SHORT(wbs->width), - SILC_STR_UI_SHORT(wbs->height), - SILC_STR_UI_INT(wbs->brush_color), - SILC_STR_UI_SHORT(wbs->brush_size), - SILC_STR_END); - silc_buffer_pull(packet, SILCPURPLE_WB_HEADER); - for (list = draw_list; list; list = list->next) { - silc_buffer_format(packet, - SILC_STR_UI_INT(GPOINTER_TO_INT(list->data)), - SILC_STR_END); - silc_buffer_pull(packet, 4); - } - - /* Send the message */ - if (wbs->type == 0) { - /* Private message */ - silc_client_send_private_message(sg->client, sg->conn, - wbs->u.client, - SILC_MESSAGE_FLAG_DATA, - packet->head, len, TRUE); - } else if (wbs->type == 1) { - /* Channel message. Channel private keys are not supported. */ - silc_client_send_channel_message(sg->client, sg->conn, - wbs->u.channel, NULL, - SILC_MESSAGE_FLAG_DATA, - packet->head, len, TRUE); - } - - silc_buffer_free(packet); -} - -/* Purple Whiteboard operations */ - -void silcpurple_wb_start(PurpleWhiteboard *wb) -{ - /* Nothing here. Everything is in initialization */ -} - -void silcpurple_wb_end(PurpleWhiteboard *wb) -{ - silc_free(wb->proto_data); - wb->proto_data = NULL; -} - -void silcpurple_wb_get_dimensions(const PurpleWhiteboard *wb, int *width, int *height) -{ - SilcPurpleWb wbs = wb->proto_data; - *width = wbs->width; - *height = wbs->height; -} - -void silcpurple_wb_set_dimensions(PurpleWhiteboard *wb, int width, int height) -{ - SilcPurpleWb wbs = wb->proto_data; - wbs->width = width > SILCPURPLE_WB_WIDTH_MAX ? SILCPURPLE_WB_WIDTH_MAX : - width; - wbs->height = height > SILCPURPLE_WB_HEIGHT_MAX ? SILCPURPLE_WB_HEIGHT_MAX : - height; - - /* Update whiteboard */ - purple_whiteboard_set_dimensions(wb, wbs->width, wbs->height); -} - -void silcpurple_wb_get_brush(const PurpleWhiteboard *wb, int *size, int *color) -{ - SilcPurpleWb wbs = wb->proto_data; - *size = wbs->brush_size; - *color = wbs->brush_color; -} - -void silcpurple_wb_set_brush(PurpleWhiteboard *wb, int size, int color) -{ - SilcPurpleWb wbs = wb->proto_data; - wbs->brush_size = size; - wbs->brush_color = color; - - /* Update whiteboard */ - purple_whiteboard_set_brush(wb, size, color); -} - -void silcpurple_wb_clear(PurpleWhiteboard *wb) -{ - SilcPurpleWb wbs = wb->proto_data; - SilcBuffer packet; - int len; - PurpleConnection *gc; - SilcPurple sg; - - gc = purple_account_get_connection(wb->account); - g_return_if_fail(gc); - sg = gc->proto_data; - g_return_if_fail(sg); - - len = SILCPURPLE_WB_HEADER; - packet = silc_buffer_alloc_size(len); - if (!packet) - return; - - /* Assmeble packet */ - silc_buffer_format(packet, - SILC_STR_UI32_STRING(SILCPURPLE_WB_MIME), - SILC_STR_UI_CHAR(SILCPURPLE_WB_CLEAR), - SILC_STR_UI_SHORT(wbs->width), - SILC_STR_UI_SHORT(wbs->height), - SILC_STR_UI_INT(wbs->brush_color), - SILC_STR_UI_SHORT(wbs->brush_size), - SILC_STR_END); - - /* Send the message */ - if (wbs->type == 0) { - /* Private message */ - silc_client_send_private_message(sg->client, sg->conn, - wbs->u.client, - SILC_MESSAGE_FLAG_DATA, - packet->head, len, TRUE); - } else if (wbs->type == 1) { - /* Channel message */ - silc_client_send_channel_message(sg->client, sg->conn, - wbs->u.channel, NULL, - SILC_MESSAGE_FLAG_DATA, - packet->head, len, TRUE); - } - - silc_buffer_free(packet); -} diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/silc10/wb.h --- a/libpurple/protocols/silc10/wb.h Mon Aug 22 11:20:05 2011 +0900 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -/* - - silcpurple.h - - Author: Pekka Riikonen - - Copyright (C) 2005 Pekka Riikonen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - -*/ - -#ifndef SILCPURPLE_WB_H -#define SILCPURPLE_WB_H - -#include "silcpurple.h" -#include "whiteboard.h" - -PurpleWhiteboard * -silcpurple_wb_init(SilcPurple sg, SilcClientEntry client_entry); -PurpleWhiteboard * -silcpurple_wb_init_ch(SilcPurple sg, SilcChannelEntry channel); -void silcpurple_wb_receive(SilcClient client, SilcClientConnection conn, - SilcClientEntry sender, SilcMessagePayload payload, - SilcMessageFlags flags, const unsigned char *message, - SilcUInt32 message_len); -void silcpurple_wb_receive_ch(SilcClient client, SilcClientConnection conn, - SilcClientEntry sender, SilcChannelEntry channel, - SilcMessagePayload payload, - SilcMessageFlags flags, - const unsigned char *message, - SilcUInt32 message_len); -void silcpurple_wb_start(PurpleWhiteboard *wb); -void silcpurple_wb_end(PurpleWhiteboard *wb); -void silcpurple_wb_get_dimensions(const PurpleWhiteboard *wb, int *width, int *height); -void silcpurple_wb_set_dimensions(PurpleWhiteboard *wb, int width, int height); -void silcpurple_wb_get_brush(const PurpleWhiteboard *wb, int *size, int *color); -void silcpurple_wb_set_brush(PurpleWhiteboard *wb, int size, int color); -void silcpurple_wb_send(PurpleWhiteboard *wb, GList *draw_list); -void silcpurple_wb_clear(PurpleWhiteboard *wb); - -#endif /* SILCPURPLE_WB_H */ diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/yahoo/yahoo_filexfer.c --- a/libpurple/protocols/yahoo/yahoo_filexfer.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/protocols/yahoo/yahoo_filexfer.c Mon Aug 29 12:28:49 2011 +0900 @@ -123,7 +123,7 @@ int remaining, written; xfer = data; - xd = xfer->data; + xd = purple_xfer_get_protocol_data(xfer); remaining = xd->txbuflen - xd->txbuf_written; written = write(xfer->fd, xd->txbuf + xd->txbuf_written, remaining); @@ -160,7 +160,7 @@ if (!(xfer = data)) return; - if (!(xd = xfer->data)) + if (!(xd = purple_xfer_get_protocol_data(xfer))) return; if ((source < 0) || (xd->path == NULL) || (xd->host == NULL)) { purple_xfer_error(PURPLE_XFER_RECEIVE, purple_xfer_get_account(xfer), @@ -194,7 +194,7 @@ int written, remaining; xfer = data; - xd = xfer->data; + xd = purple_xfer_get_protocol_data(xfer); remaining = xd->txbuflen - xd->txbuf_written; written = write(xfer->fd, xd->txbuf + xd->txbuf_written, remaining); @@ -240,7 +240,7 @@ if (!(xfer = data)) return; - if (!(xd = xfer->data)) + if (!(xd = purple_xfer_get_protocol_data(xfer))) return; if (source < 0) { @@ -318,7 +318,7 @@ PurpleAccount *account; YahooData *yd; - xfer_data = xfer->data; + xfer_data = purple_xfer_get_protocol_data(xfer); gc = xfer_data->gc; yd = gc->proto_data; account = purple_connection_get_account(gc); @@ -362,7 +362,7 @@ YahooData *yd; struct yahoo_packet *pkt; - xfer_data = xfer->data; + xfer_data = purple_xfer_get_protocol_data(xfer); gc = xfer_data->gc; yd = gc->proto_data; account = purple_connection_get_account(gc); @@ -435,7 +435,7 @@ gchar *length; gchar *end; int filelen; - struct yahoo_xfer_data *xd = xfer->data; + struct yahoo_xfer_data *xd = purple_xfer_get_protocol_data(xfer); if (purple_xfer_get_type(xfer) != PURPLE_XFER_RECEIVE) { return 0; @@ -495,7 +495,7 @@ static gssize yahoo_xfer_write(const guchar *buffer, size_t size, PurpleXfer *xfer) { gssize len; - struct yahoo_xfer_data *xd = xfer->data; + struct yahoo_xfer_data *xd = purple_xfer_get_protocol_data(xfer); if (!xd) return -1; @@ -521,7 +521,7 @@ { struct yahoo_xfer_data *xfer_data; - xfer_data = xfer->data; + xfer_data = purple_xfer_get_protocol_data(xfer); if(purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_CANCEL_LOCAL && xfer_data->version == 15) { @@ -561,14 +561,14 @@ if (xfer_data) yahoo_xfer_data_free(xfer_data); - xfer->data = NULL; + purple_xfer_set_protocol_data(xfer, NULL); } static void yahoo_xfer_cancel_recv(PurpleXfer *xfer) { struct yahoo_xfer_data *xfer_data; - xfer_data = xfer->data; + xfer_data = purple_xfer_get_protocol_data(xfer); if(purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_CANCEL_LOCAL && xfer_data->version == 15) { @@ -608,7 +608,7 @@ if (xfer_data) yahoo_xfer_data_free(xfer_data); - xfer->data = NULL; + purple_xfer_set_protocol_data(xfer, NULL); } /* Send HTTP OK after receiving file */ @@ -638,7 +638,7 @@ PurpleConnection *gc; YahooData *yd; - xfer_data = xfer_old->data; + xfer_data = purple_xfer_get_protocol_data(xfer_old); if(xfer_data && xfer_data->version == 15 && purple_xfer_get_type(xfer_old) == PURPLE_XFER_RECEIVE && xfer_data->filename_list) { @@ -694,7 +694,7 @@ xfer_data->firstoflist = FALSE; /* Dereference xfer_data from old xfer */ - xfer_old->data = NULL; + purple_xfer_set_protocol_data(xfer_old, NULL); /* Build the file transfer handle. */ xfer = purple_xfer_new(gc->account, PURPLE_XFER_RECEIVE, xfer_old->who); @@ -707,7 +707,7 @@ g_free(utf8_filename); purple_xfer_set_size(xfer, filesize); - xfer->data = xfer_data; + purple_xfer_set_protocol_data(xfer, xfer_data); /* Setup our I/O op functions */ purple_xfer_set_init_fnc(xfer, yahoo_xfer_init_15); @@ -731,8 +731,7 @@ } if (xfer_data) yahoo_xfer_data_free(xfer_data); - xfer_old->data = NULL; - + purple_xfer_set_protocol_data(xfer_old, NULL); } void yahoo_process_p2pfilexfer(PurpleConnection *gc, struct yahoo_packet *pkt) @@ -891,7 +890,7 @@ g_return_if_reached(); } - xfer->data = xfer_data; + purple_xfer_set_protocol_data(xfer, xfer_data); /* Set the info about the incoming file. */ if (filename) { @@ -948,7 +947,7 @@ g_return_val_if_reached(NULL); } - xfer->data = xfer_data; + purple_xfer_set_protocol_data(xfer, xfer_data); /* Setup our I/O op functions */ purple_xfer_set_init_fnc(xfer, yahoo_xfer_init); @@ -998,7 +997,7 @@ if (!(xfer = data)) return; - if (!(xd = xfer->data)) + if (!(xd = purple_xfer_get_protocol_data(xfer))) return; gc = xd->gc; account = purple_connection_get_account(gc); @@ -1091,7 +1090,7 @@ if( !g_hash_table_lookup(yd->peers, who) ) yahoo_send_p2p_pkt(gc, who, 0); - xfer_data = xfer->data; + xfer_data = purple_xfer_get_protocol_data(xfer); xfer_data->status_15 = STARTED; purple_xfer_set_init_fnc(xfer, yahoo_xfer_init_15); xfer_data->version = 15; @@ -1119,7 +1118,7 @@ PurpleConnection *gc; xfer = data; - xd = xfer->data; + xd = purple_xfer_get_protocol_data(xfer); account = purple_connection_get_account(xd->gc); gc = xd->gc; @@ -1172,7 +1171,7 @@ int remaining, written; xfer = data; - xd = xfer->data; + xd = purple_xfer_get_protocol_data(xfer); remaining = xd->txbuflen - xd->txbuf_written; written = write(source, xd->txbuf + xd->txbuf_written, remaining); @@ -1244,7 +1243,7 @@ if (!(xfer = data)) return; - if (!(xd = xfer->data)) + if (!(xd = purple_xfer_get_protocol_data(xfer))) return; gc = xd->gc; account = purple_connection_get_account(gc); @@ -1378,7 +1377,7 @@ struct yahoo_xfer_data *xd; xfer = data; - if (!(xd = xfer->data)) { + if (!(xd = purple_xfer_get_protocol_data(xfer))) { purple_xfer_cancel_remote(xfer); return; } @@ -1401,7 +1400,7 @@ char *time_str; xfer = data; - if (!(xd = xfer->data)) { + if (!(xd = purple_xfer_get_protocol_data(xfer))) { purple_xfer_cancel_remote(xfer); return; } @@ -1463,7 +1462,7 @@ struct yahoo_xfer_data *xd; xfer = data; - if (!(xd = xfer->data)) { + if (!(xd = purple_xfer_get_protocol_data(xfer))) { purple_xfer_cancel_remote(xfer); return; } @@ -1505,7 +1504,7 @@ char *filename_without_spaces = NULL; xfer = data; - if (!(xd = xfer->data) || (listenfd == -1)) { + if (!(xd = purple_xfer_get_protocol_data(xfer)) || (listenfd == -1)) { purple_debug_warning("yahoo","p2p: error starting server for p2p file transfer\n"); purple_xfer_cancel_remote(xfer); return; @@ -1569,7 +1568,7 @@ gchar *filename; struct yahoo_p2p_data *p2p_data; - if (!(xd = xfer->data)) + if (!(xd = purple_xfer_get_protocol_data(xfer))) return; account = purple_connection_get_account(gc); @@ -1752,7 +1751,7 @@ g_free(utf8_filename); purple_xfer_set_size(xfer, filesize); - xfer->data = xfer_data; + purple_xfer_set_protocol_data(xfer, xfer_data); /* Setup our I/O op functions */ purple_xfer_set_init_fnc(xfer, yahoo_xfer_init_15); @@ -1842,7 +1841,7 @@ return; } - xfer_data = xfer->data; + xfer_data = purple_xfer_get_protocol_data(xfer); xfer_data->info_val_249 = val_249; xfer_data->xfer_idstring_for_relay = g_strdup(xfer_idstring_for_relay); @@ -1939,7 +1938,7 @@ return; } - xfer_data = xfer->data; + xfer_data = purple_xfer_get_protocol_data(xfer); if(url) purple_url_parse(url, &(xfer_data->host), &(xfer_data->port), &(xfer_data->path), NULL, NULL); diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/yahoo/yahoo_profile.c --- a/libpurple/protocols/yahoo/yahoo_profile.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/protocols/yahoo/yahoo_profile.c Mon Aug 29 12:28:49 2011 +0900 @@ -809,7 +809,7 @@ * to send back HTML, with a 200 status code. */ if (error_message != NULL || url_text == NULL || strcmp(url_text, "") == 0) { - purple_notify_user_info_add_pair(user_info, _("Error retrieving profile"), NULL); + purple_notify_user_info_add_pair_html(user_info, _("Error retrieving profile"), NULL); purple_notify_userinfo(info_data->gc, info_data->name, user_info, NULL, NULL); purple_notify_user_info_destroy(user_info); @@ -844,7 +844,7 @@ _("If you wish to view this profile, " "you will need to visit this link in your web browser:"), profile_url_text, profile_url_text); - purple_notify_user_info_add_pair(user_info, NULL, tmp); + purple_notify_user_info_add_pair_html(user_info, NULL, tmp); g_free(tmp); purple_notify_userinfo(info_data->gc, info_data->name, @@ -1055,7 +1055,7 @@ id = purple_imgstore_add_with_id(g_memdup(url_text, len), len, NULL); tmp = g_strdup_printf("
", id); - purple_notify_user_info_add_pair(user_info, NULL, tmp); + purple_notify_user_info_add_pair_html(user_info, NULL, tmp); g_free(tmp); } } @@ -1204,7 +1204,7 @@ const gchar *str; purple_notify_user_info_add_section_break(user_info); - purple_notify_user_info_add_pair(user_info, + purple_notify_user_info_add_pair_html(user_info, _("Error retrieving profile"), NULL); if (profile_state == PROFILE_STATE_UNKNOWN_LANGUAGE) { @@ -1244,7 +1244,7 @@ purple_notify_user_info_add_section_break(user_info); tmp = g_strdup_printf("%s", profile_url_text, _("View web profile")); - purple_notify_user_info_add_pair(user_info, NULL, tmp); + purple_notify_user_info_add_pair_html(user_info, NULL, tmp); g_free(tmp); g_free(stripped); diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/yahoo/yahoochat.c --- a/libpurple/protocols/yahoo/yahoochat.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/protocols/yahoo/yahoochat.c Mon Aug 29 12:28:49 2011 +0900 @@ -1375,7 +1375,9 @@ purple_roomlist_set_in_progress(list, FALSE); if (yrl) { - list->proto_data = g_list_remove(list->proto_data, yrl); + GList *proto_data = purple_roomlist_get_proto_data(list); + proto_data = g_list_remove(proto_data, yrl); + purple_roomlist_set_proto_data(list, proto_data); yahoo_roomlist_destroy(yrl); } @@ -1451,7 +1453,7 @@ yrl->inpa = 0; g_free(yrl->txbuf); yrl->txbuf = NULL; - purple_notify_error(purple_account_get_connection(list->account), NULL, _("Unable to connect"), _("Fetching the room list failed.")); + purple_notify_error(purple_account_get_connection(purple_roomlist_get_account(list)), NULL, _("Unable to connect"), _("Fetching the room list failed.")); yahoo_roomlist_cleanup(list, yrl); return; } @@ -1474,10 +1476,12 @@ { struct yahoo_roomlist *yrl = data; PurpleRoomlist *list = yrl->list; - YahooData *yd = purple_account_get_connection(list->account)->proto_data; + PurpleAccount *account = purple_roomlist_get_account(list); + PurpleConnection *pc = purple_account_get_connection(account); + YahooData *yd = pc->proto_data; if (source < 0) { - purple_notify_error(purple_account_get_connection(list->account), NULL, _("Unable to connect"), _("Fetching the room list failed.")); + purple_notify_error(pc, NULL, _("Unable to connect"), _("Fetching the room list failed.")); yahoo_roomlist_cleanup(list, yrl); return; } @@ -1506,6 +1510,7 @@ struct yahoo_roomlist *yrl; const char *rll, *rlurl; char *url; + GList *proto_data; account = purple_connection_get_account(gc); @@ -1556,7 +1561,9 @@ return NULL; } - rl->proto_data = g_list_append(rl->proto_data, yrl); + proto_data = purple_roomlist_get_proto_data(rl); + proto_data = g_list_append(proto_data, yrl); + purple_roomlist_set_proto_data(rl, proto_data); purple_roomlist_set_in_progress(rl, TRUE); return rl; @@ -1566,8 +1573,8 @@ { GList *l, *k; - k = l = list->proto_data; - list->proto_data = NULL; + k = l = purple_roomlist_get_proto_data(list); + purple_roomlist_set_proto_data(list, NULL); purple_roomlist_set_in_progress(list, FALSE); @@ -1580,32 +1587,39 @@ void yahoo_roomlist_expand_category(PurpleRoomlist *list, PurpleRoomlistRoom *category) { + PurpleAccount *account; struct yahoo_roomlist *yrl; char *url; char *id; const char *rll; + GList *proto_data; gboolean jp = purple_account_get_bool(list->account, "yahoojp", FALSE); - if (category->type != PURPLE_ROOMLIST_ROOMTYPE_CATEGORY) + if (purple_roomlist_room_get_type(category) != PURPLE_ROOMLIST_ROOMTYPE_CATEGORY) return; - if (!(id = g_list_nth_data(category->fields, 1))) { + if (!(id = g_list_nth_data(purple_roomlist_room_get_fields(category), 1))) { purple_roomlist_set_in_progress(list, FALSE); return; } - rll = jp ? YAHOOJP_ROOMLIST_LOCALE : purple_account_get_string(list->account, "room_list_locale", YAHOO_ROOMLIST_LOCALE); + account = purple_roomlist_get_account(list); + rll = jp ? YAHOOJP_ROOMLIST_LOCALE : purple_account_get_string(account, "room_list_locale", YAHOO_ROOMLIST_LOCALE); if (rll != NULL && *rll != '\0') { - url = g_strdup_printf("%s?chatroom_%s=0&intl=%s", jp ? YAHOOJP_ROOMLIST_URL : purple_account_get_string(list->account,"room_list", YAHOO_ROOMLIST_URL), id, rll); + url = g_strdup_printf("%s?chatroom_%s=0&intl=%s", + jp ? YAHOOJP_ROOMLIST_URL : purple_account_get_string(account,"room_list", YAHOO_ROOMLIST_URL), id, rll); } else { - url = g_strdup_printf("%s?chatroom_%s=0", jp ? YAHOOJP_ROOMLIST_URL : purple_account_get_string(list->account,"room_list", YAHOO_ROOMLIST_URL), id); + url = g_strdup_printf("%s?chatroom_%s=0", jp ? YAHOOJP_ROOMLIST_URL : purple_account_get_string(account,"room_list", YAHOO_ROOMLIST_URL), id); } yrl = g_new0(struct yahoo_roomlist, 1); yrl->list = list; yrl->cat = category; - list->proto_data = g_list_append(list->proto_data, yrl); + + proto_data = purple_roomlist_get_proto_data(list); + proto_data = g_list_append(proto_data, yrl); + purple_roomlist_set_proto_data(list, proto_data); purple_url_parse(url, &(yrl->host), NULL, &(yrl->path), NULL, NULL); g_free(url); @@ -1613,11 +1627,11 @@ yrl->ucat = purple_roomlist_room_new(PURPLE_ROOMLIST_ROOMTYPE_CATEGORY, _("User Rooms"), yrl->cat); purple_roomlist_room_add(list, yrl->ucat); - if (purple_proxy_connect(purple_account_get_connection(list->account), - list->account, yrl->host, 80, + if (purple_proxy_connect(purple_account_get_connection(account), + account, yrl->host, 80, yahoo_roomlist_got_connected, yrl) == NULL) { - purple_notify_error(purple_account_get_connection(list->account), + purple_notify_error(purple_account_get_connection(account), NULL, _("Connection problem"), _("Unable to fetch room list.")); purple_roomlist_ref(list); yahoo_roomlist_cleanup(list, yrl); diff -r 9aee8493db7f -r ac6353ffa129 libpurple/protocols/zephyr/zephyr.c --- a/libpurple/protocols/zephyr/zephyr.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/protocols/zephyr/zephyr.c Mon Aug 29 12:28:49 2011 +0900 @@ -791,20 +791,23 @@ char *tmp; const char *balias; - purple_notify_user_info_add_pair(user_info, _("User"), (b ? bname : user)); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("User"), (b ? bname : user)); balias = purple_buddy_get_local_buddy_alias(b); if (b && balias) - purple_notify_user_info_add_pair(user_info, _("Alias"), balias); + purple_notify_user_info_add_pair_plaintext(user_info, _("Alias"), balias); if (!nlocs) { - purple_notify_user_info_add_pair(user_info, NULL, _("Hidden or not logged-in")); + purple_notify_user_info_add_pair_plaintext(user_info, NULL, _("Hidden or not logged-in")); } for (; nlocs > 0; nlocs--) { /* XXX add real error reporting */ ZGetLocations(&locs, &one); + /* TODO: Need to escape locs.host and locs.time? */ tmp = g_strdup_printf(_("
At %s since %s"), locs.host, locs.time); - purple_notify_user_info_add_pair(user_info, _("Location"), tmp); + purple_notify_user_info_add_pair_html(user_info, _("Location"), tmp); g_free(tmp); } purple_notify_userinfo(gc, (b ? bname : user), @@ -1161,7 +1164,7 @@ locations = find_node(newparsetree,"locations"); locval = tree_child(tree_child(tree_child(tree_child(locations,2),0),0),2)->contents; - if (!locval || !g_ascii_strcasecmp(locval," ") || (strlen(locval) == 0)) { + if (!locval || !g_ascii_strcasecmp(locval," ") || !*locval) { nlocs = 0; } else { nlocs = 1; @@ -1173,19 +1176,22 @@ char *tmp; const char *balias; - purple_notify_user_info_add_pair(user_info, _("User"), (b ? bname : user)); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("User"), (b ? bname : user)); balias = b ? purple_buddy_get_local_buddy_alias(b) : NULL; if (balias) - purple_notify_user_info_add_pair(user_info, _("Alias"), balias); + purple_notify_user_info_add_pair_plaintext(user_info, _("Alias"), balias); if (!nlocs) { - purple_notify_user_info_add_pair(user_info, NULL, _("Hidden or not logged-in")); + purple_notify_user_info_add_pair_plaintext(user_info, NULL, _("Hidden or not logged-in")); } else { + /* TODO: Need to escape the two strings that make up tmp? */ tmp = g_strdup_printf(_("
At %s since %s"), tree_child(tree_child(tree_child(tree_child(locations,2),0),0),2)->contents, tree_child(tree_child(tree_child(tree_child(locations,2),0),2),2)->contents); - purple_notify_user_info_add_pair(user_info, _("Location"), tmp); + purple_notify_user_info_add_pair_html(user_info, _("Location"), tmp); g_free(tmp); } @@ -2079,7 +2085,7 @@ int pos2 = 0; char *newmsg; - if (message && (strlen(message) > 0)) { + if (message && *message) { newmsg = g_new0(char,1+strlen(message)*2); while(pos < strlen(message)) { if (message[pos]=='\\') { @@ -2111,7 +2117,7 @@ int pos2 = 0; char *newmsg; - if (message && (strlen(message) > 0)) { + if (message && *message) { newmsg = g_new0(char,strlen(message)+1); while(pos < strlen(message)) { if (message[pos]=='\\') { diff -r 9aee8493db7f -r ac6353ffa129 libpurple/request.c --- a/libpurple/request.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/request.c Mon Aug 29 12:28:49 2011 +0900 @@ -42,6 +42,92 @@ } PurpleRequestInfo; +/** + * A request field. + */ +struct _PurpleRequestField +{ + PurpleRequestFieldType type; + PurpleRequestFieldGroup *group; + + char *id; + char *label; + char *type_hint; + + gboolean visible; + gboolean required; + + union + { + struct + { + gboolean multiline; + gboolean masked; + gboolean editable; + char *default_value; + char *value; + + } string; + + struct + { + int default_value; + int value; + + } integer; + + struct + { + gboolean default_value; + gboolean value; + + } boolean; + + struct + { + int default_value; + int value; + + GList *labels; + + } choice; + + struct + { + GList *items; + GList *icons; + GHashTable *item_data; + GList *selected; + GHashTable *selected_table; + + gboolean multiple_selection; + + } list; + + struct + { + PurpleAccount *default_account; + PurpleAccount *account; + gboolean show_all; + + PurpleFilterAccountFunc filter_func; + + } account; + + struct + { + unsigned int scale_x; + unsigned int scale_y; + const char *buffer; + gsize size; + } image; + + } u; + + void *ui_data; + char *tooltip; + +}; PurpleRequestFields * purple_request_fields_new(void) diff -r 9aee8493db7f -r ac6353ffa129 libpurple/request.h --- a/libpurple/request.h Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/request.h Mon Aug 29 12:28:49 2011 +0900 @@ -96,95 +96,6 @@ } PurpleRequestFieldGroup; -#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_REQUEST_C_) -/** - * A request field. - */ -struct _PurpleRequestField -{ - PurpleRequestFieldType type; - PurpleRequestFieldGroup *group; - - char *id; - char *label; - char *type_hint; - - gboolean visible; - gboolean required; - - union - { - struct - { - gboolean multiline; - gboolean masked; - gboolean editable; - char *default_value; - char *value; - - } string; - - struct - { - int default_value; - int value; - - } integer; - - struct - { - gboolean default_value; - gboolean value; - - } boolean; - - struct - { - int default_value; - int value; - - GList *labels; - - } choice; - - struct - { - GList *items; - GList *icons; - GHashTable *item_data; - GList *selected; - GHashTable *selected_table; - - gboolean multiple_selection; - - } list; - - struct - { - PurpleAccount *default_account; - PurpleAccount *account; - gboolean show_all; - - PurpleFilterAccountFunc filter_func; - - } account; - - struct - { - unsigned int scale_x; - unsigned int scale_y; - const char *buffer; - gsize size; - } image; - - } u; - - void *ui_data; - char *tooltip; - -}; -#endif - /** * Request UI operations. */ diff -r 9aee8493db7f -r ac6353ffa129 libpurple/roomlist.c --- a/libpurple/roomlist.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/roomlist.c Mon Aug 29 12:28:49 2011 +0900 @@ -32,6 +32,39 @@ #include "roomlist.h" #include "server.h" +/** + * Represents a list of rooms for a given connection on a given protocol. + */ +struct _PurpleRoomlist { + PurpleAccount *account; /**< The account this list belongs to. */ + GList *fields; /**< The fields. */ + GList *rooms; /**< The list of rooms. */ + gboolean in_progress; /**< The listing is in progress. */ + gpointer ui_data; /**< UI private data. */ + gpointer proto_data; /** Prpl private data. */ + guint ref; /**< The reference count. */ +}; + +/** + * Represents a room. + */ +struct _PurpleRoomlistRoom { + PurpleRoomlistRoomType type; /**< The type of room. */ + gchar *name; /**< The name of the room. */ + GList *fields; /**< Other fields. */ + PurpleRoomlistRoom *parent; /**< The parent room, or NULL. */ + gboolean expanded_once; /**< A flag the UI uses to avoid multiple expand prpl cbs. */ +}; + +/** + * A field a room might have. + */ +struct _PurpleRoomlistField { + PurpleRoomlistFieldType type; /**< The type of field. */ + gchar *label; /**< The i18n user displayed name of the field. */ + gchar *name; /**< The internal name of the field. */ + gboolean hidden; /**< Hidden? */ +}; static PurpleRoomlistUiOps *ops = NULL; @@ -127,6 +160,13 @@ purple_roomlist_destroy(list); } +PurpleAccount *purple_roomlist_get_account(PurpleRoomlist *list) +{ + g_return_val_if_fail(list != NULL, NULL); + + return list->account; +} + void purple_roomlist_set_fields(PurpleRoomlist *list, GList *fields) { g_return_if_fail(list != NULL); @@ -234,6 +274,34 @@ return list->fields; } +gpointer purple_roomlist_get_proto_data(PurpleRoomlist *list) +{ + g_return_val_if_fail(list != NULL, NULL); + + return list->proto_data; +} + +void purple_roomlist_set_proto_data(PurpleRoomlist *list, gpointer proto_data) +{ + g_return_if_fail(list != NULL); + + list->proto_data = proto_data; +} + +gpointer purple_roomlist_get_ui_data(PurpleRoomlist *list) +{ + g_return_val_if_fail(list != NULL, NULL); + + return list->ui_data; +} + +void purple_roomlist_set_ui_data(PurpleRoomlist *list, gpointer ui_data) +{ + g_return_if_fail(list != NULL); + + list->ui_data = ui_data; +} + /*@}*/ /**************************************************************************/ @@ -329,7 +397,21 @@ return room->parent; } -GList * purple_roomlist_room_get_fields(PurpleRoomlistRoom *room) +gboolean purple_roomlist_room_get_expanded_once(PurpleRoomlistRoom *room) +{ + g_return_val_if_fail(room != NULL, FALSE); + + return room->expanded_once; +} + +void purple_roomlist_room_set_expanded_once(PurpleRoomlistRoom *room, gboolean expanded_once) +{ + g_return_if_fail(room != NULL); + + room->expanded_once = expanded_once; +} + +GList *purple_roomlist_room_get_fields(PurpleRoomlistRoom *room) { return room->fields; } diff -r 9aee8493db7f -r ac6353ffa129 libpurple/roomlist.h --- a/libpurple/roomlist.h Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/roomlist.h Mon Aug 29 12:28:49 2011 +0900 @@ -64,40 +64,6 @@ /**************************************************************************/ /** - * Represents a list of rooms for a given connection on a given protocol. - */ -struct _PurpleRoomlist { - PurpleAccount *account; /**< The account this list belongs to. */ - GList *fields; /**< The fields. */ - GList *rooms; /**< The list of rooms. */ - gboolean in_progress; /**< The listing is in progress. */ - gpointer ui_data; /**< UI private data. */ - gpointer proto_data; /** Prpl private data. */ - guint ref; /**< The reference count. */ -}; - -/** - * Represents a room. - */ -struct _PurpleRoomlistRoom { - PurpleRoomlistRoomType type; /**< The type of room. */ - gchar *name; /**< The name of the room. */ - GList *fields; /**< Other fields. */ - PurpleRoomlistRoom *parent; /**< The parent room, or NULL. */ - gboolean expanded_once; /**< A flag the UI uses to avoid multiple expand prpl cbs. */ -}; - -/** - * A field a room might have. - */ -struct _PurpleRoomlistField { - PurpleRoomlistFieldType type; /**< The type of field. */ - gchar *label; /**< The i18n user displayed name of the field. */ - gchar *name; /**< The internal name of the field. */ - gboolean hidden; /**< Hidden? */ -}; - -/** * The room list ops to be filled out by the UI. */ struct _PurpleRoomlistUiOps { @@ -163,6 +129,14 @@ void purple_roomlist_unref(PurpleRoomlist *list); /** + * Retrieve the PurpleAccount that was given when the room list was + * created. + * + * @return The PurpleAccount tied to this room list. + */ +PurpleAccount *purple_roomlist_get_account(PurpleRoomlist *list); + +/** * Set the different field types and their names for this protocol. * * This must be called before purple_roomlist_room_add(). @@ -241,11 +215,49 @@ /** * Get the list of fields for a roomlist. * - * @param roomlist The roomlist, which must not be @c NULL. + * @param roomlist The roomlist, which must not be @c NULL. * @constreturn A list of fields * @since 2.4.0 */ -GList * purple_roomlist_get_fields(PurpleRoomlist *roomlist); +GList *purple_roomlist_get_fields(PurpleRoomlist *roomlist); + +/** + * Get the protocol data associated with this room list. + * + * @param roomlist The roomlist, which must not be @c NULL. + * + * @return The protocol data associated with this room list. This is a + * convenience field provided to the protocol plugin--it is not + * used the libpurple core. + */ +gpointer purple_roomlist_get_proto_data(PurpleRoomlist *list); + +/** + * Set the protocol data associated with this room list. + * + * @param list The roomlist, which must not be @c NULL. + * @param proto_data A pointer to associate with this room list. + */ +void purple_roomlist_set_proto_data(PurpleRoomlist *list, gpointer proto_data); + +/** + * Get the UI data associated with this room list. + * + * @param roomlist The roomlist, which must not be @c NULL. + * + * @return The UI data associated with this room list. This is a + * convenience field provided to the UIs--it is not + * used by the libpurple core. + */ +gpointer purple_roomlist_get_ui_data(PurpleRoomlist *list); + +/** + * Set the UI data associated with this room list. + * + * @param list The roomlist, which must not be @c NULL. + * @param UI_data A pointer to associate with this room list. + */ +void purple_roomlist_set_ui_data(PurpleRoomlist *list, gpointer ui_data); /*@}*/ @@ -308,6 +320,23 @@ PurpleRoomlistRoom * purple_roomlist_room_get_parent(PurpleRoomlistRoom *room); /** + * Get the value of the expanded_once flag. + * + * @param room The room, which must not be @c NULL. + * + * @return The value of the expanded_once flag. + */ +gboolean purple_roomlist_room_get_expanded_once(PurpleRoomlistRoom *room); + +/** + * Set the expanded_once flag. + * + * @param room The room, which must not be @c NULL. + * @param expanded_once The new value of the expanded_once flag. + */ +void purple_roomlist_room_set_expanded_once(PurpleRoomlistRoom *room, gboolean expanded_once); + +/** * Get the list of fields for a room. * * @param room The room, which must not be @c NULL. diff -r 9aee8493db7f -r ac6353ffa129 libpurple/sound.h --- a/libpurple/sound.h Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/sound.h Mon Aug 29 12:28:49 2011 +0900 @@ -38,7 +38,7 @@ * A type of sound. */ -typedef enum _PurpleSoundEventID +typedef enum { PURPLE_SOUND_BUDDY_ARRIVE = 0, /**< Buddy signs on. */ PURPLE_SOUND_BUDDY_LEAVE, /**< Buddy signs off. */ diff -r 9aee8493db7f -r ac6353ffa129 libpurple/status.c --- a/libpurple/status.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/status.c Mon Aug 29 12:28:49 2011 +0900 @@ -763,29 +763,29 @@ specified_attr_ids = g_list_prepend(specified_attr_ids, (gpointer)id); - if (value->type == PURPLE_TYPE_STRING) + if (purple_value_get_type(value) == PURPLE_TYPE_STRING) { const gchar *string_data = l->data; l = l->next; - if (purple_strequal(string_data, value->data.string_data)) + if (purple_strequal(string_data, purple_value_get_string(value))) continue; purple_status_set_attr_string(status, id, string_data); changed = TRUE; } - else if (value->type == PURPLE_TYPE_INT) + else if (purple_value_get_type(value) == PURPLE_TYPE_INT) { int int_data = GPOINTER_TO_INT(l->data); l = l->next; - if (int_data == value->data.int_data) + if (int_data == purple_value_get_int(value)) continue; purple_status_set_attr_int(status, id, int_data); changed = TRUE; } - else if (value->type == PURPLE_TYPE_BOOLEAN) + else if (purple_value_get_type(value) == PURPLE_TYPE_BOOLEAN) { gboolean boolean_data = GPOINTER_TO_INT(l->data); l = l->next; - if (boolean_data == value->data.boolean_data) + if (boolean_data == purple_value_get_boolean(value)) continue; purple_status_set_attr_boolean(status, id, boolean_data); changed = TRUE; @@ -809,7 +809,7 @@ if (!g_list_find_custom(specified_attr_ids, attr->id, (GCompareFunc)strcmp)) { PurpleValue *default_value; default_value = purple_status_attr_get_value(attr); - if (default_value->type == PURPLE_TYPE_STRING) { + if (purple_value_get_type(default_value) == PURPLE_TYPE_STRING) { const char *cur = purple_status_get_attr_string(status, attr->id); const char *def = purple_value_get_string(default_value); if ((cur == NULL && def == NULL) @@ -819,14 +819,14 @@ } purple_status_set_attr_string(status, attr->id, def); - } else if (default_value->type == PURPLE_TYPE_INT) { + } else if (purple_value_get_type(default_value) == PURPLE_TYPE_INT) { int cur = purple_status_get_attr_int(status, attr->id); int def = purple_value_get_int(default_value); if (cur == def) continue; purple_status_set_attr_int(status, attr->id, def); - } else if (default_value->type == PURPLE_TYPE_BOOLEAN) { + } else if (purple_value_get_type(default_value) == PURPLE_TYPE_BOOLEAN) { gboolean cur = purple_status_get_attr_boolean(status, attr->id); gboolean def = purple_value_get_boolean(default_value); if (cur == def) diff -r 9aee8493db7f -r ac6353ffa129 libpurple/upnp.c --- a/libpurple/upnp.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/upnp.c Mon Aug 29 12:28:49 2011 +0900 @@ -744,7 +744,7 @@ { if (control_info.status == PURPLE_UPNP_STATUS_DISCOVERED && control_info.publicip - && strlen(control_info.publicip) > 0) + && *control_info.publicip) return control_info.publicip; /* Trigger another UPnP discovery if 5 minutes have elapsed since the @@ -803,7 +803,7 @@ { if (control_info.status == PURPLE_UPNP_STATUS_DISCOVERED && control_info.internalip - && strlen(control_info.internalip) > 0) + && *control_info.internalip) return control_info.internalip; /* Trigger another UPnP discovery if 5 minutes have elapsed since the diff -r 9aee8493db7f -r ac6353ffa129 libpurple/util.c --- a/libpurple/util.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/util.c Mon Aug 29 12:28:49 2011 +0900 @@ -147,7 +147,7 @@ len = strlen(str); - g_return_val_if_fail(strlen(str) > 0, 0); + g_return_val_if_fail(*str, 0); g_return_val_if_fail(len % 2 == 0, 0); data = g_malloc(len / 2); @@ -1323,7 +1323,7 @@ g_string_append_len(dest, p, q - p); } - purple_notify_user_info_add_pair(user_info, display_name, dest->str); + purple_notify_user_info_add_pair_html(user_info, display_name, dest->str); g_string_free(dest, TRUE); return TRUE; @@ -2290,7 +2290,7 @@ url_buf = g_string_free(gurl_buf, FALSE); /* strip off trailing periods */ - if (strlen(url_buf) > 0) { + if (*url_buf) { for (d = url_buf + strlen(url_buf) - 1; *d == '.'; d--, t--) *d = '\0'; } diff -r 9aee8493db7f -r ac6353ffa129 libpurple/value.c --- a/libpurple/value.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/value.c Mon Aug 29 12:28:49 2011 +0900 @@ -29,6 +29,44 @@ #define OUTGOING_FLAG 0x01 +/** + * A wrapper for a type, subtype, and specific type of value. + */ +struct _PurpleValue +{ + PurpleType type; + unsigned short flags; + + union + { + char char_data; + unsigned char uchar_data; + gboolean boolean_data; + short short_data; + unsigned short ushort_data; + int int_data; + unsigned int uint_data; + long long_data; + unsigned long ulong_data; + gint64 int64_data; + guint64 uint64_data; + char *string_data; + void *object_data; + void *pointer_data; + int enum_data; + void *boxed_data; + + } data; + + union + { + unsigned int subtype; + char *specific_type; + + } u; + +}; + PurpleValue * purple_value_new(PurpleType type, ...) { diff -r 9aee8493db7f -r ac6353ffa129 libpurple/value.h --- a/libpurple/value.h Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/value.h Mon Aug 29 12:28:49 2011 +0900 @@ -86,40 +86,7 @@ /** * A wrapper for a type, subtype, and specific type of value. */ -typedef struct -{ - PurpleType type; - unsigned short flags; - - union - { - char char_data; - unsigned char uchar_data; - gboolean boolean_data; - short short_data; - unsigned short ushort_data; - int int_data; - unsigned int uint_data; - long long_data; - unsigned long ulong_data; - gint64 int64_data; - guint64 uint64_data; - char *string_data; - void *object_data; - void *pointer_data; - int enum_data; - void *boxed_data; - - } data; - - union - { - unsigned int subtype; - char *specific_type; - - } u; - -} PurpleValue; +typedef struct _PurpleValue PurpleValue; #ifdef __cplusplus extern "C" { diff -r 9aee8493db7f -r ac6353ffa129 libpurple/win32/libc_interface.c --- a/libpurple/win32/libc_interface.c Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/win32/libc_interface.c Mon Aug 29 12:28:49 2011 +0900 @@ -467,12 +467,6 @@ return res; } -/* stdio.h */ - -int wpurple_rename (const char *oldname, const char *newname) { - return g_rename(oldname, newname); -} - /* time.h */ struct tm * wpurple_localtime_r (const time_t *time, struct tm *resultp) { diff -r 9aee8493db7f -r ac6353ffa129 libpurple/win32/libc_interface.h --- a/libpurple/win32/libc_interface.h Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/win32/libc_interface.h Mon Aug 29 12:28:49 2011 +0900 @@ -135,7 +135,7 @@ #define vsnprintf _vsnprintf #define rename( oldname, newname ) \ -wpurple_rename( oldname, newname ) +g_rename( oldname, newname ) /* sys/stat.h */ #define fchmod(a,b) diff -r 9aee8493db7f -r ac6353ffa129 libpurple/win32/libc_internal.h --- a/libpurple/win32/libc_internal.h Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/win32/libc_internal.h Mon Aug 29 12:28:49 2011 +0900 @@ -141,9 +141,6 @@ int wpurple_gethostname(char *name, size_t size); -/* stdio.h */ -int wpurple_rename(const char *oldname, const char *newname); - #ifdef __cplusplus } #endif /* __cplusplus */ diff -r 9aee8493db7f -r ac6353ffa129 libpurple/xmlnode.h --- a/libpurple/xmlnode.h Mon Aug 22 11:20:05 2011 +0900 +++ b/libpurple/xmlnode.h Mon Aug 29 12:28:49 2011 +0900 @@ -35,7 +35,7 @@ /** * The valid types for an xmlnode */ -typedef enum _XMLNodeType +typedef enum { XMLNODE_TYPE_TAG, /**< Just a tag */ XMLNODE_TYPE_ATTRIB, /**< Has attributes */ diff -r 9aee8493db7f -r ac6353ffa129 pidgin/gtkblist.c --- a/pidgin/gtkblist.c Mon Aug 22 11:20:05 2011 +0900 +++ b/pidgin/gtkblist.c Mon Aug 29 12:28:49 2011 +0900 @@ -3780,10 +3780,8 @@ connections = purple_connections_get_all(); if (full && connections && connections->next) { - tmp = g_markup_escape_text(purple_account_get_username( - purple_buddy_get_account(b)), -1); - purple_notify_user_info_add_pair(user_info, _("Account"), tmp); - g_free(tmp); + purple_notify_user_info_add_pair_plaintext(user_info, _("Account"), + purple_account_get_username(purple_buddy_get_account(b))); } /* Alias */ @@ -3793,9 +3791,8 @@ (c->alias != NULL && c->alias[0] != '\0') && strcmp(c->alias, b->alias) != 0) { - tmp = g_markup_escape_text(b->alias, -1); - purple_notify_user_info_add_pair(user_info, _("Buddy Alias"), tmp); - g_free(tmp); + purple_notify_user_info_add_pair_plaintext(user_info, + _("Buddy Alias"), b->alias); } /* Nickname/Server Alias */ @@ -3805,9 +3802,8 @@ * to look at the tooltip. */ if (full && b->server_alias != NULL && b->server_alias[0] != '\0') { - tmp = g_markup_escape_text(b->server_alias, -1); - purple_notify_user_info_add_pair(user_info, _("Nickname"), tmp); - g_free(tmp); + purple_notify_user_info_add_pair_plaintext(user_info, + _("Nickname"), b->server_alias); } /* Logged In */ @@ -3823,7 +3819,7 @@ tmp = g_strdup(purple_date_format_long(localtime(&signon))); } else tmp = purple_str_seconds_to_string(time(NULL) - signon); - purple_notify_user_info_add_pair(user_info, _("Logged In"), tmp); + purple_notify_user_info_add_pair_plaintext(user_info, _("Logged In"), tmp); g_free(tmp); } @@ -3834,7 +3830,7 @@ if (idle_secs > 0) { tmp = purple_str_seconds_to_string(time(NULL) - idle_secs); - purple_notify_user_info_add_pair(user_info, _("Idle"), tmp); + purple_notify_user_info_add_pair_plaintext(user_info, _("Idle"), tmp); g_free(tmp); } } @@ -3869,7 +3865,7 @@ if (lastseen > 0) { tmp = purple_str_seconds_to_string(time(NULL) - lastseen); - purple_notify_user_info_add_pair(user_info, _("Last Seen"), tmp); + purple_notify_user_info_add_pair_plaintext(user_info, _("Last Seen"), tmp); g_free(tmp); } } @@ -3879,7 +3875,7 @@ /* FIXME: Why is this status special-cased by the core? --rlaager * FIXME: Alternatively, why not have the core do all of them? --rlaager */ if (!PURPLE_BUDDY_IS_ONLINE(b)) { - purple_notify_user_info_add_pair(user_info, _("Status"), _("Offline")); + purple_notify_user_info_add_pair_plaintext(user_info, _("Status"), _("Offline")); } if (purple_account_is_connected(b->account) && @@ -3891,11 +3887,11 @@ /* These are Easter Eggs. Patches to remove them will be rejected. */ if (!g_ascii_strcasecmp(b->name, "robflynn")) - purple_notify_user_info_add_pair(user_info, _("Description"), _("Spooky")); + purple_notify_user_info_add_pair_plaintext(user_info, _("Description"), _("Spooky")); if (!g_ascii_strcasecmp(b->name, "seanegn")) - purple_notify_user_info_add_pair(user_info, _("Status"), _("Awesome")); + purple_notify_user_info_add_pair_plaintext(user_info, _("Status"), _("Awesome")); if (!g_ascii_strcasecmp(b->name, "chipx86")) - purple_notify_user_info_add_pair(user_info, _("Status"), _("Rockin'")); + purple_notify_user_info_add_pair_plaintext(user_info, _("Status"), _("Rockin'")); tmp = purple_notify_user_info_get_text_with_newline(user_info, "\n"); g_string_append(str, tmp); @@ -3910,24 +3906,21 @@ user_info = purple_notify_user_info_new(); count = purple_blist_get_group_online_count(group); - if (count != 0) { /* Online buddies in group */ - tmp = g_strdup_printf("%d", count); - purple_notify_user_info_add_pair(user_info, - _("Online Buddies"), - tmp); - g_free(tmp); + char tmp2[12]; + sprintf(tmp2, "%d", count); + purple_notify_user_info_add_pair_plaintext(user_info, + _("Online Buddies"), tmp2); } count = purple_blist_get_group_size(group, FALSE); if (count != 0) { /* Total buddies (from online accounts) in group */ - tmp = g_strdup_printf("%d", count); - purple_notify_user_info_add_pair(user_info, - _("Total Buddies"), - tmp); - g_free(tmp); + char tmp2[12]; + sprintf(tmp2, "%d", count); + purple_notify_user_info_add_pair_html(user_info, + _("Total Buddies"), tmp2); } tmp = purple_notify_user_info_get_text_with_newline(user_info, "\n"); diff -r 9aee8493db7f -r ac6353ffa129 pidgin/gtkconv.c --- a/pidgin/gtkconv.c Mon Aug 22 11:20:05 2011 +0900 +++ b/pidgin/gtkconv.c Mon Aug 29 12:28:49 2011 +0900 @@ -398,8 +398,32 @@ } tmp = g_string_free(str, FALSE); + } else if (!g_ascii_strcasecmp(args[0], "unsafe")) { + if (purple_debug_is_unsafe()) { + purple_debug_set_unsafe(FALSE); + purple_conversation_write(conv, NULL, _("Unsafe debugging is now disabled."), + PURPLE_MESSAGE_NO_LOG|PURPLE_MESSAGE_SYSTEM, time(NULL)); + } else { + purple_debug_set_unsafe(TRUE); + purple_conversation_write(conv, NULL, _("Unsafe debugging is now enabled."), + PURPLE_MESSAGE_NO_LOG|PURPLE_MESSAGE_SYSTEM, time(NULL)); + } + + return PURPLE_CMD_RET_OK; + } else if (!g_ascii_strcasecmp(args[0], "verbose")) { + if (purple_debug_is_verbose()) { + purple_debug_set_verbose(FALSE); + purple_conversation_write(conv, NULL, _("Verbose debugging is now disabled."), + PURPLE_MESSAGE_NO_LOG|PURPLE_MESSAGE_SYSTEM, time(NULL)); + } else { + purple_debug_set_verbose(TRUE); + purple_conversation_write(conv, NULL, _("Verbose debugging is now enabled."), + PURPLE_MESSAGE_NO_LOG|PURPLE_MESSAGE_SYSTEM, time(NULL)); + } + + return PURPLE_CMD_RET_OK; } else { - purple_conversation_write(conv, NULL, _("Supported debug options are: plugins version"), + purple_conversation_write(conv, NULL, _("Supported debug options are: plugins version unsafe verbose"), PURPLE_MESSAGE_NO_LOG|PURPLE_MESSAGE_ERROR, time(NULL)); return PURPLE_CMD_RET_OK; } @@ -634,7 +658,7 @@ gtk_widget_grab_focus(gtkconv->entry); - if (strlen(clean) == 0) { + if (!*clean) { g_free(buf); g_free(clean); return; @@ -5346,8 +5370,8 @@ PurpleBuddy *b = PURPLE_BUDDY(bn); PurpleConversation *conv; if ((conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, b->name, b->account))) { - if (conv->ui_data) - return conv->ui_data; + if (PIDGIN_CONVERSATION(conv)) + return PIDGIN_CONVERSATION(conv); } } @@ -5435,7 +5459,7 @@ PurpleValue *value; if (conv_type == PURPLE_CONV_TYPE_IM && (gtkconv = pidgin_conv_find_gtkconv(conv))) { - conv->ui_data = gtkconv; + purple_conversation_set_ui_data(conv, gtkconv); if (!g_list_find(gtkconv->convs, conv)) gtkconv->convs = g_list_prepend(gtkconv->convs, conv); pidgin_conv_switch_active_conversation(conv); @@ -5443,7 +5467,7 @@ } gtkconv = g_new0(PidginConversation, 1); - conv->ui_data = gtkconv; + purple_conversation_set_ui_data(conv, gtkconv); gtkconv->active_conv = conv; gtkconv->convs = g_list_prepend(gtkconv->convs, conv); gtkconv->send_history = g_list_append(NULL, NULL); @@ -5470,7 +5494,7 @@ g_free(gtkconv->u.im); g_free(gtkconv); - conv->ui_data = NULL; + purple_conversation_set_ui_data(conv, NULL); return; } diff -r 9aee8493db7f -r ac6353ffa129 pidgin/gtkconv.h --- a/pidgin/gtkconv.h Mon Aug 22 11:20:05 2011 +0900 +++ b/pidgin/gtkconv.h Mon Aug 29 12:28:49 2011 +0900 @@ -56,7 +56,7 @@ }; #define PIDGIN_CONVERSATION(conv) \ - ((PidginConversation *)(conv)->ui_data) + ((PidginConversation *)purple_conversation_get_ui_data(conv)) #define PIDGIN_IS_PIDGIN_CONVERSATION(conv) \ (purple_conversation_get_ui_ops(conv) == \ diff -r 9aee8493db7f -r ac6353ffa129 pidgin/gtkdocklet.c --- a/pidgin/gtkdocklet.c Mon Aug 22 11:20:05 2011 +0900 +++ b/pidgin/gtkdocklet.c Mon Aug 29 12:28:49 2011 +0900 @@ -188,7 +188,6 @@ for(l = purple_accounts_get_all(); l != NULL; l = l->next) { PurpleAccount *account = (PurpleAccount*)l->data; - PurpleStatus *account_status; if (!purple_account_get_enabled(account, PIDGIN_UI)) continue; @@ -196,7 +195,6 @@ if (purple_account_is_disconnected(account)) continue; - account_status = purple_account_get_active_status(account); if (purple_account_is_connecting(account)) newconnecting = TRUE; } diff -r 9aee8493db7f -r ac6353ffa129 pidgin/gtkft.c --- a/pidgin/gtkft.c Mon Aug 22 11:20:05 2011 +0900 +++ b/pidgin/gtkft.c Mon Aug 29 12:28:49 2011 +0900 @@ -37,9 +37,6 @@ #include "pidginstock.h" #include "gtkutils.h" -#define PIDGINXFER(xfer) \ - (PidginXferUiData *)(xfer)->ui_data - /* the maximum size of files we will try to make a thumbnail for */ #define PIDGIN_XFER_MAX_SIZE_IMAGE_THUMBNAIL 10 * 1024 * 1024 @@ -243,7 +240,7 @@ if (dialog == NULL || xfer == NULL) return; - data = PIDGINXFER(xfer); + data = purple_xfer_get_ui_data(xfer); get_xfer_info_strings(xfer, &kbsec, &time_elapsed, &time_remaining); @@ -869,7 +866,7 @@ purple_xfer_ref(xfer); - data = PIDGINXFER(xfer); + data = purple_xfer_get_ui_data(xfer); data->in_list = TRUE; pidgin_xfer_dialog_show(dialog); @@ -926,7 +923,7 @@ g_return_if_fail(dialog != NULL); g_return_if_fail(xfer != NULL); - data = PIDGINXFER(xfer); + data = purple_xfer_get_ui_data(xfer); if (data == NULL) return; @@ -957,7 +954,7 @@ g_return_if_fail(dialog != NULL); g_return_if_fail(xfer != NULL); - data = PIDGINXFER(xfer); + data = purple_xfer_get_ui_data(xfer); if (data == NULL) return; @@ -970,7 +967,7 @@ return; } - data = PIDGINXFER(xfer); + data = purple_xfer_get_ui_data(xfer); update_detailed_info(dialog, xfer); update_title_progress(dialog); @@ -1007,7 +1004,7 @@ g_return_if_fail(dialog != NULL); g_return_if_fail(xfer != NULL); - if ((data = PIDGINXFER(xfer)) == NULL) + if ((data = purple_xfer_get_ui_data(xfer)) == NULL) return; if (data->in_list == FALSE) @@ -1095,9 +1092,9 @@ { PidginXferUiData *data; - /* This is where we're setting xfer->ui_data for the first time. */ + /* This is where we're setting xfer's "ui_data" for the first time. */ data = g_new0(PidginXferUiData, 1); - xfer->ui_data = data; + purple_xfer_set_ui_data(xfer, data); } static void @@ -1105,11 +1102,11 @@ { PidginXferUiData *data; - data = PIDGINXFER(xfer); + data = purple_xfer_get_ui_data(xfer); if (data) { g_free(data->name); g_free(data); - xfer->ui_data = NULL; + purple_xfer_set_ui_data(xfer, NULL); } } diff -r 9aee8493db7f -r ac6353ffa129 pidgin/gtkimhtml.c --- a/pidgin/gtkimhtml.c Mon Aug 22 11:20:05 2011 +0900 +++ b/pidgin/gtkimhtml.c Mon Aug 29 12:28:49 2011 +0900 @@ -5383,9 +5383,9 @@ tag = sl->data; /** don't worry about non-printing tags ending */ if (tag_ends_here(tag, &iter, &next_iter) && - strlen(tag_to_html_end(tag)) > 0 && - strlen(tag_to_html_start(tag)) > 0) { - + *tag_to_html_end(tag) && + *tag_to_html_start(tag)) + { PidginTextTagData *tmp; GQueue *r = g_queue_new(); diff -r 9aee8493db7f -r ac6353ffa129 pidgin/gtkroomlist.c --- a/pidgin/gtkroomlist.c Mon Aug 22 11:20:05 2011 +0900 +++ b/pidgin/gtkroomlist.c Mon Aug 29 12:28:49 2011 +0900 @@ -91,7 +91,7 @@ purple_timeout_remove(dialog->pg_update_to); if (dialog->roomlist) { - PidginRoomlist *rl = dialog->roomlist->ui_data; + PidginRoomlist *rl = purple_roomlist_get_ui_data(dialog->roomlist); if (dialog->pg_update_to > 0) /* yes, that's right, unref it twice. */ @@ -115,7 +115,7 @@ dialog->account = account; if (change && dialog->roomlist) { - PidginRoomlist *rl = dialog->roomlist->ui_data; + PidginRoomlist *rl = purple_roomlist_get_ui_data(dialog->roomlist); if (rl->tree) { gtk_widget_destroy(rl->tree); rl->tree = NULL; @@ -135,7 +135,7 @@ return; if (dialog->roomlist != NULL) { - rl = dialog->roomlist->ui_data; + rl = purple_roomlist_get_ui_data(dialog->roomlist); gtk_widget_destroy(rl->tree); purple_roomlist_unref(dialog->roomlist); } @@ -144,7 +144,7 @@ if (!dialog->roomlist) return; purple_roomlist_ref(dialog->roomlist); - rl = dialog->roomlist->ui_data; + rl = purple_roomlist_get_ui_data(dialog->roomlist); rl->dialog = dialog; if (dialog->account_widget) @@ -203,7 +203,7 @@ val.g_type = 0; gtk_tree_model_get_value(GTK_TREE_MODEL(grl->model), &iter, ROOM_COLUMN, &val); room = g_value_get_pointer(&val); - if (!room || !(room->type & PURPLE_ROOMLIST_ROOMTYPE_ROOM)) { + if (!room || !(purple_roomlist_room_get_type(room) & PURPLE_ROOMLIST_ROOMTYPE_ROOM)) { gtk_widget_set_sensitive(dialog->join_button, FALSE); gtk_widget_set_sensitive(dialog->add_button, FALSE); return; @@ -228,7 +228,8 @@ static void do_add_room_cb(GtkWidget *w, struct _menu_cb_info *info) { char *name; - PurpleConnection *gc = purple_account_get_connection(info->list->account); + PurpleAccount *account = purple_roomlist_get_account(info->list); + PurpleConnection *gc = purple_account_get_connection(account); PurplePluginProtocolInfo *prpl_info = NULL; if(gc != NULL) @@ -237,9 +238,9 @@ if(prpl_info != NULL && prpl_info->roomlist_room_serialize) name = prpl_info->roomlist_room_serialize(info->room); else - name = g_strdup(info->room->name); + name = g_strdup(purple_roomlist_room_get_name(info->room)); - purple_blist_request_add_chat(info->list->account, NULL, NULL, name); + purple_blist_request_add_chat(account, NULL, NULL, name); g_free(name); } @@ -247,7 +248,7 @@ static void add_room_to_blist_cb(GtkButton *button, PidginRoomlistDialog *dialog) { PurpleRoomlist *rl = dialog->roomlist; - PidginRoomlist *grl = rl->ui_data; + PidginRoomlist *grl = purple_roomlist_get_ui_data(rl); struct _menu_cb_info *info = g_object_get_data(G_OBJECT(button), "room-info"); if(info != NULL) @@ -262,7 +263,7 @@ static void join_button_cb(GtkButton *button, PidginRoomlistDialog *dialog) { PurpleRoomlist *rl = dialog->roomlist; - PidginRoomlist *grl = rl->ui_data; + PidginRoomlist *grl = purple_roomlist_get_ui_data(rl); struct _menu_cb_info *info = g_object_get_data(G_OBJECT(button), "room-info"); if(info != NULL) @@ -272,7 +273,7 @@ static void row_activated_cb(GtkTreeView *tv, GtkTreePath *path, GtkTreeViewColumn *arg2, PurpleRoomlist *list) { - PidginRoomlist *grl = list->ui_data; + PidginRoomlist *grl = purple_roomlist_get_ui_data(list); GtkTreeIter iter; PurpleRoomlistRoom *room; GValue val; @@ -282,7 +283,7 @@ val.g_type = 0; gtk_tree_model_get_value(GTK_TREE_MODEL(grl->model), &iter, ROOM_COLUMN, &val); room = g_value_get_pointer(&val); - if (!room || !(room->type & PURPLE_ROOMLIST_ROOMTYPE_ROOM)) + if (!room || !(purple_roomlist_room_get_type(room) & PURPLE_ROOMLIST_ROOMTYPE_ROOM)) return; info.list = list; @@ -294,7 +295,7 @@ static gboolean room_click_cb(GtkWidget *tv, GdkEventButton *event, PurpleRoomlist *list) { GtkTreePath *path; - PidginRoomlist *grl = list->ui_data; + PidginRoomlist *grl = purple_roomlist_get_ui_data(list); GValue val; PurpleRoomlistRoom *room; GtkTreeIter iter; @@ -313,7 +314,7 @@ gtk_tree_model_get_value (GTK_TREE_MODEL(grl->model), &iter, ROOM_COLUMN, &val); room = g_value_get_pointer(&val); - if (!room || !(room->type & PURPLE_ROOMLIST_ROOMTYPE_ROOM)) + if (!room || !(purple_roomlist_room_get_type(room) & PURPLE_ROOMLIST_ROOMTYPE_ROOM)) return FALSE; info.list = list; @@ -341,9 +342,9 @@ gtk_tree_model_get_value(gtk_tree_view_get_model(treeview), arg1, ROOM_COLUMN, &val); category = g_value_get_pointer(&val); - if (!category->expanded_once) { + if (!purple_roomlist_room_get_expanded_once(category)) { purple_roomlist_expand_category(list, category); - category->expanded_once = TRUE; + purple_roomlist_room_set_expanded_once(category, TRUE); } } @@ -354,7 +355,7 @@ pidgin_roomlist_paint_tooltip(GtkWidget *widget, gpointer user_data) { PurpleRoomlist *list = user_data; - PidginRoomlist *grl = list->ui_data; + PidginRoomlist *grl = purple_roomlist_get_ui_data(list); GtkStyle *style; int current_height, max_width; int max_text_width; @@ -393,7 +394,7 @@ static gboolean pidgin_roomlist_create_tip(PurpleRoomlist *list, GtkTreePath *path) { - PidginRoomlist *grl = list->ui_data; + PidginRoomlist *grl = purple_roomlist_get_ui_data(list); PurpleRoomlistRoom *room; GtkTreeIter iter; GValue val; @@ -414,19 +415,23 @@ gtk_tree_model_get_value(GTK_TREE_MODEL(grl->model), &iter, ROOM_COLUMN, &val); room = g_value_get_pointer(&val); - if (!room || !(room->type & PURPLE_ROOMLIST_ROOMTYPE_ROOM)) + if (!room || !(purple_roomlist_room_get_type(room) & PURPLE_ROOMLIST_ROOMTYPE_ROOM)) return FALSE; tooltip_text = g_string_new(""); gtk_tree_model_get(GTK_TREE_MODEL(grl->model), &iter, NAME_COLUMN, &name, -1); - for (j = NUM_OF_COLUMNS, l = room->fields, k = list->fields; l && k; j++, l = l->next, k = k->next) { + for (j = NUM_OF_COLUMNS, + l = purple_roomlist_room_get_fields(room), + k = purple_roomlist_get_fields(list); + l && k; j++, l = l->next, k = k->next) + { PurpleRoomlistField *f = k->data; gchar *label; - if (f->hidden) + if (purple_roomlist_field_get_hidden(f)) continue; - label = g_markup_escape_text(f->label, -1); - switch (f->type) { + label = g_markup_escape_text(purple_roomlist_field_get_label(f), -1); + switch (purple_roomlist_field_get_type(f)) { case PURPLE_ROOMLIST_FIELD_BOOL: g_string_append_printf(tooltip_text, "%s%s: %s", first ? "" : "\n", label, l->data ? "True" : "False"); break; @@ -478,7 +483,7 @@ gpointer data, int *w, int *h) { PurpleRoomlist *list = data; - PidginRoomlist *grl = list->ui_data; + PidginRoomlist *grl = purple_roomlist_get_ui_data(list); grl->tipwindow = widget; if (!pidgin_roomlist_create_tip(data, path)) return FALSE; @@ -622,7 +627,7 @@ { PidginRoomlist *rl = g_new0(PidginRoomlist, 1); - list->ui_data = rl; + purple_roomlist_set_ui_data(list, rl); rl->cats = g_hash_table_new_full(NULL, NULL, NULL, (GDestroyNotify)gtk_tree_row_reference_free); @@ -685,7 +690,7 @@ static void pidgin_roomlist_set_fields(PurpleRoomlist *list, GList *fields) { - PidginRoomlist *grl = list->ui_data; + PidginRoomlist *grl = purple_roomlist_get_ui_data(list); gint columns = NUM_OF_COLUMNS; int j; GtkTreeStore *model; @@ -707,7 +712,7 @@ for (j = NUM_OF_COLUMNS, l = fields; l; l = l->next, j++) { PurpleRoomlistField *f = l->data; - switch (f->type) { + switch (purple_roomlist_field_get_type(f)) { case PURPLE_ROOMLIST_FIELD_BOOL: types[j] = G_TYPE_BOOLEAN; break; @@ -749,18 +754,19 @@ for (j = NUM_OF_COLUMNS, l = fields; l; l = l->next, j++) { PurpleRoomlistField *f = l->data; - if (f->hidden) + if (purple_roomlist_field_get_hidden(f)) continue; renderer = gtk_cell_renderer_text_new(); - column = gtk_tree_view_column_new_with_attributes(f->label, renderer, - "text", j, NULL); + column = gtk_tree_view_column_new_with_attributes( + purple_roomlist_field_get_label(f), renderer, + "text", j, NULL); gtk_tree_view_column_set_sizing(GTK_TREE_VIEW_COLUMN(column), GTK_TREE_VIEW_COLUMN_GROW_ONLY); gtk_tree_view_column_set_resizable(GTK_TREE_VIEW_COLUMN(column), TRUE); gtk_tree_view_column_set_sort_column_id(GTK_TREE_VIEW_COLUMN(column), j); gtk_tree_view_column_set_reorderable(GTK_TREE_VIEW_COLUMN(column), TRUE); - if (f->type == PURPLE_ROOMLIST_FIELD_INT) { + if (purple_roomlist_field_get_type(f) == PURPLE_ROOMLIST_FIELD_INT) { gtk_tree_view_column_set_cell_data_func(column, renderer, int_cell_data_func, GINT_TO_POINTER(j), NULL); gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(model), j, int_sort_func, @@ -789,7 +795,7 @@ static gboolean pidgin_progress_bar_pulse(gpointer data) { PurpleRoomlist *list = data; - PidginRoomlist *rl = list->ui_data; + PidginRoomlist *rl = purple_roomlist_get_ui_data(list); if (!rl || !rl->dialog || !rl->dialog->pg_needs_pulse) { if (rl && rl->dialog) @@ -805,7 +811,7 @@ static void pidgin_roomlist_add_room(PurpleRoomlist *list, PurpleRoomlistRoom *room) { - PidginRoomlist *rl = list->ui_data; + PidginRoomlist *rl = purple_roomlist_get_ui_data(list); GtkTreeRowReference *rr, *parentrr = NULL; GtkTreePath *path; GtkTreeIter iter, parent, child; @@ -814,7 +820,7 @@ gboolean append = TRUE; rl->total_rooms++; - if (room->type == PURPLE_ROOMLIST_ROOMTYPE_ROOM) + if (purple_roomlist_room_get_type(room) == PURPLE_ROOMLIST_ROOMTYPE_ROOM) rl->num_rooms++; if (rl->dialog) { @@ -826,8 +832,8 @@ rl->dialog->pg_needs_pulse = TRUE; } - if (room->parent) { - parentrr = g_hash_table_lookup(rl->cats, room->parent); + if (purple_roomlist_room_get_parent(room)) { + parentrr = g_hash_table_lookup(rl->cats, purple_roomlist_room_get_parent(room)); path = gtk_tree_row_reference_get_path(parentrr); if (path) { PurpleRoomlistRoom *tmproom = NULL; @@ -848,24 +854,28 @@ else iter = child; - if (room->type & PURPLE_ROOMLIST_ROOMTYPE_CATEGORY) + if (purple_roomlist_room_get_type(room) & PURPLE_ROOMLIST_ROOMTYPE_CATEGORY) gtk_tree_store_append(rl->model, &child, &iter); path = gtk_tree_model_get_path(GTK_TREE_MODEL(rl->model), &iter); - if (room->type & PURPLE_ROOMLIST_ROOMTYPE_CATEGORY) { + if (purple_roomlist_room_get_type(room) & PURPLE_ROOMLIST_ROOMTYPE_CATEGORY) { rr = gtk_tree_row_reference_new(GTK_TREE_MODEL(rl->model), path); g_hash_table_insert(rl->cats, room, rr); } gtk_tree_path_free(path); - gtk_tree_store_set(rl->model, &iter, NAME_COLUMN, room->name, -1); + gtk_tree_store_set(rl->model, &iter, NAME_COLUMN, purple_roomlist_room_get_name(room), -1); gtk_tree_store_set(rl->model, &iter, ROOM_COLUMN, room, -1); - for (j = NUM_OF_COLUMNS, l = room->fields, k = list->fields; l && k; j++, l = l->next, k = k->next) { + for (j = NUM_OF_COLUMNS, + l = purple_roomlist_room_get_fields(room), + k = purple_roomlist_get_fields(list); + l && k; j++, l = l->next, k = k->next) + { PurpleRoomlistField *f = k->data; - if (f->hidden) + if (purple_roomlist_field_get_hidden(f)) continue; gtk_tree_store_set(rl->model, &iter, j, l->data, -1); } @@ -873,7 +883,7 @@ static void pidgin_roomlist_in_progress(PurpleRoomlist *list, gboolean in_progress) { - PidginRoomlist *rl = list->ui_data; + PidginRoomlist *rl = purple_roomlist_get_ui_data(list); if (!rl || !rl->dialog) return; @@ -895,7 +905,7 @@ static void pidgin_roomlist_destroy(PurpleRoomlist *list) { - PidginRoomlist *rl = list->ui_data; + PidginRoomlist *rl = purple_roomlist_get_ui_data(list); roomlists = g_list_remove(roomlists, list); @@ -903,7 +913,7 @@ g_hash_table_destroy(rl->cats); g_free(rl); - list->ui_data = NULL; + purple_roomlist_set_ui_data(list, NULL); } static PurpleRoomlistUiOps ops = { diff -r 9aee8493db7f -r ac6353ffa129 pidgin/gtkutils.c --- a/pidgin/gtkutils.c Mon Aug 22 11:20:05 2011 +0900 +++ b/pidgin/gtkutils.c Mon Aug 29 12:28:49 2011 +0900 @@ -984,7 +984,7 @@ show_retrieveing_info(PurpleConnection *conn, const char *name) { PurpleNotifyUserInfo *info = purple_notify_user_info_new(); - purple_notify_user_info_add_pair(info, _("Information"), _("Retrieving...")); + purple_notify_user_info_add_pair_plaintext(info, _("Information"), _("Retrieving...")); purple_notify_userinfo(conn, name, info, NULL, NULL); purple_notify_user_info_destroy(info); } @@ -1290,7 +1290,7 @@ monitor_num = gdk_screen_get_monitor_at_point (screen, *x, *y); - push_in = FALSE; + *push_in = FALSE; /* * The placement of popup menus horizontally works like this (with @@ -3246,9 +3246,9 @@ { gchar *escaped = g_shell_quote(uri); gchar *param = g_strconcat("/select,\"", uri, "\"", NULL); - gchar *wc_param = g_utf8_to_utf16(param, -1, NULL, NULL, NULL); - - code = (int)ShellExecuteW(NULL, "OPEN", L"explorer.exe", wc_param, NULL, SW_NORMAL); + wchar_t *wc_param = g_utf8_to_utf16(param, -1, NULL, NULL, NULL); + + code = (int)ShellExecuteW(NULL, L"OPEN", L"explorer.exe", wc_param, NULL, SW_NORMAL); g_free(wc_param); g_free(param); diff -r 9aee8493db7f -r ac6353ffa129 pidgin/win32/untar.h --- a/pidgin/win32/untar.h Mon Aug 22 11:20:05 2011 +0900 +++ b/pidgin/win32/untar.h Mon Aug 29 12:28:49 2011 +0900 @@ -12,7 +12,7 @@ extern "C" { #endif /* __cplusplus */ -typedef enum _untar_opt { +typedef enum { UNTAR_LISTING = (1 << 0), UNTAR_QUIET = (1 << 1), UNTAR_VERBOSE = (1 << 2), diff -r 9aee8493db7f -r ac6353ffa129 po/POTFILES.in --- a/po/POTFILES.in Mon Aug 22 11:20:05 2011 +0900 +++ b/po/POTFILES.in Mon Aug 29 12:28:49 2011 +0900 @@ -160,14 +160,6 @@ libpurple/protocols/silc/silc.c libpurple/protocols/silc/util.c libpurple/protocols/silc/wb.c -libpurple/protocols/silc10/buddy.c -libpurple/protocols/silc10/chat.c -libpurple/protocols/silc10/ft.c -libpurple/protocols/silc10/ops.c -libpurple/protocols/silc10/pk.c -libpurple/protocols/silc10/silc.c -libpurple/protocols/silc10/util.c -libpurple/protocols/silc10/wb.c libpurple/protocols/simple/simple.c libpurple/protocols/yahoo/libyahoo.c libpurple/protocols/yahoo/libyahoojp.c