Mon, 27 Aug 2007 21:59:11 +0000
propagate from branch 'im.pidgin.pidgin' (head cae3ca855d0dc6a31886c057a2767a81c4533731)
to branch 'im.pidgin.soc.2007.xmpp' (head e9a2be88e56510550986519d686b42559ca3a394)
--- a/AUTHORS Fri Aug 17 02:26:42 2007 +0000 +++ b/AUTHORS Mon Aug 27 21:59:11 2007 +0000 @@ -22,7 +22,7 @@ Ka-Hing Cheung - Developer Sadrul Habib Chowdhury - Developer Mark 'KingAnt' Doliner - Developer -Christian 'ChipX86' Hammond - Developer & Webmaster +Casey Harkins - Developer Gary 'grim' Kramlich - Developer Richard 'rlaager' Laager - Developer Richard 'wabz' Nelson - Developer @@ -31,21 +31,16 @@ Etan 'deryni' Reisner - Developer Tim 'marv' Ringenbach - Developer Luke 'LSchiere' Schierer - Support -Megan 'Cae' Schneider (support/QA) +Megan 'Cae' Schneider - support/QA Evan Schoenberg - Developer +Kevin 'SimGuy' Stange - Developer & Webmaster Stu 'nosnilmot' Tomlinson - Developer Nathan 'faceprint' Walp - Developer Crazy Patch Writers: ------------------- John 'rekkanoryo' Bailey -Felipe 'shx' Contreras -Decklin Foster -Casey Harkins Peter 'Bleeter' Lawler -Robert 'Robot101' McQueen -Benjamin Miller -Kevin 'SimGuy' Stange Retired Developers: ------------------ @@ -53,11 +48,19 @@ Jim Duchek <jim@linuxpimps.com> - maintainer Rob Flynn <gaim@robflynn.com> - maintainer Adam Fritzler - libfaim maintainer +Christian 'ChipX86' Hammond - Developer & Webmaster Syd Logan - hacker and designated driver [lazy bum] Jim Seymour - XMPP developer Mark Spencer <markster@marko.net> - original author Eric Warmenhoven <eric@warmenhoven.org> - lead developer +Retired Crazy Patch Writers: +--------------------------- +Felipe 'shx' Contreras +Decklin Foster +Robert 'Robot101' McQueen +Benjamin Miller + Artists: ------- Hylke Bons - Icons
--- a/COPYRIGHT Fri Aug 17 02:26:42 2007 +0000 +++ b/COPYRIGHT Mon Aug 27 21:59:11 2007 +0000 @@ -214,6 +214,7 @@ Nicolas Lichtmaier Wesley Lin Artem Litvinovich +Josh Littlefield Syd Logan Lokheed Norberto Lopes @@ -301,6 +302,7 @@ Luciano Miguel Ferreira Rocha Andrew Rodland Miguel Rodríguez (migrax) +Bob Rossi Jason Roth Jean-Francois Roy Sam S.
--- a/ChangeLog Fri Aug 17 02:26:42 2007 +0000 +++ b/ChangeLog Mon Aug 27 21:59:11 2007 +0000 @@ -1,17 +1,32 @@ Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul -version 2.1.1 (??/??/????): +version 2.2.0: + Libpurple: + * New protocol plugin: MySpaceIM (Jeff Connelly, Google Summer of + Code) + + Pidgin: + * Insert Horizontal Rules and Strikethrough text from toolbar + + Finch: + * Per-conversation mute and logging options (accessible from the menu) + +version 2.1.1 (08/20/2007): Yahoo: * Added an account action to open your inbox in the yahoo prpl. * Added support for Unicode status messages in Yahoo. * Server-stored aliases for Yahoo. (John Moody) * Fixed support for Yahoo! doodling. - * Support for MSN Messenger contacts + * Limited support for MSN Messenger contacts Bonjour: * Bonjour plugin uses native Avahi instead of Howl * Bonjour plugin supports Buddy Icons + XMPP: + * Only report conversation close when 'send typing notifications' + preference is turned on (Bob Rossi) + Pidgin: * Show current outgoing conversation formatting on the font label on the toolbar @@ -22,6 +37,7 @@ * Moved "Reset Formatting" toolbar button to Font menu. * Double click on the infopane to alias buddies and set topics on chats + * New smiley style Finch: * Sound support (Eric Polino)
--- a/ChangeLog.API Fri Aug 17 02:26:42 2007 +0000 +++ b/ChangeLog.API Mon Aug 27 21:59:11 2007 +0000 @@ -1,6 +1,24 @@ Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul -Version 2.1.1 (x/x/x): +Version 2.2.0 (??/??/????): + Pidgin: + Added: + * pidgin_set_accessible_relations, sets up label-for and labelled-by + ATK relations (broken out from pidgin_set_accessible_label) + + Finch: + Added: + * finch_sound_is_enabled + * The reserved field in the FinchConv is now used to store information + about the conversation (using FinchConversationFlag) + + libgnt: + * gnt_slider_set_small_step, gnt_slider_set_large_step to allow more + fine tuned updates of a GntSlider + * gnt_util_parse_xhtml_to_textview to parse XHTML strings in a + GntTextView (this works only if libxml2 is available) + +Version 2.1.1 (08/20/2007): libpurple: Changed: * PurpleAccountUiOps.request_authorize's authorize_cb and
--- a/ChangeLog.win32 Fri Aug 17 02:26:42 2007 +0000 +++ b/ChangeLog.win32 Mon Aug 27 21:59:11 2007 +0000 @@ -1,3 +1,6 @@ +version 2.1.1 (08/20/2007): + * No changes + version 2.1.0 (7/28/2007): * Updated launcher application (pidgin.exe) to support portable mode via `pidgin.exe --portable-mode` or by renaming the binary to
--- a/NEWS Fri Aug 17 02:26:42 2007 +0000 +++ b/NEWS Mon Aug 27 21:59:11 2007 +0000 @@ -1,5 +1,25 @@ Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul +2.1.1 (8/20/2007): + Sean: Continuing our schedule of frequent releases, Pidgin 2.1.1 + is out. In it, we've addressed a lot of UI issues from our + experimental new changes introduced in 2.1.0, and gave a lot of + attention to Yahoo! and Bonjour. Thanks to everyone who + contributed. + + Luke: We have reworked some parts of the conversation windows in + response to user comments. We did not quite reach 100 tickets + closed this release, so a fair few will role over again. Still, + we are slowly but surely working our way through the reported bugs. + Many thanks to everyone who has helped with tracking down the + various issues, testing fixes, and getting patches in. + + Tim: Sean finally got me to fix some of the buddy list bugs with + Yahoo! when in version 15 mode. So now we have some Yahoo! to + MSN support, which is kind of nice. Looks like some others have + been contributing to Yahoo! while I've been AWOL, so many thanks + to them. + 2.1.0 (7/28/2007): Sean: This release took a bit longer than 3 weeks, but boy is it worth it! We're beginning to experiment with new UI concepts and
--- a/configure.ac Fri Aug 17 02:26:42 2007 +0000 +++ b/configure.ac Mon Aug 27 21:59:11 2007 +0000 @@ -43,18 +43,18 @@ # # Make sure to update finch/libgnt/configure.ac with libgnt version changes. # -m4_define([purple_lt_current], [1]) +m4_define([purple_lt_current], [2]) m4_define([purple_major_version], [2]) -m4_define([purple_minor_version], [1]) -m4_define([purple_micro_version], [1]) +m4_define([purple_minor_version], [2]) +m4_define([purple_micro_version], [0]) m4_define([purple_version_suffix], [devel]) m4_define([purple_version], [purple_major_version.purple_minor_version.purple_micro_version]) m4_define([purple_display_version], purple_version[]m4_ifdef([purple_version_suffix],[purple_version_suffix])) -m4_define([gnt_lt_current], [1]) +m4_define([gnt_lt_current], [2]) m4_define([gnt_major_version], [2]) -m4_define([gnt_minor_version], [1]) +m4_define([gnt_minor_version], [2]) m4_define([gnt_micro_version], [0]) m4_define([gnt_version_suffix], [devel]) m4_define([gnt_version], @@ -858,7 +858,7 @@ fi if test "x$STATIC_PRPLS" = "xall" ; then - STATIC_PRPLS="bonjour gg irc jabber msn novell oscar qq sametime silc simple yahoo zephyr" + STATIC_PRPLS="bonjour gg irc jabber msn myspace novell oscar qq sametime silc simple yahoo zephyr" fi if test "x$have_meanwhile" != "xyes" ; then STATIC_PRPLS=`echo $STATIC_PRPLS | $sedpath 's/sametime//'` @@ -904,6 +904,7 @@ irc) static_irc=yes ;; jabber) static_jabber=yes ;; msn) static_msn=yes ;; + myspace) static_myspace=yes ;; novell) static_novell=yes ;; oscar) static_oscar=yes ;; aim) static_oscar=yes ;; @@ -924,6 +925,7 @@ AM_CONDITIONAL(STATIC_IRC, test "x$static_irc" = "xyes") AM_CONDITIONAL(STATIC_JABBER, test "x$static_jabber" = "xyes") AM_CONDITIONAL(STATIC_MSN, test "x$static_msn" = "xyes") +AM_CONDITIONAL(STATIC_MYSPACE, test "x$static_myspace" = "xyes") AM_CONDITIONAL(STATIC_NOVELL, test "x$static_novell" = "xyes") AM_CONDITIONAL(STATIC_OSCAR, test "x$static_oscar" = "xyes") AM_CONDITIONAL(STATIC_QQ, test "x$static_qq" = "xyes") @@ -939,7 +941,7 @@ AC_ARG_WITH(dynamic_prpls, [AC_HELP_STRING([--with-dynamic-prpls], [specify which protocols to build dynamically])], [DYNAMIC_PRPLS=`echo $withval | $sedpath 's/,/ /g'`]) if test "x$DYNAMIC_PRPLS" = "xall" ; then - DYNAMIC_PRPLS="bonjour gg irc jabber msn novell oscar qq sametime silc simple yahoo zephyr" + DYNAMIC_PRPLS="bonjour gg irc jabber msn myspace novell oscar qq sametime silc simple yahoo zephyr" fi if test "x$have_meanwhile" != "xyes"; then DYNAMIC_PRPLS=`echo $DYNAMIC_PRPLS | $sedpath 's/sametime//'` @@ -963,6 +965,7 @@ irc) dynamic_irc=yes ;; jabber) dynamic_jabber=yes ;; msn) dynamic_msn=yes ;; + myspace) dynamic_myspace=yes ;; novell) dynamic_novell=yes ;; oscar) dynamic_oscar=yes ;; aim) dynamic_oscar=yes ;; @@ -983,6 +986,7 @@ AM_CONDITIONAL(DYNAMIC_IRC, test "x$dynamic_irc" = "xyes") AM_CONDITIONAL(DYNAMIC_JABBER, test "x$dynamic_jabber" = "xyes") AM_CONDITIONAL(DYNAMIC_MSN, test "x$dynamic_msn" = "xyes") +AM_CONDITIONAL(DYNAMIC_MYSPACE, test "x$dynamic_myspace" = "xyes") AM_CONDITIONAL(DYNAMIC_NOVELL, test "x$dynamic_novell" = "xyes") AM_CONDITIONAL(DYNAMIC_OSCAR, test "x$dynamic_oscar" = "xyes") AM_CONDITIONAL(DYNAMIC_QQ, test "x$dynamic_qq" = "xyes") @@ -1089,7 +1093,7 @@ dnl ####################################################################### AC_ARG_ENABLE(dbus, [AC_HELP_STRING([--enable-dbus], [enable D-Bus support])], , enable_dbus=yes) -AC_ARG_ENABLE(nm, [AC_HELP_STRING([--enable-nm], [enable NetworkManager support (buggy) (requires D-Bus)])], enable_libnm=yes, enable_libnm=no) +AC_ARG_ENABLE(nm, [AC_HELP_STRING([--enable-nm], [enable NetworkManager support (buggy) (requires D-Bus)])], enable_libnm=$enableval, enable_libnm=no) if test "x$enable_dbus" = "xyes" ; then AC_CHECK_PROG(enable_dbus, dbus-binding-tool, yes, no) @@ -2135,6 +2139,9 @@ pidgin/pixmaps/protocols/48/Makefile pidgin/pixmaps/protocols/48/scalable/Makefile pidgin/pixmaps/status/Makefile + pidgin/pixmaps/status/11/Makefile + pidgin/pixmaps/status/11/scalable/Makefile + pidgin/pixmaps/status/11/rtl/Makefile pidgin/pixmaps/status/16/Makefile pidgin/pixmaps/status/16/rtl/Makefile pidgin/pixmaps/status/16/scalable/Makefile @@ -2185,6 +2192,7 @@ libpurple/protocols/irc/Makefile libpurple/protocols/jabber/Makefile libpurple/protocols/msn/Makefile + libpurple/protocols/myspace/Makefile libpurple/protocols/novell/Makefile libpurple/protocols/null/Makefile libpurple/protocols/oscar/Makefile @@ -2203,6 +2211,7 @@ finch/Makefile finch/libgnt/Makefile finch/libgnt/gnt.pc + finch/libgnt/pygnt/Makefile finch/libgnt/wms/Makefile finch/plugins/Makefile po/Makefile.in
--- a/doc/funniest_home_convos.txt Fri Aug 17 02:26:42 2007 +0000 +++ b/doc/funniest_home_convos.txt Mon Aug 27 21:59:11 2007 +0000 @@ -474,3 +474,16 @@ 19:23 <-- elb has quit (K-lined) +19:01 <user> whoa +19:01 <user> okay +19:01 <user> now when i try to go into the left over files after the + uninstall +19:01 <user> something is seriously wrong because it says "the files on the + c drive are not formatted, would you like to format?" +19:03 <user> manually deleting the folder from command gives me a "Data + error (cyclic redundancy check)." +19:03 <elb> remember, one line per thought +19:03 <elb> and yes, you have something wrong with your computer, we've + established that +19:03 <user> its functioning just fine +
--- a/finch/gntaccount.c Fri Aug 17 02:26:42 2007 +0000 +++ b/finch/gntaccount.c Mon Aug 27 21:59:11 2007 +0000 @@ -222,6 +222,11 @@ /* XXX: Proxy options */ + if (accounts.window && accounts.tree) { + gnt_tree_set_selected(GNT_TREE(accounts.tree), account); + gnt_box_give_focus_to_child(GNT_BOX(accounts.window), accounts.tree); + } + gnt_widget_destroy(dialog->window); }
--- a/finch/gntblist.c Fri Aug 17 02:26:42 2007 +0000 +++ b/finch/gntblist.c Mon Aug 27 21:59:11 2007 +0000 @@ -1292,8 +1292,11 @@ account = purple_buddy_get_account(buddy); presence = purple_buddy_get_presence(buddy); - if (!full || g_utf8_collate(purple_buddy_get_name(buddy), alias)) - purple_notify_user_info_add_pair(user_info, _("Nickname"), alias); + 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); + } tmp = g_strdup_printf("%s (%s)", purple_account_get_username(account), @@ -2136,20 +2139,29 @@ } } -static void -account_signed_on_cb(PurpleConnection *pc, gpointer null) +static gboolean +auto_join_chats(gpointer data) { PurpleBlistNode *node; + PurpleConnection *pc = data; + PurpleAccount *account = purple_connection_get_account(pc); for (node = purple_blist_get_root(); node; node = purple_blist_node_next(node, FALSE)) { if (PURPLE_BLIST_NODE_IS_CHAT(node)) { PurpleChat *chat = (PurpleChat*)node; - if (chat->account == purple_connection_get_account(pc) && + if (chat->account == account && purple_blist_node_get_bool(node, "gnt-autojoin")) serv_join_chat(purple_account_get_connection(chat->account), chat->components); } } + return FALSE; +} + +static void +account_signed_on_cb(PurpleConnection *gc, gpointer null) +{ + g_idle_add(auto_join_chats, gc); } static void toggle_pref_cb(GntMenuItem *item, gpointer n)
--- a/finch/gntconv.c Fri Aug 17 02:26:42 2007 +0000 +++ b/finch/gntconv.c Mon Aug 27 21:59:11 2007 +0000 @@ -37,6 +37,7 @@ #include "gntdebug.h" #include "gntplugin.h" #include "gntprefs.h" +#include "gntsound.h" #include "gntstatus.h" #include "gntpounce.h" @@ -60,6 +61,7 @@ static void finch_write_common(PurpleConversation *conv, const char *who, const char *message, PurpleMessageFlags flags, time_t mtime); +static void generate_send_to_menu(FinchConv *ggc); static void send_typing_notification(GntWidget *w, FinchConv *ggconv) @@ -141,6 +143,11 @@ } g_free(error); } + else if (!purple_account_is_connected(ggconv->active_conv->account)) + { + purple_conversation_write(ggconv->active_conv, "", _("Message was not sent, because you are not signed on."), + PURPLE_MESSAGE_ERROR | PURPLE_MESSAGE_NO_LOG, time(NULL)); + } else { char *escape = g_markup_escape_text(text, -1); @@ -199,10 +206,10 @@ } static PurpleConversation * -find_conv_with_contact(PurpleConversation *conv) +find_conv_with_contact(PurpleAccount *account, const char *name) { PurpleBlistNode *node; - PurpleBuddy *buddy = purple_find_buddy(conv->account, conv->name); + PurpleBuddy *buddy = purple_find_buddy(account, name); PurpleConversation *ret = NULL; if (!buddy) @@ -272,6 +279,28 @@ PURPLE_MESSAGE_SYSTEM, time(NULL)); } +static void +buddy_signed_on_off(PurpleBuddy *buddy, gpointer null) +{ + PurpleConversation *conv = find_conv_with_contact(buddy->account, buddy->name); + if (conv == NULL) + return; + generate_send_to_menu(conv->ui_data); +} + +static void +account_signed_on_off(PurpleConnection *gc, gpointer null) +{ + GList *ims = purple_get_ims(); + while (ims) { + PurpleConversation *conv = ims->data; + PurpleConversation *cc = find_conv_with_contact(conv->account, conv->name); + if (cc) + generate_send_to_menu(cc->ui_data); + ims = ims->next; + } +} + static gpointer finch_conv_get_handle() { @@ -319,6 +348,53 @@ } static void +toggle_logging_cb(GntMenuItem *item, gpointer ggconv) +{ + FinchConv *fc = ggconv; + PurpleConversation *conv = fc->active_conv; + gboolean logging = gnt_menuitem_check_get_checked(GNT_MENU_ITEM_CHECK(item)); + GList *iter; + + if (logging == purple_conversation_is_logging(conv)) + return; + + /* Xerox */ + if (logging) { + /* Enable logging first so the message below can be logged. */ + purple_conversation_set_logging(conv, TRUE); + + purple_conversation_write(conv, NULL, + _("Logging started. Future messages in this conversation will be logged."), + conv->logs ? (PURPLE_MESSAGE_SYSTEM) : + (PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LOG), + time(NULL)); + } else { + purple_conversation_write(conv, NULL, + _("Logging stopped. Future messages in this conversation will not be logged."), + conv->logs ? (PURPLE_MESSAGE_SYSTEM) : + (PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LOG), + time(NULL)); + + /* Disable the logging second, so that the above message can be logged. */ + purple_conversation_set_logging(conv, FALSE); + } + + /* Each conversation with the same person will have the same logging setting */ + for (iter = fc->list; iter; iter = iter->next) { + if (iter->data == conv) + continue; + purple_conversation_set_logging(iter->data, logging); + } +} + +static void +toggle_sound_cb(GntMenuItem *item, gpointer ggconv) +{ + FinchConv *fc = ggconv; + fc->flags ^= FINCH_CONV_NO_SOUND; +} + +static void send_to_cb(GntMenuItem *m, gpointer n) { PurpleAccount *account = g_object_get_data(G_OBJECT(m), "purple_account"); @@ -339,12 +415,15 @@ if (!buds) return; - item = gnt_menuitem_new(_("Send To")); - gnt_menu_add_item(GNT_MENU(menu), item); + if ((item = ggc->u.im->sendto) == NULL) { + item = gnt_menuitem_new(_("Send To")); + gnt_menu_add_item(GNT_MENU(menu), item); + ggc->u.im->sendto = item; + } sub = gnt_menu_new(GNT_MENU_POPUP); gnt_menuitem_set_submenu(item, GNT_MENU(sub)); - for (; buds; buds = buds->next) { + for (; buds; buds = g_slist_delete_link(buds, buds)) { PurpleBlistNode *node = (PurpleBlistNode *)purple_buddy_get_contact((PurpleBuddy *)buds->data); for (node = node->child; node != NULL; node = node->next) { PurpleBuddy *buddy = (PurpleBuddy *)node; @@ -357,7 +436,7 @@ } } } - for (list = g_list_last(list); list != NULL; list = list->prev) { + for (list = g_list_reverse(list); list != NULL; list = g_list_delete_link(list, list)) { PurplePresence *pre = list->data; PurpleBuddy *buddy = purple_presence_get_buddy(pre); PurpleAccount *account = purple_buddy_get_account(buddy); @@ -370,8 +449,6 @@ g_object_set_data(G_OBJECT(item), "purple_account", account); g_object_set_data_full(G_OBJECT(item), "purple_buddy_name", name, g_free); } - g_list_free(list); - g_slist_free(buds); } static void @@ -423,6 +500,18 @@ generate_send_to_menu(ggc); } + + item = gnt_menuitem_check_new(_("Enable Logging")); + gnt_menuitem_check_set_checked(GNT_MENU_ITEM_CHECK(item), + purple_conversation_is_logging(ggc->active_conv)); + gnt_menu_add_item(GNT_MENU(sub), item); + gnt_menuitem_set_callback(item, toggle_logging_cb, ggc); + + item = gnt_menuitem_check_new(_("Enable Sounds")); + gnt_menuitem_check_set_checked(GNT_MENU_ITEM_CHECK(item), + !(ggc->flags & FINCH_CONV_NO_SOUND)); + gnt_menu_add_item(GNT_MENU(sub), item); + gnt_menuitem_set_callback(item, toggle_sound_cb, ggc); } static void @@ -462,12 +551,18 @@ if (ggc) return; - cc = find_conv_with_contact(conv); + cc = find_conv_with_contact(conv->account, conv->name); if (cc && cc->ui_data) ggc = cc->ui_data; else ggc = g_new0(FinchConv, 1); + /* Each conversation with the same person will have the same logging setting */ + if (ggc->list) { + purple_conversation_set_logging(conv, + purple_conversation_is_logging(ggc->list->data)); + } + ggc->list = g_list_prepend(ggc->list, conv); ggc->active_conv = conv; conv->ui_data = ggc; @@ -504,8 +599,6 @@ break; } - gg_create_menu(ggc); - ggc->tv = gnt_text_view_new(); gnt_widget_set_name(ggc->tv, "conversation-window-textview"); gnt_widget_set_size(ggc->tv, purple_prefs_get_int(PREF_ROOT "/size/width"), @@ -527,6 +620,7 @@ g_signal_connect(G_OBJECT(tree), "activate", G_CALLBACK(create_conv_from_userlist), ggc); gnt_widget_set_visible(tree, purple_prefs_get_bool(PREF_USERLIST)); } else { + ggc->u.im = g_new0(FinchConvIm, 1); gnt_box_add_widget(GNT_BOX(ggc->window), ggc->tv); } @@ -558,6 +652,11 @@ g_signal_connect(G_OBJECT(ggc->entry), "text_changed", G_CALLBACK(send_typing_notification), ggc); } + if (!finch_sound_is_enabled()) + ggc->flags |= FINCH_CONV_NO_SOUND; + + gg_create_menu(ggc); + g_free(title); gnt_box_give_focus_to_child(GNT_BOX(ggc->window), ggc->entry); g_signal_connect(G_OBJECT(ggc->window), "gained-focus", G_CALLBACK(gained_focus_cb), ggc); @@ -800,6 +899,23 @@ gnt_tree_change_text(GNT_TREE(ggc->u.chat->userlist), (gpointer)user, 0, chat_flag_text(cb->flags)); } +static void +finch_conv_present(PurpleConversation *conv) +{ + FinchConv *fc = FINCH_CONV(conv); + if (fc && fc->window) + return gnt_window_present(fc->window); +} + +static gboolean +finch_conv_has_focus(PurpleConversation *conv) +{ + FinchConv *fc = FINCH_CONV(conv); + if (fc && fc->window) + return gnt_widget_has_focus(fc->window); + return FALSE; +} + static PurpleConversationUiOps conv_ui_ops = { finch_create_conversation, @@ -811,8 +927,8 @@ finch_chat_rename_user, finch_chat_remove_users, finch_chat_update_user, - NULL, /* present */ - NULL, /* has_focus */ + finch_conv_present, /* present */ + finch_conv_has_focus, /* has_focus */ NULL, /* custom_smiley_add */ NULL, /* custom_smiley_write */ NULL, /* custom_smiley_close */ @@ -1016,6 +1132,14 @@ PURPLE_CALLBACK(update_buddy_typing), NULL); purple_signal_connect(purple_conversations_get_handle(), "chat-left", finch_conv_get_handle(), PURPLE_CALLBACK(chat_left_cb), NULL); + purple_signal_connect(purple_blist_get_handle(), "buddy-signed-on", finch_conv_get_handle(), + PURPLE_CALLBACK(buddy_signed_on_off), NULL); + purple_signal_connect(purple_blist_get_handle(), "buddy-signed-off", finch_conv_get_handle(), + PURPLE_CALLBACK(buddy_signed_on_off), NULL); + purple_signal_connect(purple_connections_get_handle(), "signed-on", finch_conv_get_handle(), + PURPLE_CALLBACK(account_signed_on_off), NULL); + purple_signal_connect(purple_connections_get_handle(), "signed-off", finch_conv_get_handle(), + PURPLE_CALLBACK(account_signed_on_off), NULL); } void finch_conversation_uninit()
--- a/finch/gntconv.h Fri Aug 17 02:26:42 2007 +0000 +++ b/finch/gntconv.h Mon Aug 27 21:59:11 2007 +0000 @@ -27,6 +27,7 @@ #include <gnt.h> #include <gntwidget.h> +#include <gntmenuitem.h> #include "conversation.h" @@ -42,6 +43,11 @@ typedef struct _FinchConvChat FinchConvChat; typedef struct _FinchConvIm FinchConvIm; +typedef enum +{ + FINCH_CONV_NO_SOUND = 1 << 0, +} FinchConversationFlag; + struct _FinchConv { GList *list; @@ -50,9 +56,9 @@ GntWidget *window; /* the container */ GntWidget *entry; /* entry */ GntWidget *tv; /* text-view */ - GntWidget *menu; /* future use */ + GntWidget *menu; GntWidget *info; - void *pad; + FinchConversationFlag flags; union { @@ -70,7 +76,7 @@ struct _FinchConvIm { - void *nothing_for_now; + GntMenuItem *sendto; void *something_for_later; };
--- a/finch/gntft.c Fri Aug 17 02:26:42 2007 +0000 +++ b/finch/gntft.c Mon Aug 27 21:59:11 2007 +0000 @@ -193,6 +193,8 @@ g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(finch_xfer_dialog_destroy), NULL); gnt_box_set_toplevel(GNT_BOX(window), TRUE); gnt_box_set_title(GNT_BOX(window), _("File Transfers")); + gnt_box_set_fill(GNT_BOX(window), TRUE); + gnt_box_set_alignment(GNT_BOX(window), GNT_ALIGN_MID); xfer_dialog->tree = tree = gnt_tree_new_with_columns(NUM_COLUMNS); gnt_tree_set_column_titles(GNT_TREE(tree), _("Progress"), _("Filename"), _("Size"), _("Speed"), _("Remaining"), _("Status")); @@ -219,7 +221,7 @@ G_CALLBACK(toggle_clear_finished_cb), NULL); gnt_box_add_widget(GNT_BOX(window), checkbox); - bbox = gnt_hbox_new(TRUE); + bbox = gnt_hbox_new(FALSE); xfer_dialog->remove_button = button = gnt_button_new(_("Remove")); g_signal_connect(G_OBJECT(button), "activate", @@ -425,8 +427,11 @@ g_free(remaining_str); g_free(kbsec); if (purple_xfer_is_completed(xfer)) { + char *msg = g_strdup_printf(_("The file was saved as %s."), purple_xfer_get_local_filename(xfer)); gnt_tree_change_text(GNT_TREE(xfer_dialog->tree), xfer, COLUMN_STATUS, _("Finished")); gnt_tree_change_text(GNT_TREE(xfer_dialog->tree), xfer, COLUMN_REMAINING, _("Finished")); + purple_xfer_conversation_write(xfer, msg, FALSE); + g_free(msg); } else { gnt_tree_change_text(GNT_TREE(xfer_dialog->tree), xfer, COLUMN_STATUS, _("Transferring")); }
--- a/finch/gntpounce.c Fri Aug 17 02:26:42 2007 +0000 +++ b/finch/gntpounce.c Mon Aug 27 21:59:11 2007 +0000 @@ -452,7 +452,7 @@ gnt_box_add_widget(GNT_BOX(window), gnt_line_new(FALSE)); /* Now the button box! */ - bbox = gnt_hbox_new(TRUE); + bbox = gnt_hbox_new(FALSE); /* Cancel button */ button = gnt_button_new(_("Cancel")); @@ -613,6 +613,12 @@ static void pounces_manager_add_cb(GntButton *button, gpointer user_data) { + if (purple_accounts_get_all() == NULL) { + purple_notify_error(NULL, _("Cannot create pounce"), + _("You do not have any accounts."), + _("You must create an account first before you can create a pounce.")); + return; + } finch_pounce_editor_show(NULL, NULL, NULL); } @@ -622,7 +628,8 @@ { PouncesManager *dialog = user_data; PurplePounce *pounce = gnt_tree_get_selection_data(GNT_TREE(dialog->tree)); - finch_pounce_editor_show(NULL, NULL, pounce); + if (pounce) + finch_pounce_editor_show(NULL, NULL, pounce); } static void @@ -645,6 +652,9 @@ char *buf; pounce = (PurplePounce *)gnt_tree_get_selection_data(GNT_TREE(dialog->tree)); + if (pounce == NULL) + return; + account = purple_pounce_get_pouncer(pounce); pouncer = purple_account_get_username(account); pouncee = purple_pounce_get_pouncee(pounce); @@ -696,7 +706,7 @@ gnt_box_add_widget(GNT_BOX(win), tree); /* Button box. */ - bbox = gnt_hbox_new(TRUE); + bbox = gnt_hbox_new(FALSE); /* Add button */ button = gnt_button_new(_("Add"));
--- a/finch/gntsound.c Fri Aug 17 02:26:42 2007 +0000 +++ b/finch/gntsound.c Mon Aug 27 21:59:11 2007 +0000 @@ -40,6 +40,8 @@ #include "sound.h" #include "util.h" +#include "gntconv.h" + #include "gntbox.h" #include "gntwindow.h" #include "gntcombobox.h" @@ -173,7 +175,8 @@ has_focus = purple_conversation_has_focus(conv); - if (has_focus && !purple_prefs_get_bool(make_pref("/conv_focus"))) + if ((gntconv->flags & FINCH_CONV_NO_SOUND) || + (has_focus && !purple_prefs_get_bool(make_pref("/conv_focus")))) { return; } @@ -300,15 +303,15 @@ purple_prefs_add_none(make_pref("")); purple_prefs_add_none(make_pref("/enabled")); purple_prefs_add_none(make_pref("/file")); - purple_prefs_add_bool(make_pref("/enabled/login"), TRUE); + purple_prefs_add_bool(make_pref("/enabled/login"), FALSE); purple_prefs_add_path(make_pref("/file/login"), ""); - purple_prefs_add_bool(make_pref("/enabled/logout"), TRUE); + purple_prefs_add_bool(make_pref("/enabled/logout"), FALSE); purple_prefs_add_path(make_pref("/file/logout"), ""); - purple_prefs_add_bool(make_pref("/enabled/im_recv"), TRUE); + purple_prefs_add_bool(make_pref("/enabled/im_recv"), FALSE); purple_prefs_add_path(make_pref("/file/im_recv"), ""); purple_prefs_add_bool(make_pref("/enabled/first_im_recv"), FALSE); purple_prefs_add_path(make_pref("/file/first_im_recv"), ""); - purple_prefs_add_bool(make_pref("/enabled/send_im"), TRUE); + purple_prefs_add_bool(make_pref("/enabled/send_im"), FALSE); purple_prefs_add_path(make_pref("/file/send_im"), ""); purple_prefs_add_bool(make_pref("/enabled/join_chat"), FALSE); purple_prefs_add_path(make_pref("/file/join_chat"), ""); @@ -320,9 +323,9 @@ purple_prefs_add_path(make_pref("/file/chat_msg_recv"), ""); purple_prefs_add_bool(make_pref("/enabled/nick_said"), FALSE); purple_prefs_add_path(make_pref("/file/nick_said"), ""); - purple_prefs_add_bool(make_pref("/enabled/pounce_default"), TRUE); + purple_prefs_add_bool(make_pref("/enabled/pounce_default"), FALSE); purple_prefs_add_path(make_pref("/file/pounce_default"), ""); - purple_prefs_add_bool(make_pref("/conv_focus"), TRUE); + purple_prefs_add_bool(make_pref("/conv_focus"), FALSE); purple_prefs_add_bool(make_pref("/mute"), FALSE); purple_prefs_add_path(make_pref("/command"), ""); purple_prefs_add_string(make_pref("/method"), "automatic"); @@ -409,14 +412,14 @@ GError *err = NULL; switch (GST_MESSAGE_TYPE (msg)) { - case GST_MESSAGE_EOS: - gst_element_set_state(play, GST_STATE_NULL); - gst_object_unref(GST_OBJECT(play)); - break; case GST_MESSAGE_ERROR: gst_message_parse_error(msg, &err, NULL); purple_debug_error("gstreamer", "%s\n", err->message); g_error_free(err); + /* fall-through and clean up */ + case GST_MESSAGE_EOS: + gst_element_set_state(play, GST_STATE_NULL); + gst_object_unref(GST_OBJECT(play)); break; case GST_MESSAGE_WARNING: gst_message_parse_warning(msg, &err, NULL); @@ -446,7 +449,7 @@ method = purple_prefs_get_string(make_pref("/method")); - if (!strcmp(method, "none")) { + if (!strcmp(method, "nosound")) { return; } else if (!strcmp(method, "beep")) { beep(); @@ -670,28 +673,34 @@ { PurpleSoundEventID id = GPOINTER_TO_INT(gnt_tree_get_selection_data(GNT_TREE(pref_dialog->events))); FinchSoundEvent * event = &sounds[id]; - char *enabled, *file, *tmpfile; + char *enabled, *file, *tmpfile, *volpref; gboolean temp_value; + int volume; enabled = g_strdup_printf(FINCH_PREFS_ROOT "/sound/profiles/%s/enabled/%s", finch_sound_get_active_profile(), event->pref); file = g_strdup_printf(FINCH_PREFS_ROOT "/sound/profiles/%s/file/%s", finch_sound_get_active_profile(), event->pref); + volpref = g_strdup(make_pref("/volume")); temp_value = purple_prefs_get_bool(enabled); tmpfile = g_strdup(purple_prefs_get_string(file)); + volume = purple_prefs_get_int(volpref); purple_prefs_set_string(file, event->file); if (!temp_value) purple_prefs_set_bool(enabled, TRUE); + purple_prefs_set_int(volpref, gnt_slider_get_value(GNT_SLIDER(pref_dialog->volume))); purple_sound_play_event(id, NULL); if (!temp_value) purple_prefs_set_bool(enabled, FALSE); purple_prefs_set_string(file, tmpfile); + purple_prefs_set_int(volpref, volume); g_free(enabled); g_free(file); g_free(tmpfile); + g_free(volpref); } static void @@ -747,6 +756,7 @@ } if (pref_dialog->selector) gnt_widget_destroy(pref_dialog->selector); + g_free(pref_dialog->original_profile); g_free(pref_dialog); pref_dialog = NULL; } @@ -989,6 +999,8 @@ pref_dialog->volume = slider = gnt_slider_new(FALSE, 100, 0); gnt_slider_set_step(GNT_SLIDER(slider), 5); + gnt_slider_set_small_step(GNT_SLIDER(slider), 1); + gnt_slider_set_large_step(GNT_SLIDER(slider), 20); label = gnt_label_new(""); gnt_slider_reflect_label(GNT_SLIDER(slider), GNT_LABEL(label)); gnt_box_set_pad(GNT_BOX(tmpbox), 1); @@ -1052,7 +1064,22 @@ load_pref_window(finch_sound_get_active_profile()); gnt_widget_show(win); -} +} + +gboolean finch_sound_is_enabled(void) +{ + const char *pref = make_pref("/method"); + const char *method = purple_prefs_get_string(pref); + + if (!method) + return FALSE; + if (strcmp(method, "nosound") == 0) + return FALSE; + if (purple_prefs_get_int(make_pref("/volume")) <= 0) + return FALSE; + + return TRUE; +} static PurpleSoundUiOps sound_ui_ops = {
--- a/finch/gntsound.h Fri Aug 17 02:26:42 2007 +0000 +++ b/finch/gntsound.h Mon Aug 27 21:59:11 2007 +0000 @@ -55,6 +55,14 @@ GList *finch_sound_get_profiles(void); /** + * Determine whether any sound will be played or not. + * + * @return Returns FALSE if preference is set to 'No sound', or if volume is + * set to zero. + */ +gboolean finch_sound_is_enabled(void); + +/** * Gets GNT sound UI ops. * * @return The UI operations structure.
--- a/finch/gntstatus.c Fri Aug 17 02:26:42 2007 +0000 +++ b/finch/gntstatus.c Mon Aug 27 21:59:11 2007 +0000 @@ -299,6 +299,7 @@ { purple_notify_error(edit, _("Error"), _("Invalid title"), _("Please enter a non-empty title for the status.")); + gnt_box_give_focus_to_child(GNT_BOX(edit->window), edit->title); return; } @@ -307,6 +308,7 @@ { purple_notify_error(edit, _("Error"), _("Duplicate title"), _("Please enter a different title for the status.")); + gnt_box_give_focus_to_child(GNT_BOX(edit->window), edit->title); return; } @@ -447,6 +449,7 @@ sub->window = window = gnt_vbox_new(FALSE); gnt_box_set_toplevel(GNT_BOX(window), TRUE); gnt_box_set_title(GNT_BOX(window), _("Substatus")); /* XXX: a better title */ + gnt_box_set_alignment(GNT_BOX(window), GNT_ALIGN_MID); box = gnt_hbox_new(FALSE); gnt_box_add_widget(GNT_BOX(box), gnt_label_new(_("Account:"))); @@ -523,7 +526,7 @@ gnt_box_set_toplevel(GNT_BOX(window), TRUE); gnt_box_set_title(GNT_BOX(window), _("Edit Status")); gnt_box_set_fill(GNT_BOX(window), TRUE); - gnt_box_set_alignment(GNT_BOX(window), GNT_ALIGN_LEFT); + gnt_box_set_alignment(GNT_BOX(window), GNT_ALIGN_MID); gnt_box_set_pad(GNT_BOX(window), 0); edits = g_list_append(edits, edit);
--- a/finch/libgnt/configure.ac Fri Aug 17 02:26:42 2007 +0000 +++ b/finch/libgnt/configure.ac Mon Aug 27 21:59:11 2007 +0000 @@ -24,9 +24,9 @@ # Make sure to update ../../configure.ac with libgnt version changes. # -m4_define([gnt_lt_current], [1]) +m4_define([gnt_lt_current], [2]) m4_define([gnt_major_version], [2]) -m4_define([gnt_minor_version], [1]) +m4_define([gnt_minor_version], [2]) m4_define([gnt_micro_version], [0]) m4_define([gnt_version_suffix], [devel]) m4_define([gnt_version],
--- a/finch/libgnt/gnt.h Fri Aug 17 02:26:42 2007 +0000 +++ b/finch/libgnt/gnt.h Mon Aug 27 21:59:11 2007 +0000 @@ -37,6 +37,15 @@ #include "gntkeys.h" /** + * Get things to compile in Glib < 2.8 + */ +#if !GLIB_CHECK_VERSION(2,8,0) + #define G_PARAM_STATIC_NAME G_PARAM_PRIVATE + #define G_PARAM_STATIC_NICK G_PARAM_PRIVATE + #define G_PARAM_STATIC_BLURB G_PARAM_PRIVATE +#endif + +/** * */ void gnt_init(void);
--- a/finch/libgnt/gntbutton.c Fri Aug 17 02:26:42 2007 +0000 +++ b/finch/libgnt/gntbutton.c Mon Aug 27 21:59:11 2007 +0000 @@ -111,6 +111,7 @@ style = gnt_style_get_from_name(NULL, "small-button"); small_button = gnt_style_parse_bool(style); + g_free(style); GNTDEBUG; }
--- a/finch/libgnt/gntcolors.c Fri Aug 17 02:26:42 2007 +0000 +++ b/finch/libgnt/gntcolors.c Mon Aug 27 21:59:11 2007 +0000 @@ -133,6 +133,7 @@ restore_colors(); } +#if GLIB_CHECK_VERSION(2,6,0) static int get_color(char *key) { @@ -164,7 +165,6 @@ return color; } -#if GLIB_CHECK_VERSION(2,6,0) void gnt_colors_parse(GKeyFile *kfile) { GError *error = NULL;
--- a/finch/libgnt/gntfilesel.c Fri Aug 17 02:26:42 2007 +0000 +++ b/finch/libgnt/gntfilesel.c Mon Aug 27 21:59:11 2007 +0000 @@ -200,7 +200,7 @@ const char *tmp; tmp = sel->suggest ? sel->suggest : (const char*)gnt_tree_get_selection_data(sel->dirsonly ? GNT_TREE(sel->dirs) : GNT_TREE(sel->files)); - old = g_strdup_printf("%s%s%s", sel->current, sel->current[1] ? G_DIR_SEPARATOR_S : "", tmp ? tmp : ""); + old = g_strdup_printf("%s%s%s", SAFE(sel->current), SAFE(sel->current)[1] ? G_DIR_SEPARATOR_S : "", tmp ? tmp : ""); gnt_entry_set_text(GNT_ENTRY(sel->location), old); g_free(old); }
--- a/finch/libgnt/gntslider.c Fri Aug 17 02:26:42 2007 +0000 +++ b/finch/libgnt/gntslider.c Mon Aug 27 21:59:11 2007 +0000 @@ -125,22 +125,66 @@ step_back(GntBindable *bindable, GList *null) { GntSlider *slider = GNT_SLIDER(bindable); - if (slider->current <= slider->min) - return FALSE; gnt_slider_advance_step(slider, -1); return TRUE; } static gboolean +small_step_back(GntBindable *bindable, GList *null) +{ + GntSlider *slider = GNT_SLIDER(bindable); + gnt_slider_set_value(slider, slider->current - slider->smallstep); + return TRUE; +} + +static gboolean +large_step_back(GntBindable *bindable, GList *null) +{ + GntSlider *slider = GNT_SLIDER(bindable); + gnt_slider_set_value(slider, slider->current - slider->largestep); + return TRUE; +} + +static gboolean step_forward(GntBindable *bindable, GList *list) { GntSlider *slider = GNT_SLIDER(bindable); - if (slider->current >= slider->max) - return FALSE; gnt_slider_advance_step(slider, 1); return TRUE; } +static gboolean +small_step_forward(GntBindable *bindable, GList *null) +{ + GntSlider *slider = GNT_SLIDER(bindable); + gnt_slider_set_value(slider, slider->current + slider->smallstep); + return TRUE; +} + +static gboolean +large_step_forward(GntBindable *bindable, GList *null) +{ + GntSlider *slider = GNT_SLIDER(bindable); + gnt_slider_set_value(slider, slider->current + slider->largestep); + return TRUE; +} + +static gboolean +move_min_value(GntBindable *bindable, GList *null) +{ + GntSlider *slider = GNT_SLIDER(bindable); + gnt_slider_set_value(slider, slider->min); + return TRUE; +} + +static gboolean +move_max_value(GntBindable *bindable, GList *null) +{ + GntSlider *slider = GNT_SLIDER(bindable); + gnt_slider_set_value(slider, slider->max); + return TRUE; +} + static void gnt_slider_class_init(GntSliderClass *klass) { @@ -165,8 +209,14 @@ gnt_bindable_register_binding(bindable, "step-backward", GNT_KEY_DOWN, NULL); gnt_bindable_class_register_action(bindable, "step-forward", step_forward, GNT_KEY_RIGHT, NULL); gnt_bindable_register_binding(bindable, "step-forward", GNT_KEY_UP, NULL); - - /* XXX: how would home/end work? */ + gnt_bindable_class_register_action(bindable, "small-step-backward", small_step_back, GNT_KEY_CTRL_LEFT, NULL); + gnt_bindable_register_binding(bindable, "small-step-backward", GNT_KEY_CTRL_DOWN, NULL); + gnt_bindable_class_register_action(bindable, "small-step-forward", small_step_forward, GNT_KEY_CTRL_RIGHT, NULL); + gnt_bindable_register_binding(bindable, "small-step-forward", GNT_KEY_CTRL_UP, NULL); + gnt_bindable_class_register_action(bindable, "large-step-backward", large_step_back, GNT_KEY_PGDOWN, NULL); + gnt_bindable_class_register_action(bindable, "large-step-forward", large_step_forward, GNT_KEY_PGUP, NULL); + gnt_bindable_class_register_action(bindable, "min-value", move_min_value, GNT_KEY_HOME, NULL); + gnt_bindable_class_register_action(bindable, "max-value", move_max_value, GNT_KEY_END, NULL); gnt_style_read_actions(G_OBJECT_CLASS_TYPE(klass), GNT_BINDABLE_CLASS(klass)); } @@ -233,10 +283,14 @@ void gnt_slider_set_value(GntSlider *slider, int value) { + int old; if (slider->current == value) return; + old = slider->current; slider->current = value; sanitize_value(slider); + if (old == slider->current) + return; redraw_slider(slider); slider_value_changed(slider); } @@ -248,10 +302,7 @@ int gnt_slider_advance_step(GntSlider *slider, int steps) { - slider->current += steps * slider->step; - sanitize_value(slider); - redraw_slider(slider); - slider_value_changed(slider); + gnt_slider_set_value(slider, slider->current + steps * slider->step); return slider->current; } @@ -260,6 +311,16 @@ slider->step = step; } +void gnt_slider_set_small_step(GntSlider *slider, int step) +{ + slider->smallstep = step; +} + +void gnt_slider_set_large_step(GntSlider *slider, int step) +{ + slider->largestep = step; +} + void gnt_slider_set_range(GntSlider *slider, int max, int min) { slider->max = MAX(max, min);
--- a/finch/libgnt/gntslider.h Fri Aug 17 02:26:42 2007 +0000 +++ b/finch/libgnt/gntslider.h Mon Aug 27 21:59:11 2007 +0000 @@ -56,6 +56,8 @@ int min; /* minimum value */ int step; /* amount to change at each step */ int current; /* current value */ + int smallstep; + int largestep; }; struct _GntSliderClass @@ -103,11 +105,27 @@ * Sets the amount of change at each step. * * @param slider The slider - * @param step The amount for each ste + * @param step The amount for each step */ void gnt_slider_set_step(GntSlider *slider, int step); /** + * Sets the amount of change a small step. + * + * @param slider The slider + * @param step The amount for a small step (for the slider) + */ +void gnt_slider_set_small_step(GntSlider *slider, int step); + +/** + * Sets the amount of change a large step. + * + * @param slider The slider + * @param step The amount for a large step (for the slider) + */ +void gnt_slider_set_large_step(GntSlider *slider, int step); + +/** * Advance the slider forward or backward. * * @param slider The slider
--- a/finch/libgnt/gntstyle.c Fri Aug 17 02:26:42 2007 +0000 +++ b/finch/libgnt/gntstyle.c Mon Aug 27 21:59:11 2007 +0000 @@ -55,6 +55,8 @@ if (!group) group = "general"; return g_key_file_get_value(gkfile, group, key, NULL); +#else + return NULL; #endif } @@ -93,6 +95,7 @@ return def; } +#if GLIB_CHECK_VERSION(2,6,0) static void refine(char *text) { @@ -133,6 +136,7 @@ { return (char *)gnt_key_translate(key); } +#endif void gnt_style_read_workspaces(GntWM *wm) {
--- a/finch/libgnt/gnttextview.c Fri Aug 17 02:26:42 2007 +0000 +++ b/finch/libgnt/gnttextview.c Mon Aug 27 21:59:11 2007 +0000 @@ -549,7 +549,8 @@ if ((end = strchr(start, '\r')) != NULL || (end = strchr(start, '\n')) != NULL) { len = gnt_util_onscreen_width(start, end - has_scroll); - if (len >= widget->priv.width - line->length - has_scroll) { + if (widget->priv.width > 0 && + len >= widget->priv.width - line->length - has_scroll) { end = NULL; } }
--- a/finch/libgnt/gnttree.c Fri Aug 17 02:26:42 2007 +0000 +++ b/finch/libgnt/gnttree.c Mon Aug 27 21:59:11 2007 +0000 @@ -985,11 +985,7 @@ g_param_spec_int("columns", "Columns", "Number of columns in the tree.", 1, G_MAXINT, 1, -#if GLIB_CHECK_VERSION(2,8,0) G_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB -#else - G_PARAM_READWRITE|G_PARAM_PRIVATE -#endif ) );
--- a/finch/libgnt/gntutils.c Fri Aug 17 02:26:42 2007 +0000 +++ b/finch/libgnt/gntutils.c Mon Aug 27 21:59:11 2007 +0000 @@ -376,6 +376,101 @@ #endif } +#ifndef NO_LIBXML +static void +util_parse_html_to_tv(xmlNode *node, GntTextView *tv, GntTextFormatFlags flag) +{ + const char *name; + char *content; + xmlNode *ch; + gboolean processed = FALSE; + char *url = NULL; + gboolean insert_nl_s = FALSE, insert_nl_e = FALSE; + + if (node == NULL || node->name == NULL || node->type != XML_ELEMENT_NODE) + return; + + name = (char*)node->name; + if (g_ascii_strcasecmp(name, "b") == 0 || + g_ascii_strcasecmp(name, "strong") == 0 || + g_ascii_strcasecmp(name, "i") == 0 || + g_ascii_strcasecmp(name, "blockquote") == 0) { + flag |= GNT_TEXT_FLAG_BOLD; + } else if (g_ascii_strcasecmp(name, "u") == 0) { + flag |= GNT_TEXT_FLAG_UNDERLINE; + } else if (g_ascii_strcasecmp(name, "br") == 0) { + insert_nl_e = TRUE; + } else if (g_ascii_strcasecmp(name, "a") == 0) { + flag |= GNT_TEXT_FLAG_UNDERLINE; + url = (char *)xmlGetProp(node, (xmlChar*)"href"); + } else if (g_ascii_strcasecmp(name, "h1") == 0 || + g_ascii_strcasecmp(name, "h2") == 0 || + g_ascii_strcasecmp(name, "h3") == 0 || + g_ascii_strcasecmp(name, "h4") == 0 || + g_ascii_strcasecmp(name, "h5") == 0 || + g_ascii_strcasecmp(name, "h6") == 0) { + insert_nl_s = TRUE; + insert_nl_e = TRUE; + } else if (g_ascii_strcasecmp(name, "title") == 0) { + insert_nl_s = TRUE; + insert_nl_e = TRUE; + flag |= GNT_TEXT_FLAG_BOLD | GNT_TEXT_FLAG_UNDERLINE; + } else { + /* XXX: Process other possible tags */ + } + + if (insert_nl_s) + gnt_text_view_append_text_with_flags(tv, "\n", flag); + + for (ch = node->children; ch; ch = ch->next) { + if (ch->type == XML_ELEMENT_NODE) { + processed = TRUE; + util_parse_html_to_tv(ch, tv, flag); + } + } + + if (!processed) { + content = (char*)xmlNodeGetContent(node); + gnt_text_view_append_text_with_flags(tv, content, flag); + xmlFree(content); + } + + if (url) { + char *href = g_strdup_printf(" (%s)", url); + gnt_text_view_append_text_with_flags(tv, href, flag); + g_free(href); + xmlFree(url); + } + + if (insert_nl_e) + gnt_text_view_append_text_with_flags(tv, "\n", flag); +} +#endif + +gboolean gnt_util_parse_xhtml_to_textview(const char *string, GntTextView *tv) +{ +#ifdef NO_LIBXML + return FALSE; +#else + xmlParserCtxtPtr ctxt; + xmlDocPtr doc; + xmlNodePtr node; + GntTextFormatFlags flag = GNT_TEXT_FLAG_NORMAL; + gboolean ret = FALSE; + + ctxt = xmlNewParserCtxt(); + doc = xmlCtxtReadDoc(ctxt, (xmlChar*)string, NULL, NULL, XML_PARSE_NOBLANKS | XML_PARSE_RECOVER); + if (doc) { + node = xmlDocGetRootElement(doc); + util_parse_html_to_tv(node, tv, flag); + xmlFreeDoc(doc); + ret = TRUE; + } + xmlCleanupParser(); + return ret; +#endif +} + /* Setup trigger widget */ typedef struct { char *text; @@ -408,4 +503,3 @@ g_signal_connect(G_OBJECT(wid), "key_pressed", G_CALLBACK(key_pressed), tb); g_signal_connect_swapped(G_OBJECT(button), "destroy", G_CALLBACK(free_trigger_button), tb); } -
--- a/finch/libgnt/gntutils.h Fri Aug 17 02:26:42 2007 +0000 +++ b/finch/libgnt/gntutils.h Mon Aug 27 21:59:11 2007 +0000 @@ -27,6 +27,7 @@ #include <glib.h> #include "gnt.h" +#include "gnttextview.h" #include "gntwidget.h" typedef gpointer (*GDupFunc)(gconstpointer data); @@ -132,6 +133,16 @@ void gnt_util_parse_widgets(const char *string, int num, ...); /** + * Parse an XHTML string and add it in a GntTextView with + * appropriate text flags. + * + * @param string The XHTML string + * @param tv The GntTextView + * @return @c TRUE if the string was added to the textview properly, @c FALSE otherwise. + */ +gboolean gnt_util_parse_xhtml_to_textview(const char *string, GntTextView *tv); + +/** * Make some keypress activate a button when some key is pressed with 'wid' in focus. * * @param widget The widget
--- a/finch/libgnt/gntwm.c Fri Aug 17 02:26:42 2007 +0000 +++ b/finch/libgnt/gntwm.c Mon Aug 27 21:59:11 2007 +0000 @@ -738,7 +738,7 @@ print = ch; #ifndef NO_WIDECHAR if (wch.chars[0] > 255) { - snprintf(unicode, sizeof(unicode), "&#x%x;", wch.chars[0]); + snprintf(unicode, sizeof(unicode), "&#x%x;", (unsigned int)wch.chars[0]); print = unicode; } #endif
--- a/finch/libgnt/test/tv.c Fri Aug 17 02:26:42 2007 +0000 +++ b/finch/libgnt/test/tv.c Mon Aug 27 21:59:11 2007 +0000 @@ -5,6 +5,7 @@ #include "gntbox.h" #include "gntentry.h" #include "gnttextview.h" +#include "gntutils.h" static gboolean key_pressed(GntWidget *w, const char *key, GntWidget *view) @@ -117,6 +118,8 @@ gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(view), "plugins: ", GNT_TEXT_FLAG_BOLD); gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(view), "this is the 4th line\n", GNT_TEXT_FLAG_NORMAL); + gnt_util_parse_xhtml_to_textview("<p><b>Ohoy hoy!!</b><br/><p>I think this is going to</p> <u> WORK!!! </u><a href='www.google.com'>check this out!!</a></p>", GNT_TEXT_VIEW(view)); + #ifdef STANDALONE gnt_main();
--- a/libpurple/Makefile.am Fri Aug 17 02:26:42 2007 +0000 +++ b/libpurple/Makefile.am Mon Aug 27 21:59:11 2007 +0000 @@ -22,9 +22,9 @@ win32/giowin32.c \ win32/win32dep.h -if USE_GCONFTOOL -GCONF_DIR=gconf -endif +# if USE_GCONFTOOL +# GCONF_DIR=gconf +# endif pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = purple.pc
--- a/libpurple/blist.c Fri Aug 17 02:26:42 2007 +0000 +++ b/libpurple/blist.c Mon Aug 27 21:59:11 2007 +0000 @@ -1190,6 +1190,12 @@ group = purple_group_new(_("Chats")); purple_blist_add_group(group, purple_blist_get_last_sibling(purplebuddylist->root)); + } else { + /* Add group to blist if isn't already on it. Fixes #2752. */ + if (!purple_find_group(group->name)) { + purple_blist_add_group(group, + purple_blist_get_last_sibling(purplebuddylist->root)); + } } } else { group = (PurpleGroup*)node->parent; @@ -1284,6 +1290,12 @@ g = (PurpleGroup *)((PurpleBlistNode *)c)->parent; } else { if (group) { + /* Add chat to blist if isn't already on it. Fixes #2752. */ + if (!purple_find_group(group->name)) { + purple_blist_add_group(group, + purple_blist_get_last_sibling(purplebuddylist->root)); + } + g = group; } else { g = purple_group_new(_("Buddies"));
--- a/libpurple/example/nullclient.c Fri Aug 17 02:26:42 2007 +0000 +++ b/libpurple/example/nullclient.c Mon Aug 27 21:59:11 2007 +0000 @@ -197,7 +197,7 @@ purple_util_set_user_dir(CUSTOM_USER_DIRECTORY); /* We do not want any debugging for now to keep the noise to a minimum. */ - purple_debug_set_enabled(FALSE); + purple_debug_set_enabled(TRUE); /* Set the core-uiops, which is used to * - initialize the ui specific preferences. @@ -257,6 +257,24 @@ PURPLE_CALLBACK(signed_on), NULL); } + + + +void signedOn( PurpleConnection *gc, gpointer dummy ) { + + + if( gc ) { + + PurpleAccount* a = purple_connection_get_account( gc ); + + if( a ) { + + purple_presence_set_idle( purple_account_get_presence( a ), TRUE, time( NULL ) ); + } + } +} + + int main() { GList *iter; @@ -282,30 +300,26 @@ names = g_list_append(names, info->id); } } - printf("Select the protocol [0-%d]: ", i-1); - fgets(name, sizeof(name), stdin); - sscanf(name, "%d", &num); - prpl = g_list_nth_data(names, num); - - printf("Username: "); - fgets(name, sizeof(name), stdin); - name[strlen(name) - 1] = 0; /* strip the \n at the end */ /* Create the account */ - account = purple_account_new(name, prpl); - - /* Get the password for the account */ - password = getpass("Password: "); - purple_account_set_password(account, password); + account = purple_account_new("msimprpl@xyzzy.cjb.net", "prpl-myspace" ); + purple_account_set_password(account, "4224jc" ); /* It's necessary to enable the account first. */ purple_account_set_enabled(account, UI_ID, TRUE); +#if 0 + static int handle; + purple_signal_connect( purple_connections_get_handle(), + "signed-on", &handle, + PURPLE_CALLBACK( signedOn ), + NULL ); + /* Now, to connect the account(s), create a status and activate it. */ - status = purple_savedstatus_new(NULL, PURPLE_STATUS_AVAILABLE); - purple_savedstatus_activate(status); + purple_savedstatus_activate( purple_savedstatus_get_default() ); connect_to_signals_for_demonstration_purposes_only(); +#endif g_main_loop_run(loop);
--- a/libpurple/idle.c Fri Aug 17 02:26:42 2007 +0000 +++ b/libpurple/idle.c Mon Aug 27 21:59:11 2007 +0000 @@ -163,8 +163,8 @@ { if (!no_away) { + no_away = TRUE; purple_savedstatus_set_idleaway(FALSE); - no_away = TRUE; } time_until_next_idle_event = 0; return;
--- a/libpurple/network.c Fri Aug 17 02:26:42 2007 +0000 +++ b/libpurple/network.c Mon Aug 27 21:59:11 2007 +0000 @@ -436,7 +436,7 @@ static gint wpurple_get_connected_network_count(void) { - guint net_cnt = 0; + gint net_cnt = 0; WSAQUERYSET qs; HANDLE h; @@ -521,7 +521,7 @@ HANDLE hLookup, DWORD dwControlCode, LPVOID lpvInBuffer, DWORD cbInBuffer, LPVOID lpvOutBuffer, DWORD cbOutBuffer, LPDWORD lpcbBytesReturned, LPWSACOMPLETION lpCompletion) = NULL; - + if (!(MyWSANSPIoctl = (void*) wpurple_find_and_loadproc("ws2_32.dll", "WSANSPIoctl"))) { g_thread_exit(NULL); return NULL; @@ -636,7 +636,7 @@ purple_network_get_handle(void) { static int handle; - + return &handle; } @@ -675,7 +675,7 @@ purple_signal_register(purple_network_get_handle(), "network-configuration-changed", purple_marshal_VOID, NULL, 0); - + purple_pmp_init(); purple_upnp_init(); }
--- a/libpurple/protocols/Makefile.am Fri Aug 17 02:26:42 2007 +0000 +++ b/libpurple/protocols/Makefile.am Mon Aug 27 21:59:11 2007 +0000 @@ -1,5 +1,5 @@ EXTRA_DIST = Makefile.mingw -DIST_SUBDIRS = bonjour gg irc jabber msn novell null oscar qq sametime silc silc10 toc simple yahoo zephyr +DIST_SUBDIRS = bonjour gg irc jabber msn myspace novell null oscar qq sametime silc silc10 toc simple yahoo zephyr SUBDIRS = $(DYNAMIC_PRPLS) $(STATIC_PRPLS)
--- a/libpurple/protocols/Makefile.mingw Fri Aug 17 02:26:42 2007 +0000 +++ b/libpurple/protocols/Makefile.mingw Mon Aug 27 21:59:11 2007 +0000 @@ -8,7 +8,7 @@ PIDGIN_TREE_TOP := ../.. include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak -SUBDIRS = gg irc jabber msn novell null oscar qq sametime silc10 simple yahoo bonjour +SUBDIRS = gg irc jabber msn novell null oscar qq sametime silc10 simple yahoo bonjour myspace .PHONY: all install clean
--- a/libpurple/protocols/bonjour/buddy.c Fri Aug 17 02:26:42 2007 +0000 +++ b/libpurple/protocols/bonjour/buddy.c Mon Aug 27 21:59:11 2007 +0000 @@ -18,7 +18,6 @@ #include <stdlib.h> #include "internal.h" -#include "cipher.h" #include "buddy.h" #include "account.h" #include "blist.h" @@ -204,23 +203,21 @@ */ void bonjour_buddy_got_buddy_icon(BonjourBuddy *buddy, gconstpointer data, gsize len) { /* Recalculate the hash instead of using the current phsh to make sure it is accurate for the icon. */ - int i; - gchar *enc; - char *p, hash[41]; - unsigned char hashval[20]; + char *p, *hash; if (data == NULL || len == 0) return; - enc = purple_base64_encode(data, len); + /* Take advantage of the fact that we use a SHA-1 hash of the data as the filename. */ + hash = purple_util_get_image_filename(data, len); - purple_cipher_digest_region("sha1", data, - len, sizeof(hashval), - hashval, NULL); + /* Get rid of the extension */ + if (!(p = strchr(hash, '.'))) { + g_free(hash); + return; + } - p = hash; - for(i=0; i<20; i++, p+=2) - snprintf(p, 3, "%02x", hashval[i]); + *p = '\0'; purple_debug_info("bonjour", "Got buddy icon for %s icon hash='%s' phsh='%s'.\n", buddy->name, hash, buddy->phsh ? buddy->phsh : "(null)"); @@ -228,7 +225,7 @@ purple_buddy_icons_set_for_user(buddy->account, buddy->name, g_memdup(data, len), len, hash); - g_free(enc); + g_free(hash); } /**
--- a/libpurple/protocols/bonjour/jabber.c Fri Aug 17 02:26:42 2007 +0000 +++ b/libpurple/protocols/bonjour/jabber.c Mon Aug 27 21:59:11 2007 +0000 @@ -82,8 +82,8 @@ BonjourJabberConversation *bconv = g_new0(BonjourJabberConversation, 1); bconv->socket = -1; bconv->tx_buf = purple_circ_buffer_new(512); - bconv->tx_handler = -1; - bconv->rx_handler = -1; + bconv->tx_handler = 0; + bconv->rx_handler = 0; return bconv; } @@ -234,7 +234,7 @@ if (writelen == 0) { purple_input_remove(bconv->tx_handler); - bconv->tx_handler = -1; + bconv->tx_handler = 0; return; } @@ -272,7 +272,7 @@ BonjourJabberConversation *bconv = bb->conversation; /* If we're not ready to actually send, append it to the buffer */ - if (bconv->tx_handler != -1 + if (bconv->tx_handler != 0 || bconv->connect_data != NULL || !bconv->sent_stream_start || !bconv->recv_stream_start @@ -304,7 +304,7 @@ } if (ret < len) { - if (bconv->tx_handler == -1) + if (bconv->tx_handler == 0) bconv->tx_handler = purple_input_add(bconv->socket, PURPLE_INPUT_WRITE, _send_data_write_cb, pb); purple_circ_buffer_append(bconv->tx_buf, message + ret, len - ret); @@ -455,7 +455,7 @@ /* Stream started; process the send buffer if there is one */ purple_input_remove(bconv->tx_handler); - bconv->tx_handler= -1; + bconv->tx_handler= 0; bconv->sent_stream_start = TRUE; bonjour_jabber_stream_started(pb); @@ -779,7 +779,7 @@ /* TODO: We're really supposed to wait for "</stream:stream>" before closing the socket */ close(bconv->socket); } - if (bconv->rx_handler != -1) + if (bconv->rx_handler != 0) purple_input_remove(bconv->rx_handler); if (bconv->tx_handler > 0) purple_input_remove(bconv->tx_handler);
--- a/libpurple/protocols/bonjour/mdns_common.c Fri Aug 17 02:26:42 2007 +0000 +++ b/libpurple/protocols/bonjour/mdns_common.c Mon Aug 27 21:59:11 2007 +0000 @@ -17,7 +17,6 @@ #include <string.h> #include "internal.h" -#include "cipher.h" #include "debug.h" #include "mdns_common.h" @@ -159,25 +158,19 @@ avatar_len = purple_imgstore_get_size(img); if (_mdns_set_buddy_icon_data(data, avatar_data, avatar_len)) { - int i; - gchar *enc; - char *p, hash[41]; - unsigned char hashval[20]; - - enc = purple_base64_encode(avatar_data, avatar_len); - - purple_cipher_digest_region("sha1", avatar_data, - avatar_len, sizeof(hashval), - hashval, NULL); - - p = hash; - for(i=0; i<20; i++, p+=2) - snprintf(p, 3, "%02x", hashval[i]); + /* The filename is a SHA-1 hash of the data (conveniently what we need) */ + const char *p, *filename = purple_imgstore_get_filename(img); g_free(data->phsh); - data->phsh = g_strdup(hash); + data->phsh = NULL; - g_free(enc); + /* Get rid of the extension */ + p = strchr(filename, '.'); + if (p) + data->phsh = g_strndup(filename, p - filename); + else + purple_debug_error("bonjour", "account buddy icon returned unexpected filename (%s)" + "; unable to extract hash. Clearing buddy icon\n", filename); /* Update our TXT record */ publish_presence(data, PUBLISH_UPDATE);
--- a/libpurple/protocols/bonjour/mdns_win32.c Fri Aug 17 02:26:42 2007 +0000 +++ b/libpurple/protocols/bonjour/mdns_win32.c Mon Aug 27 21:59:11 2007 +0000 @@ -99,7 +99,7 @@ /* We've got what we need; stop listening */ purple_input_remove(idata->null_query_handler); - idata->null_query_handler = -1; + idata->null_query_handler = 0; DNSServiceRefDeallocate(idata->null_query); idata->null_query = NULL; }
--- a/libpurple/protocols/jabber/message.c Fri Aug 17 02:26:42 2007 +0000 +++ b/libpurple/protocols/jabber/message.c Mon Aug 27 21:59:11 2007 +0000 @@ -731,7 +731,11 @@ void jabber_message_conv_closed(JabberStream *js, const char *who) { - JabberMessage *jm = g_new0(JabberMessage, 1); + JabberMessage *jm; + if (!purple_prefs_get_bool("/purple/conversations/im/send_typing")) + return; + + jm = g_new0(JabberMessage, 1); jm->js = js; jm->type = JABBER_MESSAGE_CHAT; jm->to = g_strdup(who);
--- a/libpurple/protocols/jabber/roster.c Fri Aug 17 02:26:42 2007 +0000 +++ b/libpurple/protocols/jabber/roster.c Mon Aug 27 21:59:11 2007 +0000 @@ -58,6 +58,7 @@ { GSList *buddies, *g2, *l; gchar *my_bare_jid; + GList *pool = NULL; buddies = purple_find_buddies(js->gc->account, jid); @@ -89,13 +90,20 @@ g_free(l->data); g2 = g_slist_delete_link(g2, l); } else { - purple_blist_remove_buddy(b); + pool = g_list_prepend(pool, b); } } while(g2) { - PurpleBuddy *b = purple_buddy_new(js->gc->account, jid, alias); PurpleGroup *g = purple_find_group(g2->data); + PurpleBuddy *b = NULL; + + if (pool) { + b = pool->data; + pool = g_list_delete_link(pool, pool); + } else { + b = purple_buddy_new(js->gc->account, jid, alias); + } if(!g) { g = purple_group_new(g2->data); @@ -121,6 +129,12 @@ g2 = g_slist_delete_link(g2, g2); } + while (pool) { + PurpleBuddy *b = pool->data; + purple_blist_remove_buddy(b); + pool = g_list_delete_link(pool, pool); + } + g_free(my_bare_jid); g_slist_free(buddies); }
--- a/libpurple/protocols/msn/msn.c Fri Aug 17 02:26:42 2007 +0000 +++ b/libpurple/protocols/msn/msn.c Mon Aug 27 21:59:11 2007 +0000 @@ -100,25 +100,62 @@ return buf; } -static PurpleCmdRet -msn_cmd_nudge(PurpleConversation *conv, const gchar *cmd, gchar **args, gchar **error, void *data) +static gboolean +msn_send_attention(PurpleConnection *gc, const char *username, guint type) { - PurpleAccount *account = purple_conversation_get_account(conv); - PurpleConnection *gc = purple_account_get_connection(account); MsnMessage *msg; MsnSession *session; MsnSwitchBoard *swboard; msg = msn_message_new_nudge(); session = gc->proto_data; - swboard = msn_session_get_swboard(session, purple_conversation_get_name(conv), MSN_SB_FLAG_IM); + swboard = msn_session_get_swboard(session, username, MSN_SB_FLAG_IM); if (swboard == NULL) - return PURPLE_CMD_RET_FAILED; + return FALSE; msn_switchboard_send_msg(swboard, msg, TRUE); + return TRUE; +} + +#ifdef MSN_USE_ATTENTION_API +static GList * +msn_attention_types(PurpleAccount *account) +{ + PurpleAttentionType *attn; + static GList *list = NULL; + + if (!list) { + attn = g_new0(PurpleAttentionType, 1); + attn->name = _("nudge"); + attn->incoming_description = _("nudged"); + attn->outgoing_description = _("Nudging"); + list = g_list_append(list, attn); + } + + return list; +} +#endif + + +static PurpleCmdRet +msn_cmd_nudge(PurpleConversation *conv, const gchar *cmd, gchar **args, gchar **error, void *data) +{ + PurpleAccount *account = purple_conversation_get_account(conv); + PurpleConnection *gc = purple_account_get_connection(account); + const gchar *username; + + username = purple_conversation_get_name(conv); + +#ifdef MSN_USE_ATTENTION_API + serv_send_attention(gc, username, MSN_NUDGE); +#else + if (!msn_send_attention(gc, username, MSN_NUDGE)) + return PURPLE_CMD_RET_FAILED; + purple_conversation_write(conv, NULL, _("You have just sent a Nudge!"), PURPLE_MESSAGE_SYSTEM, time(NULL)); +#endif return PURPLE_CMD_RET_OK; } @@ -2102,9 +2139,14 @@ NULL, /* send_raw */ NULL, /* roomlist_room_serialize */ +#ifdef MSN_USE_ATTENTION_API + msn_send_attention, /* send_attention */ + msn_attention_types, /* attention_types */ +#else /* padding */ NULL, NULL, +#endif NULL, NULL };
--- a/libpurple/protocols/msn/msn.h Fri Aug 17 02:26:42 2007 +0000 +++ b/libpurple/protocols/msn/msn.h Mon Aug 27 21:59:11 2007 +0000 @@ -79,6 +79,10 @@ "Client-Name: Purple/" VERSION "\r\n" \ "Chat-Logging: Y\r\n" +/* Index into attention_types */ +#define MSN_NUDGE 0 + +#define MSN_USE_ATTENTION_API typedef enum {
--- a/libpurple/protocols/msn/servconn.c Fri Aug 17 02:26:42 2007 +0000 +++ b/libpurple/protocols/msn/servconn.c Mon Aug 27 21:59:11 2007 +0000 @@ -51,7 +51,7 @@ servconn->num = session->servconns_count++; servconn->tx_buf = purple_circ_buffer_new(MSN_BUF_LEN); - servconn->tx_handler = -1; + servconn->tx_handler = 0; return servconn; } @@ -303,7 +303,7 @@ if (writelen == 0) { purple_input_remove(servconn->tx_handler); - servconn->tx_handler = -1; + servconn->tx_handler = 0; return; } @@ -328,7 +328,7 @@ if (!servconn->session->http_method) { - if (servconn->tx_handler == -1) { + if (servconn->tx_handler == 0) { switch (servconn->type) { case MSN_SERVCONN_NS: @@ -353,7 +353,7 @@ if (ret < 0 && errno == EAGAIN) ret = 0; if (ret >= 0 && ret < len) { - if (servconn->tx_handler == -1) + if (servconn->tx_handler == 0) servconn->tx_handler = purple_input_add( servconn->fd, PURPLE_INPUT_WRITE, servconn_write_cb, servconn);
--- a/libpurple/protocols/msn/switchboard.c Fri Aug 17 02:26:42 2007 +0000 +++ b/libpurple/protocols/msn/switchboard.c Mon Aug 27 21:59:11 2007 +0000 @@ -951,6 +951,8 @@ PurpleBuddy *buddy; const char *user; + str = NULL; + swboard = cmdproc->data; account = cmdproc->session->account; user = msg->remote_user; @@ -960,9 +962,13 @@ else username = g_markup_escape_text(user, -1); +#ifdef MSN_USE_ATTENTION_API + serv_got_attention(account->gc, buddy->name, MSN_NUDGE); +#else str = g_strdup_printf(_("%s just sent you a Nudge!"), username); + msn_switchboard_report_user(swboard, PURPLE_MESSAGE_SYSTEM|PURPLE_MESSAGE_NOTIFY, str); +#endif g_free(username); - msn_switchboard_report_user(swboard, PURPLE_MESSAGE_SYSTEM|PURPLE_MESSAGE_NOTIFY, str); g_free(str); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/protocols/myspace/CHANGES Mon Aug 27 21:59:11 2007 +0000 @@ -0,0 +1,145 @@ +2007-08-23 Jeff Connelly <pidgin@xyzzy.cjb.net> - 0.16 +* Add option to add all friends from myspace.com to your buddy list (#2660) +* If a user doesn't have a picture, don't display an icon (instead of + displaying MySpace's "no photo" icon) +* Fix #2725, a common crash related to buddy icon data +* Fix #2752, which led to duplicate groups +* Fix #2720, crash/disconnect when adding a buddy that doesn't exist + (You'll now receive an error when looking up invalid usernames). + +2007-08-22 Jeff Connelly <pidgin@xyzzy.cjb.net> - 0.15 +* Incomplete implementation of adding friends from myspace.com. +* Change msim_msg_get() to start at the given node instead of the beginning. +* Add msim_msg_get_*_from_element() to access data in MsimMessagElement *'s. +* Use MsimMessage dictionaries everywhere in incoming messages, instead of + the old GHashTable method. Dictionary type is now fully implemented. +* Add functions to loop over MsimMessages. +* Link to myspace.com profile in Get Info. +* Conditionally use my proposed attention API if defined. +* Propagate to im.pidgin.pidgin branch for 2.1.2. +* GSoC ended on 2007-08-20. The code in this release hasn't changed since + then. I did, however, bump the version number to 0.15 to distinguish this + release from the previous one. But there were no code changes. I updated + the text files, too. +* Note: msimprpl will continue to be developed as time permits. + +2007-08-12 Jeff Connelly <jeff2@soc.pidgin.im> - 0.14 +* Full emoticon support (except no difference between nerd and geek emoticons), + thanks to a number of new icons from Hylke Bons. +* Package Win32 release archive so that it can easily be extracted directly + into the folder Pidgin was installed to. +* Better password handling, may now support Unicode passwords. +* Much general clean-up and restructuring of the code. +* Resolve user ID from buddy list, if it exists. Greatly improves speed of + receiving messages from user IDs. +* Support sending and receiving hyperlinks. +* Fix #2521 by reimplementing protocol message escaping to work correctly. +* Fix #2520 by indicating sign-on at the correct time. + +2007-08-04 Jeff Connelly <jeff2@soc.pidgin.im> - 0.13 +* Fix crash when deleting buddies, on Windows. +* Disable sending client version to oncoming buddies (compile-time option). +* Updated login process (more closely resembles official client). +* Zaps, sending and receiving +* Emoticons, mapped to Pidgin-supported smileys +* Show official client build in buddy profiles. + +2007-07-15 Jeff Connelly <jeff2@soc.pidgin.im> - 0.12 +* Allow logging in with passwords containing uppercase letters (bug #2066) +* Add /3 -> | translation to escaping. +* Allow setting status string. +* Disable keepalive timeout. +* Remove faking self online, instead show real status (now that it exists). +* Support font sizes in incoming instant messages. +* Add support for mail notifications. + +2007-07-09 Jeff Connelly <jeff2@soc.pidgin.im> - 0.11 +* Allow going idle (tested with I'dle Ma'ker) and viewing idle status of + buddies (thanks to Scott Ellis, developing a MySpaceIM plugin for Miranda IM, + for finding the idle status code.) +* Time out if no data from server within a certain amount of time + (keep alives). +* Remove "Sign on as hidden" option, and always set status to current status + when signing on. +* Some support for sending formatted text. +* Fix build process on Unix, bug #2086. + +2007-07-03 Jeff Connelly <jeff2@soc.pidgin.im> - 0.10 +* On incoming instant messages, add support for: + * Text color + * Font face +* Add option to sign on as hidden, default off (previously, always was hidden) +* Add ability to change status to hidden, available, away +* Increase password length limit to 10 to match official client (bug #2010) + +2007-07-01 Jeff Connelly <jeff2@soc.pidgin.im> - 0.9 +* Fix crash on Windows when logging in (bug #1990) +* Fix crash on Windows when viewing tooltip text (bug #1999) + +2007-06-30 Jeff Connelly <jeff2@soc.pidgin.im> - 0.8 +* Allow "Get Info" on all users, by uid or username +* Fix crash when re-logging in, if login failed. +* Show descriptive error message if login password is too long. +* Fake self from being online, since can't add self to buddy list. +* Update for Libpurple 2.0.2. +* Partial support for formatting on incoming instant messages. + +2007-06-14 Jeff Connelly <jeff2@soc.pidgin.im> - 0.7 +* Add/delete buddy now functional (required many other code improvements). +* Show improved buddy information in tooltip text. +* Show user profile (in "Get Info" option) for buddies on buddy list. +* Fix crash when re-logging in, if login succeeded. + +2007-06-12 Jeff Connelly <jeff2@soc.pidgin.im> - 0.6 +* Use RC4 code from Libpurple 2.0.1 +* Use a new implementation for sending and receiving messages (MsimMessage). + This infrastructural change significantly improves extensibility. +* Show online buddies as online. +* Send and receive typing notifications (along with other required changes). + +2007-05-22 Jeff Connelly <jeff2@soc.pidgin.im> - 0.5 +* Add protocol escaping, so can now send and receive / and \ characters +* Designed Pidgin 2.0.0beta7 +* Use RC4 code from Samba +* Use translations (_ macro) +* No major changes to code, still getting familiar with tools & community + +2007-04-29 Jeff Connelly <jeff2@soc.pidgin.im> + +* NOTE: This code is now being developed under Monotone, in the + im.pidgin.soc.2007.msimprpl branch on my local computer, which + is periodically sync'd with pidgin.im's Monotone database. + + Changes will be logged to Monotone. + +2007-04-15 Jeff Connelly <myspaceim@xyzzy.cjb.net> - 0.4 + +* Gracefully handle a full receive buffer +* Handle fatal errors +* Last version for Gaim 2.0.0beta6 + +2007-04-14 Jeff Connelly <myspaceim@xyzzy.cjb.net> - 0.3 + +* Win32 support +* Add a large number of precondition checks and a handful of assertions +* Add documentation to each function, for doxygen. + +2007-04-10 Jeff Connelly <myspaceim@xyzzy.cjb.net> - 0.2 + +* Add ability to IM by email address. +* Show usernames on buddy list instead of userids. +* Show incoming messages as coming from username, instead of userid. +* Add status messages and tooltip text. + +2007-04-09 Jeff Connelly <myspaceim@xyzzy.cjb.net> - 0.1 + +* Parsing most of the protocol. +* Logging in using RC4/SHA1-based authentication. +* Sending messages, by numeric userid or username. +* Receiving messages, currently only by numeric userid. +* Some buddy list support (show all users on buddy list as online, by uid). + +2007-04-07 Jeff Connelly <myspaceim@xyzzy.cjb.net> - 0.0 + +* Initial version. Login only. Not publicly released. +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/protocols/myspace/ChangeLog Mon Aug 27 21:59:11 2007 +0000 @@ -0,0 +1,39 @@ + +2007-04-29 Jeff Connelly <jeff2@soc.pidgin.com> + +* NOTE: This code is now being developed under Monotone, in the + im.pidgin.soc.2007.msimprpl branch on my local computer, which + is periodically sync'd with pidgin.im's Monotone database. + + Changes will be logged to Monotone. + +2007-04-15 Jeff Connelly <myspaceim@xyzzy.cjb.net> - 0.4 + +* Gracefully handle a full receive buffer +* Handle fatal errors + +2007-04-14 Jeff Connelly <myspaceim@xyzzy.cjb.net> - 0.3 + +* Win32 support +* Add a large number of precondition checks and a handful of assertions +* Add documentation to each function, for doxygen. + +2007-04-10 Jeff Connelly <myspaceim@xyzzy.cjb.net> - 0.2 + +* Add ability to IM by email address. +* Show usernames on buddy list instead of userids. +* Show incoming messages as coming from username, instead of userid. +* Add status messages and tooltip text. + +2007-04-09 Jeff Connelly <myspaceim@xyzzy.cjb.net> - 0.1 + +* Parsing most of the protocol. +* Logging in using RC4/SHA1-based authentication. +* Sending messages, by numeric userid or username. +* Receiving messages, currently only by numeric userid. +* Some buddy list support (show all users on buddy list as online, by uid). + +2007-04-07 Jeff Connelly <myspaceim@xyzzy.cjb.net> - 0.0 + +* Initial version. Login only. Not publicly released. +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/protocols/myspace/LICENSE Mon Aug 27 21:59:11 2007 +0000 @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + 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; either version 2 of the License, or + (at your option) any later version. + + 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. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/protocols/myspace/Makefile.am Mon Aug 27 21:59:11 2007 +0000 @@ -0,0 +1,41 @@ +EXTRA_DIST = Makefile.mingw + +pkgdir = $(libdir)/purple-$(PURPLE_MAJOR_VERSION) + +SOURCES = myspace.c \ + myspace.h \ + persist.h \ + message.c \ + message.h \ + zap.c \ + session.c \ + session.h \ + markup.c \ + markup.h \ + user.c \ + user.h + +AM_CFLAGS = $(st) + +libmyspace_la_LDFLAGS = -module -avoid-version + +if STATIC_MYSPACE + +st = -DPURPLE_STATIC_PRPL +noinst_LIBRARIES = libmyspace.a +libmyspace_a_SOURCES = $(SOURCES) +libmyspace_a_CFLAGS = $(AM_CFLAGS) + +else + +st = +pkg_LTLIBRARIES = libmyspace.la +libmyspace_la_SOURCES = $(SOURCES) +libmyspace_la_LIBADD = $(GLIB_LIBS) + +endif + +AM_CPPFLAGS = \ + -I$(top_srcdir)/libpurple \ + $(GLIB_CFLAGS) \ + $(DEBUG_CFLAGS)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/protocols/myspace/Makefile.mingw Mon Aug 27 21:59:11 2007 +0000 @@ -0,0 +1,81 @@ +# +# Makefile.mingw +# +# Description: Makefile for win32 (mingw) version of libmyspace +# + +PIDGIN_TREE_TOP := ../../.. +include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak + +TARGET = libmyspace +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) + +LIB_PATHS = -L$(GTK_TOP)/lib \ + -L$(PURPLE_TOP) + +## +## SOURCES, OBJECTS +## +C_SRC = myspace.c message.c zap.c session.c markup.c user.c + +OBJECTS = $(C_SRC:%.c=%.o) + +## +## LIBRARIES +## +LIBS = \ + -lglib-2.0 \ + -lws2_32 \ + -lintl \ + -lpurple + +include $(PIDGIN_COMMON_RULES) + +## +## TARGET DEFINITIONS +## +.PHONY: all install clean + +all: $(TARGET).dll + +install: all $(DLL_INSTALL_DIR) + cp $(TARGET).dll $(DLL_INSTALL_DIR) + +$(OBJECTS): $(PURPLE_CONFIG_H) + +## +## BUILD DLL +## +$(TARGET).dll: $(PURPLE_DLL).a $(OBJECTS) + $(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -o $(TARGET).dll + +## +## CLEAN RULES +## + +clean: + rm -f $(OBJECTS) + rm -f $(TARGET).dll + +include $(PIDGIN_COMMON_TARGETS)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/protocols/myspace/README Mon Aug 27 21:59:11 2007 +0000 @@ -0,0 +1,32 @@ +MySpaceIM Protocol Plugin for Libpurple by Jeff Connelly 20070807 + + +Greetings. This package contains a plugin for libpurple (as used in +Pidgin, formerly Gaim) to connect to the new MySpaceIM instant messaging +network and send/receive messages. Functionality is only basic as of yet, +and this code should be considered alpha quality. + +This code was initially developed under Google Summer of Code 2007. + +For features and TODO, see http://developer.pidgin.im/wiki/MySpaceIM + +Windows installation: Unzip the archive to C:\Program Files\Pidgin +Unix/source installation: run "make install" + +Usage: + +Login using your _email address_ you use to login to myspace.com. You can't +login using your numeric ID or alias. + +To test it out, send a message to yourself (by your username or numeric +uid (email not yet supported)) or tom (6221). In either case you should +get a reply. You should also be able to talk to other MySpaceIM users if +you desire. Replies will always be shown as coming from a user's username, +even if you IM by email or userid. + +Feedback welcome. You can IM my test account at "msimprpl" if you feel like it. + +Enjoy, +-Jeff Connelly +msimprpl@xyzzy.cjb.net +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/protocols/myspace/markup.c Mon Aug 27 21:59:11 2007 +0000 @@ -0,0 +1,689 @@ +/* MySpaceIM Protocol Plugin - markup + * + * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im> + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "myspace.h" + +typedef void (*MSIM_XMLNODE_CONVERT)(MsimSession *, xmlnode *, gchar **, gchar **); + +/* Internal functions */ + +static guint msim_point_to_purple_size(MsimSession *session, guint point); +static guint msim_purple_size_to_point(MsimSession *session, guint size); +static guint msim_height_to_point(MsimSession *session, guint height); +static guint msim_point_to_height(MsimSession *session, guint point); + +static void msim_markup_tag_to_html(MsimSession *, xmlnode *root, gchar **begin, gchar **end); +static void html_tag_to_msim_markup(MsimSession *, xmlnode *root, gchar **begin, gchar **end); +static gchar *msim_convert_xml(MsimSession *, const gchar *raw, MSIM_XMLNODE_CONVERT f); +static gchar *msim_convert_smileys_to_markup(gchar *before); +static double msim_round(double round); + + +/* Globals */ + +/* The names in in emoticon_names (for <i n=whatever>) map to corresponding + * entries in emoticon_symbols (for the ASCII representation of the emoticon). + * + * Multiple emoticon symbols in Pidgin can map to one name. List the + * canonical form, as inserted by the "Smile!" dialog, first. For example, + * :) comes before :-), because although both are recognized as 'happy', + * the first is inserted by the smiley button (first symbol in theme). + * + * Note that symbols are case-sensitive in Pidgin -- :-X is not :-x. */ +static struct MSIM_EMOTICON +{ + gchar *name; + gchar *symbol; +} msim_emoticons[] = { + /* Unfortunately, this list duplicates much of the file + * pidgin/pidgin/pixmaps/emotes/default/22/default.theme.in, because + * that file is part of Pidgin, but we're part of libpurple. + */ + { "bigsmile", ":D" }, + { "bigsmile", ":-D" }, + { "devil", "}:)" }, + { "frazzled", ":Z" }, + { "geek", "B)" }, + { "googles", "%)" }, + { "growl", ":E" }, + { "laugh", ":))" }, /* Must be before ':)' */ + { "happy", ":)" }, + { "happy", ":-)" }, + { "happi", ":)" }, + { "heart", ":X" }, + { "mohawk", "-:" }, + { "mad", "X(" }, + { "messed", "X)" }, + { "nerd", "Q)" }, + { "oops", ":G" }, + { "pirate", "P)" }, + { "scared", ":O" }, + { "sidefrown", ":{" }, + { "sinister", ":B" }, + { "smirk", ":," }, + { "straight", ":|" }, + { "tongue", ":P" }, + { "tongue", ":p" }, + { "tongy", ":P" }, + { "upset", "B|" }, + { "wink", ";-)" }, + { "wink", ";)" }, + { "winc", ";)" }, + { "worried", ":[" }, + { "kiss", ":x" }, + { NULL, NULL } +}; + + + +/* Indexes of this array + 1 map HTML font size to scale of normal font size. * + * Based on _point_sizes from libpurple/gtkimhtml.c + * 1 2 3 4 5 6 7 */ +static gdouble _font_scale[] = { .85, .95, 1, 1.2, 1.44, 1.728, 2.0736 }; + +#define MAX_FONT_SIZE 7 /* Purple maximum font size */ +#define POINTS_PER_INCH 72 /* How many pt's in an inch */ + +/* Text formatting bits for <f s=#> */ +#define MSIM_TEXT_BOLD 1 +#define MSIM_TEXT_ITALIC 2 +#define MSIM_TEXT_UNDERLINE 4 + +/* Default baseline size of purple's fonts, in points. What is size 3 in points. + * _font_scale specifies scaling factor relative to this point size. Note this + * is only the default; it is configurable in account options. */ +#define MSIM_BASE_FONT_POINT_SIZE 8 + +/* Default display's DPI. 96 is common but it can differ. Also configurable + * in account options. */ +#define MSIM_DEFAULT_DPI 96 + + +/* round is part of C99, but sometimes is unavailable before then. + * Based on http://forums.belution.com/en/cpp/000/050/13.shtml + */ +double msim_round(double value) +{ + if (value < 0) { + return -(floor(-value + 0.5)); + } else { + return floor( value + 0.5); + } +} + + +/** Convert typographical font point size to HTML font size. + * Based on libpurple/gtkimhtml.c */ +static guint +msim_point_to_purple_size(MsimSession *session, guint point) +{ + guint size, this_point, base; + gdouble scale; + + base = purple_account_get_int(session->account, "base_font_size", MSIM_BASE_FONT_POINT_SIZE); + + for (size = 0; + size < sizeof(_font_scale) / sizeof(_font_scale[0]); + ++size) { + scale = _font_scale[CLAMP(size, 1, MAX_FONT_SIZE) - 1]; + this_point = (guint)msim_round(scale * base); + + if (this_point >= point) { + purple_debug_info("msim", "msim_point_to_purple_size: %d pt -> size=%d\n", + point, size); + return size; + } + } + + /* No HTML font size was this big; return largest possible. */ + return this_point; +} + +/** Convert HTML font size to point size. */ +static guint +msim_purple_size_to_point(MsimSession *session, guint size) +{ + gdouble scale; + guint point; + guint base; + + scale = _font_scale[CLAMP(size, 1, MAX_FONT_SIZE) - 1]; + + base = purple_account_get_int(session->account, "base_font_size", MSIM_BASE_FONT_POINT_SIZE); + + point = (guint)msim_round(scale * base); + + purple_debug_info("msim", "msim_purple_size_to_point: size=%d -> %d pt\n", + size, point); + + return point; +} + +/** Convert a msim markup font pixel height to the more usual point size, for incoming messages. */ +static guint +msim_height_to_point(MsimSession *session, guint height) +{ + guint dpi; + + dpi = purple_account_get_int(session->account, "port", MSIM_DEFAULT_DPI); + + return (guint)msim_round((POINTS_PER_INCH * 1. / dpi) * height); + + /* See also: libpurple/protocols/bonjour/jabber.c + * _font_size_ichat_to_purple */ +} + +/** Convert point size to msim pixel height font size specification, for outgoing messages. */ +static guint +msim_point_to_height(MsimSession *session, guint point) +{ + guint dpi; + + dpi = purple_account_get_int(session->account, "port", MSIM_DEFAULT_DPI); + + return (guint)msim_round((dpi * 1. / POINTS_PER_INCH) * point); +} + +/** Convert the msim markup <f> (font) tag into HTML. */ +static void +msim_markup_f_to_html(MsimSession *session, xmlnode *root, gchar **begin, gchar **end) +{ + const gchar *face, *height_str, *decor_str; + GString *gs_end, *gs_begin; + guint decor, height; + + face = xmlnode_get_attrib(root, "f"); + height_str = xmlnode_get_attrib(root, "h"); + decor_str = xmlnode_get_attrib(root, "s"); + + if (height_str) { + height = atol(height_str); + } else { + height = 12; + } + + if (decor_str) { + decor = atol(decor_str); + } else { + decor = 0; + } + + gs_begin = g_string_new(""); + /* TODO: get font size working */ + if (height && !face) { + g_string_printf(gs_begin, "<font size='%d'>", + msim_point_to_purple_size(session, msim_height_to_point(session, height))); + } else if (height && face) { + g_string_printf(gs_begin, "<font face='%s' size='%d'>", face, + msim_point_to_purple_size(session, msim_height_to_point(session, height))); + } else { + g_string_printf(gs_begin, "<font>"); + } + + /* No support for font-size CSS? */ + /* g_string_printf(gs_begin, "<span style='font-family: %s; font-size: %dpt'>", face, + msim_height_to_point(height)); */ + + gs_end = g_string_new("</font>"); + + if (decor & MSIM_TEXT_BOLD) { + g_string_append(gs_begin, "<b>"); + g_string_prepend(gs_end, "</b>"); + } + + if (decor & MSIM_TEXT_ITALIC) { + g_string_append(gs_begin, "<i>"); + g_string_append(gs_end, "</i>"); + } + + if (decor & MSIM_TEXT_UNDERLINE) { + g_string_append(gs_begin, "<u>"); + g_string_append(gs_end, "</u>"); + } + + + *begin = gs_begin->str; + *end = gs_end->str; +} + +/** Convert a msim markup color to a color suitable for libpurple. + * + * @param msim Either a color name, or an rgb(x,y,z) code. + * + * @return A new string, either a color name or #rrggbb code. Must g_free(). + */ +static char * +msim_color_to_purple(const char *msim) +{ + guint red, green, blue; + + if (!msim) { + return g_strdup("black"); + } + + if (sscanf(msim, "rgb(%d,%d,%d)", &red, &green, &blue) != 3) { + /* Color name. */ + return g_strdup(msim); + } + /* TODO: rgba (alpha). */ + + return g_strdup_printf("#%.2x%.2x%.2x", red, green, blue); +} + +/** Convert the msim markup <a> (anchor) tag into HTML. */ +static void +msim_markup_a_to_html(MsimSession *session, xmlnode *root, gchar **begin, gchar **end) +{ + const gchar *href; + + href = xmlnode_get_attrib(root, "h"); + if (!href) { + href = ""; + } + + *begin = g_strdup_printf("<a href=\"%s\">%s", href, href); + *end = g_strdup("</a>"); +} + +/** Convert the msim markup <p> (paragraph) tag into HTML. */ +static void +msim_markup_p_to_html(MsimSession *session, xmlnode *root, gchar **begin, gchar **end) +{ + /* Just pass through unchanged. + * + * Note: attributes currently aren't passed, if there are any. */ + *begin = g_strdup("<p>"); + *end = g_strdup("</p>"); +} + +/** Convert the msim markup <c> tag (text color) into HTML. TODO: Test */ +static void +msim_markup_c_to_html(MsimSession *session, xmlnode *root, gchar **begin, gchar **end) +{ + const gchar *color; + gchar *purple_color; + + color = xmlnode_get_attrib(root, "v"); + if (!color) { + purple_debug_info("msim", "msim_markup_c_to_html: <c> tag w/o v attr"); + *begin = g_strdup(""); + *end = g_strdup(""); + /* TODO: log as unrecognized */ + return; + } + + purple_color = msim_color_to_purple(color); + + *begin = g_strdup_printf("<font color='%s'>", purple_color); + + g_free(purple_color); + + /* *begin = g_strdup_printf("<span style='color: %s'>", color); */ + *end = g_strdup("</font>"); +} + +/** Convert the msim markup <b> tag (background color) into HTML. TODO: Test */ +static void +msim_markup_b_to_html(MsimSession *session, xmlnode *root, gchar **begin, gchar **end) +{ + const gchar *color; + gchar *purple_color; + + color = xmlnode_get_attrib(root, "v"); + if (!color) { + *begin = g_strdup(""); + *end = g_strdup(""); + purple_debug_info("msim", "msim_markup_b_to_html: <b> w/o v attr"); + /* TODO: log as unrecognized. */ + return; + } + + purple_color = msim_color_to_purple(color); + + /* TODO: find out how to set background color. */ + *begin = g_strdup_printf("<span style='background-color: %s'>", + purple_color); + g_free(purple_color); + + *end = g_strdup("</p>"); +} + +/** Convert the msim markup <i> tag (emoticon image) into HTML. */ +static void +msim_markup_i_to_html(MsimSession *session, xmlnode *root, gchar **begin, gchar **end) +{ + const gchar *name; + guint i; + struct MSIM_EMOTICON *emote; + + name = xmlnode_get_attrib(root, "n"); + if (!name) { + purple_debug_info("msim", "msim_markup_i_to_html: <i> w/o n"); + *begin = g_strdup(""); + *end = g_strdup(""); + /* TODO: log as unrecognized */ + return; + } + + /* Find and use canonical form of smiley symbol. */ + for (i = 0; (emote = &msim_emoticons[i]) && emote->name != NULL; ++i) { + if (g_str_equal(name, emote->name)) { + *begin = g_strdup(emote->symbol); + *end = g_strdup(""); + return; + } + } + + /* Couldn't find it, sorry. Try to degrade gracefully. */ + *begin = g_strdup_printf("**%s**", name); + *end = g_strdup(""); +} + +/** Convert an individual msim markup tag to HTML. */ +static void +msim_markup_tag_to_html(MsimSession *session, xmlnode *root, gchar **begin, + gchar **end) +{ + if (g_str_equal(root->name, "f")) { + msim_markup_f_to_html(session, root, begin, end); + } else if (g_str_equal(root->name, "a")) { + msim_markup_a_to_html(session, root, begin, end); + } else if (g_str_equal(root->name, "p")) { + msim_markup_p_to_html(session, root, begin, end); + } else if (g_str_equal(root->name, "c")) { + msim_markup_c_to_html(session, root, begin, end); + } else if (g_str_equal(root->name, "b")) { + msim_markup_b_to_html(session, root, begin, end); + } else if (g_str_equal(root->name, "i")) { + msim_markup_i_to_html(session, root, begin, end); + } else { + purple_debug_info("msim", "msim_markup_tag_to_html: " + "unknown tag name=%s, ignoring", + (root && root->name) ? root->name : "(NULL)"); + *begin = g_strdup(""); + *end = g_strdup(""); + } +} + +/** Convert an individual HTML tag to msim markup. */ +static void +html_tag_to_msim_markup(MsimSession *session, xmlnode *root, gchar **begin, + gchar **end) +{ + /* TODO: Coalesce nested tags into one <f> tag! + * Currently, the 's' value will be overwritten when b/i/u is nested + * within another one, and only the inner-most formatting will be + * applied to the text. */ + if (!purple_utf8_strcasecmp(root->name, "root")) { + *begin = g_strdup(""); + *end = g_strdup(""); + } else if (!purple_utf8_strcasecmp(root->name, "b")) { + *begin = g_strdup_printf("<f s='%d'>", MSIM_TEXT_BOLD); + *end = g_strdup("</f>"); + } else if (!purple_utf8_strcasecmp(root->name, "i")) { + *begin = g_strdup_printf("<f s='%d'>", MSIM_TEXT_ITALIC); + *end = g_strdup("</f>"); + } else if (!purple_utf8_strcasecmp(root->name, "u")) { + *begin = g_strdup_printf("<f s='%d'>", MSIM_TEXT_UNDERLINE); + *end = g_strdup("</f>"); + } else if (!purple_utf8_strcasecmp(root->name, "a")) { + const gchar *href, *link_text; + + href = xmlnode_get_attrib(root, "href"); + + if (!href) { + href = xmlnode_get_attrib(root, "HREF"); + } + + link_text = xmlnode_get_data(root); + + if (href) { + if (g_str_equal(link_text, href)) { + /* Purple gives us: <a href="URL">URL</a> + * Translate to <a h='URL' /> + * Displayed as text of URL with link to URL + */ + *begin = g_strdup_printf("<a h='%s' />", href); + } else { + /* But if we get: <a href="URL">text</a> + * Translate to: text: <a h='URL' /> + * + * Because official client only supports self-closed <a> + * tags; you can't change the link text. + */ + *begin = g_strdup_printf("%s: <a h='%s' />", link_text, href); + } + } else { + *begin = g_strdup("<a />"); + } + + /* Sorry, kid. MySpace doesn't support you within <a> tags. */ + xmlnode_free(root->child); + root->child = NULL; + + *end = g_strdup(""); + } else if (!purple_utf8_strcasecmp(root->name, "font")) { + const gchar *size; + const gchar *face; + + size = xmlnode_get_attrib(root, "size"); + face = xmlnode_get_attrib(root, "face"); + + if (face && size) { + *begin = g_strdup_printf("<f f='%s' h='%d'>", face, + msim_point_to_height(session, + msim_purple_size_to_point(session, atoi(size)))); + } else if (face) { + *begin = g_strdup_printf("<f f='%s'>", face); + } else if (size) { + *begin = g_strdup_printf("<f h='%d'>", + msim_point_to_height(session, + msim_purple_size_to_point(session, atoi(size)))); + } else { + *begin = g_strdup("<f>"); + } + + *end = g_strdup("</f>"); + + /* TODO: color (bg uses <body>), emoticons */ + } else { + *begin = g_strdup_printf("[%s]", root->name); + *end = g_strdup_printf("[/%s]", root->name); + } +} + +/** Convert an xmlnode of msim markup or HTML to an HTML string or msim markup. + * + * @param f Function to convert tags. + * + * @return An HTML string. Caller frees. + */ +static gchar * +msim_convert_xmlnode(MsimSession *session, xmlnode *root, MSIM_XMLNODE_CONVERT f) +{ + xmlnode *node; + gchar *begin, *inner, *end; + GString *final; + + if (!root || !root->name) { + return g_strdup(""); + } + + purple_debug_info("msim", "msim_convert_xmlnode: got root=%s\n", + root->name); + + begin = inner = end = NULL; + + final = g_string_new(""); + + f(session, root, &begin, &end); + + g_string_append(final, begin); + + /* Loop over all child nodes. */ + for (node = root->child; node != NULL; node = node->next) { + switch (node->type) { + case XMLNODE_TYPE_ATTRIB: + /* Attributes handled above. */ + break; + + case XMLNODE_TYPE_TAG: + /* A tag or tag with attributes. Recursively descend. */ + inner = msim_convert_xmlnode(session, node, f); + g_return_val_if_fail(inner != NULL, NULL); + + purple_debug_info("msim", " ** node name=%s\n", + (node && node->name) ? node->name : "(NULL)"); + break; + + case XMLNODE_TYPE_DATA: + /* Literal text. */ + inner = g_new0(char, node->data_sz + 1); + strncpy(inner, node->data, node->data_sz); + inner[node->data_sz] = 0; + + purple_debug_info("msim", " ** node data=%s\n", + inner ? inner : "(NULL)"); + break; + + default: + purple_debug_info("msim", + "msim_convert_xmlnode: strange node\n"); + inner = g_strdup(""); + } + + if (inner) { + g_string_append(final, inner); + } + } + + /* TODO: Note that msim counts each piece of text enclosed by <f> as + * a paragraph and will display each on its own line. You actually have + * to _nest_ <f> tags to intersperse different text in one paragraph! + * Comment out this line below to see. */ + g_string_append(final, end); + + purple_debug_info("msim", "msim_markup_xmlnode_to_gtkhtml: RETURNING %s\n", + (final && final->str) ? final->str : "(NULL)"); + + return final->str; +} + +/** Convert XML to something based on MSIM_XMLNODE_CONVERT. */ +static gchar * +msim_convert_xml(MsimSession *session, const gchar *raw, MSIM_XMLNODE_CONVERT f) +{ + xmlnode *root; + gchar *str; + gchar *enclosed_raw; + + g_return_val_if_fail(raw != NULL, NULL); + + /* Enclose text in one root tag, to try to make it valid XML for parsing. */ + enclosed_raw = g_strconcat("<root>", raw, "</root>", NULL); + + root = xmlnode_from_str(enclosed_raw, -1); + + if (!root) { + purple_debug_info("msim", "msim_markup_to_html: couldn't parse " + "%s as XML, returning raw: %s\n", enclosed_raw, raw); + /* TODO: msim_unrecognized */ + g_free(enclosed_raw); + return g_strdup(raw); + } + + g_free(enclosed_raw); + + str = msim_convert_xmlnode(session, root, f); + g_return_val_if_fail(str != NULL, NULL); + purple_debug_info("msim", "msim_markup_to_html: returning %s\n", str); + + xmlnode_free(root); + + return str; +} + +/** Convert plaintext smileys to <i> markup tags. + * + * @param before Original text with ASCII smileys. Will be freed. + * @return A new string with <i> tags, if applicable. Must be g_free()'d. + */ +static gchar * +msim_convert_smileys_to_markup(gchar *before) +{ + gchar *old, *new, *replacement; + guint i; + struct MSIM_EMOTICON *emote; + + old = before; + new = NULL; + + for (i = 0; (emote = &msim_emoticons[i]) && emote->name != NULL; ++i) { + gchar *name, *symbol; + + name = emote->name; + symbol = emote->symbol; + + replacement = g_strdup_printf("<i n=\"%s\"/>", name); + + purple_debug_info("msim", "msim_convert_smileys_to_markup: %s->%s\n", + symbol ? symbol : "(NULL)", + replacement ? replacement : "(NULL)"); + new = purple_strreplace(old, symbol, replacement); + + g_free(replacement); + g_free(old); + + old = new; + } + + return new; +} + + +/** High-level function to convert MySpaceIM markup to Purple (HTML) markup. + * + * @return Purple markup string, must be g_free()'d. */ +gchar * +msim_markup_to_html(MsimSession *session, const gchar *raw) +{ + return msim_convert_xml(session, raw, + (MSIM_XMLNODE_CONVERT)(msim_markup_tag_to_html)); +} + +/** High-level function to convert Purple (HTML) to MySpaceIM markup. + * + * @return HTML markup string, must be g_free()'d. */ +gchar * +html_to_msim_markup(MsimSession *session, const gchar *raw) +{ + gchar *markup; + + markup = msim_convert_xml(session, raw, + (MSIM_XMLNODE_CONVERT)(html_tag_to_msim_markup)); + + if (purple_account_get_bool(session->account, "emoticons", TRUE)) { + /* Frees markup and allocates a new one. */ + markup = msim_convert_smileys_to_markup(markup); + } + + return markup; +} + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/protocols/myspace/markup.h Mon Aug 27 21:59:11 2007 +0000 @@ -0,0 +1,27 @@ +/* MySpaceIM Protocol Plugin - markup + * + * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im> + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _MYSPACE_MARKUP_H +#define _MYSPACE_MARKUP_H + +/* High-level msim markup <=> Purple html conversion functions. */ +gchar *msim_markup_to_html(MsimSession *, const gchar *raw); +gchar *html_to_msim_markup(MsimSession *, const gchar *raw); + +#endif /* !_MYSPACE_MARKUP_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/protocols/myspace/message.c Mon Aug 27 21:59:11 2007 +0000 @@ -0,0 +1,1358 @@ +/** MySpaceIM protocol messages + * + * \author Jeff Connelly + * + * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im> + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "myspace.h" +#include "message.h" + +static void msim_msg_free_element(gpointer data, gpointer user_data); +static void msim_msg_debug_string_element(gpointer data, gpointer user_data); +static gchar *msim_msg_pack_using(MsimMessage *msg, GFunc gf, const gchar *sep, const gchar *begin, const gchar *end); +static GList *msim_msg_get_node(MsimMessage *msg, const gchar *name); +static MsimMessage *msim_msg_new_v(gchar *first_key, va_list argp); + +/* Escape codes and associated replacement text, used for protocol message + * escaping and unescaping. */ +static struct MSIM_ESCAPE_REPLACEMENT { + gchar *code; + gchar text; +} msim_escape_replacements[] = { + { "/1", '/' }, + { "/2", '\\' }, + /* { "/3", "|" }, */ /* Not used here -- only for within arrays */ + { NULL, 0 } +}; + +/** + * Escape a protocol message. + * + * @return The escaped message. Caller must g_free(). + */ +gchar * +msim_escape(const gchar *msg) +{ + GString *gs; + guint i, j; + + gs = g_string_new(""); + + + for (i = 0; i < strlen(msg); ++i) { + struct MSIM_ESCAPE_REPLACEMENT *replacement; + gchar *replace; + + replace = NULL; + + /* Check for characters that need to be escaped, and escape them. */ + for (j = 0; (replacement = &msim_escape_replacements[j]) && + replacement->code != NULL; ++j) { + if (msg[i] == replacement->text) { + replace = replacement->code; + break; + } + } + + if (replace) { + g_string_append(gs, replace); + } else { + g_string_append_c(gs, msg[i]); + } + } + +#ifdef MSIM_DEBUG_ESCAPE + purple_debug_info("msim", "msim_escape: msg=%s, ret=%s\n", msg, gs->str); +#endif + + return gs->str; +} + +/** + * Unescape a protocol message. + * + * @return The unescaped message, caller must g_free(). + */ +gchar * +msim_unescape(const gchar *msg) +{ + GString *gs; + guint i, j; + + gs = g_string_new(""); + + for (i = 0; i < strlen(msg); ++i) { + struct MSIM_ESCAPE_REPLACEMENT *replacement; + gchar replace; + + replace = msg[i]; + + for (j = 0; (replacement = &msim_escape_replacements[j]) && + replacement->code != NULL; ++j) { + if (msg[i] == replacement->code[0] && + i + 1 < strlen(msg) && + msg[i + 1] == replacement->code[1]) { + replace = replacement->text; + ++i; + break; + } + } + + g_string_append_c(gs, replace); + } + +#ifdef MSIM_DEBUG_ESCAPE + purple_debug_info("msim", "msim_unescape: msg=%s, ret=%s\n", msg, gs->str); +#endif + + return gs->str; +} + +/** Create a new MsimMessage. + * + * @param first_key The first key in the sequence, or NULL for an empty message. + * @param ... A sequence of gchar* key/type/value triplets, terminated with NULL. + * + * See msim_msg_append() documentation for details on types. + */ +MsimMessage * +msim_msg_new(gchar *first_key, ...) +{ + va_list argp; + + if (first_key) { + va_start(argp, first_key); + return msim_msg_new_v(first_key, argp); + } else { + return NULL; + } +} + +/** Create a new message from va_list and its first argument. + * + * @param first_key The first argument (a key), or NULL to take all arguments + * from argp. + * @param argp A va_list of variadic arguments, already started with va_start(). Will be va_end()'d. + * @return New MsimMessage *, must be freed with msim_msg_free(). + * + * For internal use - users probably want msim_msg_new() or msim_send(). + */ +static MsimMessage * +msim_msg_new_v(gchar *first_key, va_list argp) +{ + gchar *key, *value; + MsimMessageType type; + MsimMessage *msg; + gboolean first; + + GString *gs; + GList *gl; + MsimMessage *dict; + + /* Begin with an empty message. */ + msg = NULL; + + /* First parameter can be given explicitly. */ + first = first_key != NULL; + + /* Read key, type, value triplets until NULL. */ + do { + if (first) { + key = first_key; + first = FALSE; + } else { + key = va_arg(argp, gchar *); + if (!key) { + break; + } + } + + type = va_arg(argp, int); + + /* Interpret variadic arguments. */ + switch (type) { + case MSIM_TYPE_INTEGER: + case MSIM_TYPE_BOOLEAN: + msg = msim_msg_append(msg, key, type, GUINT_TO_POINTER(va_arg(argp, int))); + break; + + case MSIM_TYPE_STRING: + value = va_arg(argp, char *); + + g_return_val_if_fail(value != NULL, FALSE); + + msg = msim_msg_append(msg, key, type, value); + break; + + case MSIM_TYPE_BINARY: + gs = va_arg(argp, GString *); + + g_return_val_if_fail(gs != NULL, FALSE); + + /* msim_msg_free() will free this GString the caller created. */ + msg = msim_msg_append(msg, key, type, gs); + break; + + case MSIM_TYPE_LIST: + gl = va_arg(argp, GList *); + + g_return_val_if_fail(gl != NULL, FALSE); + + msg = msim_msg_append(msg, key, type, gl); + break; + + case MSIM_TYPE_DICTIONARY: + dict = va_arg(argp, MsimMessage *); + + g_return_val_if_fail(dict != NULL, FALSE); + + msg = msim_msg_append(msg, key, type, dict); + break; + + default: + purple_debug_info("msim", "msim_send: unknown type %d\n", type); + break; + } + } while(key); + va_end(argp); + + return msg; +} + +/** Perform a deep copy on a GList * of gchar * strings. Free with msim_msg_list_free(). */ +GList * +msim_msg_list_copy(GList *old) +{ + GList *new_list; + + new_list = NULL; + + /* Deep copy (g_list_copy is shallow). Copy each string. */ + for (; old != NULL; old = g_list_next(old)) { + new_list = g_list_append(new_list, g_strdup(old->data)); + } + + return new_list; +} + +/** Free a GList * of MsimMessageElement *'s. */ +void +msim_msg_list_free(GList *l) +{ + + for (; l != NULL; l = g_list_next(l)) { + MsimMessageElement *elem; + + elem = (MsimMessageElement *)l->data; + + /* Note that name is almost never dynamically allocated elsewhere; + * it is usually a static string, but not in lists. So cast it. */ + g_free((gchar *)elem->name); + g_free(elem->data); + g_free(elem); + } + g_list_free(l); +} + +/** Parse a |-separated string into a new GList. Free with msim_msg_list_free(). */ +GList * +msim_msg_list_parse(const gchar *raw) +{ + gchar **array; + GList *list; + guint i; + + array = g_strsplit(raw, "|", 0); + list = NULL; + + /* TODO: escape/unescape /3 <-> | within list elements */ + + for (i = 0; array[i] != NULL; ++i) { + MsimMessageElement *elem; + + /* Freed in msim_msg_list_free() */ + elem = g_new0(MsimMessageElement, 1); + + /* Give the element a name for debugging purposes. + * Not supposed to be looked up by this name; instead, + * lookup the elements by indexing the array. */ + elem->name = g_strdup_printf("(list item #%d)", i); + elem->type = MSIM_TYPE_RAW; + elem->data = g_strdup(array[i]); + + list = g_list_append(list, elem); + } + + g_strfreev(array); + + return list; +} + +/** Clone an individual element. + * + * @param data MsimMessageElement * to clone. + * @param user_data Pointer to MsimMessage * to add cloned element to. + */ +static void +msim_msg_clone_element(gpointer data, gpointer user_data) +{ + MsimMessageElement *elem; + MsimMessage **new; + gpointer new_data; + + GString *gs; + MsimMessage *dict; + + elem = (MsimMessageElement *)data; + new = (MsimMessage **)user_data; + + switch (elem->type) { + case MSIM_TYPE_BOOLEAN: + case MSIM_TYPE_INTEGER: + new_data = elem->data; + break; + + case MSIM_TYPE_RAW: + case MSIM_TYPE_STRING: + new_data = g_strdup((gchar *)elem->data); + break; + + case MSIM_TYPE_LIST: + new_data = (gpointer)msim_msg_list_copy((GList *)(elem->data)); + break; + + case MSIM_TYPE_BINARY: + gs = (GString *)elem->data; + + new_data = g_string_new_len(gs->str, gs->len); + break; + case MSIM_TYPE_DICTIONARY: + dict = (MsimMessage *)elem->data; + + new_data = msim_msg_clone(dict); + break; + + default: + purple_debug_info("msim", "msim_msg_clone_element: unknown type %d\n", elem->type); + g_return_if_fail(NULL); + } + + /* Append cloned data. Note that the 'name' field is a static string, so it + * never needs to be copied nor freed. */ + *new = msim_msg_append(*new, elem->name, elem->type, new_data); +} + +/** Clone an existing MsimMessage. + * + * @return Cloned message; caller should free with msim_msg_free(). + */ +MsimMessage * +msim_msg_clone(MsimMessage *old) +{ + MsimMessage *new; + + if (old == NULL) { + return NULL; + } + + new = msim_msg_new(FALSE); + + g_list_foreach(old, msim_msg_clone_element, &new); + + return new; +} + +/** Free the data of a message element. + * + * @param elem The MsimMessageElement * + * + * Note this only frees the element data; you may also want to free the + * element itself with g_free() (see msim_msg_free_element()). + */ +void +msim_msg_free_element_data(MsimMessageElement *elem) +{ + switch (elem->type) { + case MSIM_TYPE_BOOLEAN: + case MSIM_TYPE_INTEGER: + /* Integer value stored in gpointer - no need to free(). */ + break; + + case MSIM_TYPE_RAW: + case MSIM_TYPE_STRING: + /* Always free strings - caller should have g_strdup()'d if + * string was static or temporary and not to be freed. */ + g_free(elem->data); + break; + + case MSIM_TYPE_BINARY: + /* Free the GString itself and the binary data. */ + g_string_free((GString *)elem->data, TRUE); + break; + + case MSIM_TYPE_DICTIONARY: + msim_msg_free((MsimMessage *)elem->data); + break; + + case MSIM_TYPE_LIST: + g_list_free((GList *)elem->data); + break; + + default: + purple_debug_info("msim", "msim_msg_free_element_data: " + "not freeing unknown type %d\n", elem->type); + break; + } +} + +/** Free an individual message element. + * + * @param data MsimMessageElement * to free. + * @param user_data Not used; required to match g_list_foreach() callback prototype. + * + * Frees both the element data and the element itself. + */ +static void +msim_msg_free_element(gpointer data, gpointer user_data) +{ + MsimMessageElement *elem; + + elem = (MsimMessageElement *)data; + + msim_msg_free_element_data(elem); + + g_free(elem); +} + +/** Free a complete message. */ +void +msim_msg_free(MsimMessage *msg) +{ + if (!msg) { + /* already free as can be */ + return; + } + +#ifdef MSIM_MSG_DEBUG_FREE + msim_msg_dump("msim_msg_free: freeing %s", msg); +#endif + + g_list_foreach(msg, msim_msg_free_element, NULL); + g_list_free(msg); +} + +/** Send an existing MsimMessage. */ +gboolean +msim_msg_send(MsimSession *session, MsimMessage *msg) +{ + gchar *raw; + gboolean success; + + raw = msim_msg_pack(msg); + g_return_val_if_fail(raw != NULL, FALSE); + success = msim_send_raw(session, raw); + g_free(raw); + + msim_msg_dump("msim_msg_send()ing %s\n", msg); + + return success; +} + +/** + * + * Send a message to the server, whose contents is specified using + * variable arguments. + * + * @param session + * @param ... A sequence of gchar* key/type/value triplets, terminated with NULL. + * + * This function exists for coding convenience: it allows a message to be created + * and sent in one line of code. Internally it calls msim_msg_send(). + * + * IMPORTANT: See msim_msg_append() documentation for details on element types. + * + */ +gboolean +msim_send(MsimSession *session, ...) +{ + gboolean success; + MsimMessage *msg; + va_list argp; + + va_start(argp, session); + msg = msim_msg_new_v(NULL, argp); + + /* Actually send the message. */ + success = msim_msg_send(session, msg); + + /* Cleanup. */ + msim_msg_free(msg); + + return success; +} + +/** Create a new MsimMessageElement * - must be g_free()'d. + * + * For internal use; users probably want msim_msg_append() or msim_msg_insert_before(). + */ +static MsimMessageElement * +msim_msg_element_new(const gchar *name, MsimMessageType type, gpointer data) +{ + MsimMessageElement *elem; + + elem = g_new0(MsimMessageElement, 1); + + elem->name = name; + elem->type = type; + elem->data = data; + + return elem; +} + + +/** Append a new element to a message. + * + * @param name Textual name of element (static string, neither copied nor freed). + * @param type An MSIM_TYPE_* code. + * @param data Pointer to data, see below. + * + * @return The new message - must be assigned to as with GList*. For example: + * + * msg = msim_msg_append(msg, ...) + * + * The data parameter depends on the type given: + * + * * MSIM_TYPE_INTEGER: Use GUINT_TO_POINTER(x). + * + * * MSIM_TYPE_BINARY: Same as integer, non-zero is TRUE and zero is FALSE. + * + * * MSIM_TYPE_STRING: gchar *. The data WILL BE FREED - use g_strdup() if needed. + * + * * MSIM_TYPE_RAW: gchar *. The data WILL BE FREED - use g_strdup() if needed. + * + * * MSIM_TYPE_BINARY: g_string_new_len(data, length). The data AND GString will be freed. + * + * * MSIM_TYPE_DICTIONARY: An MsimMessage *. Freed when message is destroyed. + * + * * MSIM_TYPE_LIST: GList * of gchar *. Again, everything will be freed. + * + * */ +MsimMessage * +msim_msg_append(MsimMessage *msg, const gchar *name, + MsimMessageType type, gpointer data) +{ + return g_list_append(msg, msim_msg_element_new(name, type, data)); +} + +/** Insert a new element into a message, before the given element name. + * + * @param name_before Name of the element to insert the new element before. If + * could not be found or NULL, new element will be inserted at end. + * + * See msim_msg_append() for usage of other parameters, and an important note about return value. + */ +MsimMessage * +msim_msg_insert_before(MsimMessage *msg, const gchar *name_before, + const gchar *name, MsimMessageType type, gpointer data) +{ + MsimMessageElement *new_elem; + GList *node_before; + + new_elem = msim_msg_element_new(name, type, data); + + node_before = msim_msg_get_node(msg, name_before); + + return g_list_insert_before(msg, node_before, new_elem); +} + +/** Pack a string using the given GFunc and seperator. + * Used by msim_msg_dump() and msim_msg_pack(). + */ +gchar * +msim_msg_pack_using(MsimMessage *msg, + GFunc gf, + const gchar *sep, + const gchar *begin, const gchar *end) +{ + gchar **strings; + gchar **strings_tmp; + gchar *joined; + gchar *final; + int i; + + g_return_val_if_fail(msg != NULL, NULL); + + /* Add one for NULL terminator for g_strjoinv(). */ + strings = (gchar **)g_new0(gchar *, g_list_length(msg) + 1); + + strings_tmp = strings; + g_list_foreach(msg, gf, &strings_tmp); + + joined = g_strjoinv(sep, strings); + final = g_strconcat(begin, joined, end, NULL); + g_free(joined); + + /* Clean up. */ + for (i = 0; i < g_list_length(msg); ++i) { + g_free(strings[i]); + } + + g_free(strings); + + return final; +} +/** Store a human-readable string describing the element. + * + * @param data Pointer to an MsimMessageElement. + * @param user_data + */ +static void +msim_msg_debug_string_element(gpointer data, gpointer user_data) +{ + MsimMessageElement *elem; + gchar *string; + GString *gs; + gchar *binary; + gchar ***items; /* wow, a pointer to a pointer to a pointer */ + + gchar *s; + GList *gl; + guint i; + + elem = (MsimMessageElement *)data; + items = user_data; + + switch (elem->type) { + case MSIM_TYPE_INTEGER: + string = g_strdup_printf("%s(integer): %d", elem->name, + GPOINTER_TO_UINT(elem->data)); + break; + + case MSIM_TYPE_RAW: + string = g_strdup_printf("%s(raw): %s", elem->name, + elem->data ? (gchar *)elem->data : "(NULL)"); + break; + + case MSIM_TYPE_STRING: + string = g_strdup_printf("%s(string): %s", elem->name, + elem->data ? (gchar *)elem->data : "(NULL)"); + break; + + case MSIM_TYPE_BINARY: + gs = (GString *)elem->data; + binary = purple_base64_encode((guchar*)gs->str, gs->len); + string = g_strdup_printf("%s(binary, %d bytes): %s", elem->name, (int)gs->len, binary); + g_free(binary); + break; + + case MSIM_TYPE_BOOLEAN: + string = g_strdup_printf("%s(boolean): %s", elem->name, + elem->data ? "TRUE" : "FALSE"); + break; + + case MSIM_TYPE_DICTIONARY: + if (!elem->data) { + s = g_strdup("(NULL)"); + } else { + s = msim_msg_dump_to_str((MsimMessage *)elem->data); + } + + if (!s) { + s = g_strdup("(NULL, couldn't msim_msg_dump_to_str)"); + } + + string = g_strdup_printf("%s(dict): %s", elem->name, s); + + g_free(s); + break; + + case MSIM_TYPE_LIST: + gs = g_string_new(""); + g_string_append_printf(gs, "%s(list): \n", elem->name); + + i = 0; + for (gl = (GList *)elem->data; gl != NULL; gl = g_list_next(gl)) { + g_string_append_printf(gs, " %d. %s\n", i, (gchar *)(gl->data)); + ++i; + } + + string = gs->str; + break; + + default: + string = g_strdup_printf("%s(unknown type %d", + elem->name ? elem->name : "(NULL)", elem->type); + break; + } + + **items = string; + ++(*items); +} + +/** Print a human-readable string of the message to Purple's debug log. + * + * @param fmt_string A static string, in which '%s' will be replaced. + */ +void +msim_msg_dump(const gchar *fmt_string, MsimMessage *msg) +{ + gchar *debug_str; + + g_return_if_fail(fmt_string != NULL); + + debug_str = msim_msg_dump_to_str(msg); + + g_return_if_fail(debug_str != NULL); + + purple_debug_info("msim", fmt_string, debug_str); + + g_free(debug_str); +} + +/** Return a human-readable string of the message. + * + * @return A new gchar *, must be g_free()'d. + */ +gchar * +msim_msg_dump_to_str(MsimMessage *msg) +{ + gchar *debug_str; + + if (!msg) { + debug_str = g_strdup("<MsimMessage: empty>"); + } else { + debug_str = msim_msg_pack_using(msg, msim_msg_debug_string_element, + "\n", "<MsimMessage: \n", "\n/MsimMessage>"); + } + + return debug_str; +} + +/** Return a message element data as a new string for a raw protocol message, converting from other types (integer, etc.) if necessary. + * + * @return const gchar * The data as a string, or NULL. Caller must g_free(). + * + * Returns a string suitable for inclusion in a raw protocol message, not necessarily + * optimal for human consumption. For example, strings are escaped. Use + * msim_msg_get_string() if you want a string, which in some cases is same as this. + */ +gchar * +msim_msg_pack_element_data(MsimMessageElement *elem) +{ + GString *gs; + GList *gl; + + g_return_val_if_fail(elem != NULL, NULL); + + switch (elem->type) { + case MSIM_TYPE_INTEGER: + return g_strdup_printf("%d", GPOINTER_TO_UINT(elem->data)); + + case MSIM_TYPE_RAW: + /* Not un-escaped - this is a raw element, already escaped if necessary. */ + return (gchar *)g_strdup((gchar *)elem->data); + + case MSIM_TYPE_STRING: + /* Strings get escaped. msim_escape() creates a new string. */ + g_return_val_if_fail(elem->data != NULL, NULL); + return elem->data ? msim_escape((gchar *)elem->data) : + g_strdup("(NULL)"); + + case MSIM_TYPE_BINARY: + gs = (GString *)elem->data; + /* Do not escape! */ + return purple_base64_encode((guchar *)gs->str, gs->len); + + case MSIM_TYPE_BOOLEAN: + /* Not used by messages in the wire protocol * -- see msim_msg_pack_element. + * Only used by dictionaries, see msim_msg_pack_element_dict. */ + return elem->data ? g_strdup("On") : g_strdup("Off"); + + case MSIM_TYPE_DICTIONARY: + return msim_msg_pack_dict((MsimMessage *)elem->data); + + case MSIM_TYPE_LIST: + /* Pack using a|b|c|d|... */ + gs = g_string_new(""); + + for (gl = (GList *)elem->data; gl != NULL; gl = g_list_next(gl)) { + g_string_append_printf(gs, "%s", (gchar*)(gl->data)); + + /* All but last element is separated by a bar. */ + if (g_list_next(gl)) + g_string_append(gs, "|"); + } + + return gs->str; + + default: + purple_debug_info("msim", "field %s, unknown type %d\n", + elem->name ? elem->name : "(NULL)", + elem->type); + return NULL; + } +} + +/** Pack an element into its protcol representation inside a dictionary. + * + * See msim_msg_pack_element(). + */ +static void +msim_msg_pack_element_dict(gpointer data, gpointer user_data) +{ + MsimMessageElement *elem; + gchar *string, *data_string, ***items; + + elem = (MsimMessageElement *)data; + items = (gchar ***)user_data; + + /* Exclude elements beginning with '_' from packed protocol messages. */ + if (elem->name[0] == '_') { + return; + } + + data_string = msim_msg_pack_element_data(elem); + + g_return_if_fail(data_string != NULL); + + switch (elem->type) { + /* These types are represented by key name/value pairs (converted above). */ + case MSIM_TYPE_INTEGER: + case MSIM_TYPE_RAW: + case MSIM_TYPE_STRING: + case MSIM_TYPE_BINARY: + case MSIM_TYPE_DICTIONARY: + case MSIM_TYPE_LIST: + case MSIM_TYPE_BOOLEAN: /* Boolean is On or Off */ + string = g_strconcat(elem->name, "=", data_string, NULL); + break; + + default: + g_free(data_string); + g_return_if_fail(FALSE); + break; + } + + g_free(data_string); + + **items = string; + ++(*items); +} + +/** Pack an element into its protocol representation. + * + * @param data Pointer to an MsimMessageElement. + * @param user_data Pointer to a gchar ** array of string items. + * + * Called by msim_msg_pack(). Will pack the MsimMessageElement into + * a part of the protocol string and append it to the array. Caller + * is responsible for creating array to correct dimensions, and + * freeing each string element of the array added by this function. + */ +static void +msim_msg_pack_element(gpointer data, gpointer user_data) +{ + MsimMessageElement *elem; + gchar *string, *data_string; + gchar ***items; + + elem = (MsimMessageElement *)data; + items = (gchar ***)user_data; + + /* Exclude elements beginning with '_' from packed protocol messages. */ + if (elem->name[0] == '_') { + return; + } + + data_string = msim_msg_pack_element_data(elem); + + switch (elem->type) { + /* These types are represented by key name/value pairs (converted above). */ + case MSIM_TYPE_INTEGER: + case MSIM_TYPE_RAW: + case MSIM_TYPE_STRING: + case MSIM_TYPE_BINARY: + case MSIM_TYPE_DICTIONARY: + case MSIM_TYPE_LIST: + string = g_strconcat(elem->name, "\\", data_string, NULL); + break; + + /* Boolean is represented by absence or presence of name. */ + case MSIM_TYPE_BOOLEAN: + if (GPOINTER_TO_UINT(elem->data)) { + /* True - leave in, with blank value. */ + string = g_strdup_printf("%s\\", elem->name); + } else { + /* False - leave out. */ + string = g_strdup(""); + } + break; + + default: + g_free(data_string); + g_return_if_fail(FALSE); + break; + } + + g_free(data_string); + + **items = string; + ++(*items); +} + + +/** Return a packed string of a message suitable for sending over the wire. + * + * @return A string. Caller must g_free(). + */ +gchar * +msim_msg_pack(MsimMessage *msg) +{ + g_return_val_if_fail(msg != NULL, NULL); + + return msim_msg_pack_using(msg, msim_msg_pack_element, "\\", "\\", "\\final\\"); +} + +/** Return a packed string of a dictionary, suitable for embedding in MSIM_TYPE_DICTIONARY. + * + * @return A string; caller must g_free(). + */ +gchar * +msim_msg_pack_dict(MsimMessage *msg) +{ + g_return_val_if_fail(msg != NULL, NULL); + + return msim_msg_pack_using(msg, msim_msg_pack_element_dict, "\034", "", ""); +} + +/** + * Parse a raw protocol message string into a MsimMessage *. + * + * @param raw The raw message string to parse, will be g_free()'d. + * + * @return MsimMessage *. Caller should msim_msg_free() when done. + */ +MsimMessage * +msim_parse(gchar *raw) +{ + MsimMessage *msg; + gchar *token; + gchar **tokens; + gchar *key; + gchar *value; + int i; + + g_return_val_if_fail(raw != NULL, NULL); + + purple_debug_info("msim", "msim_parse: got <%s>\n", raw); + + key = NULL; + + /* All messages begin with a \. */ + if (raw[0] != '\\' || raw[1] == 0) { + purple_debug_info("msim", "msim_parse: incomplete/bad string, " + "missing initial backslash: <%s>\n", raw); + /* XXX: Should we try to recover, and read to first backslash? */ + + g_free(raw); + return NULL; + } + + msg = msim_msg_new(FALSE); + + for (tokens = g_strsplit(raw + 1, "\\", 0), i = 0; + (token = tokens[i]); + i++) { +#ifdef MSIM_DEBUG_PARSE + purple_debug_info("msim", "tok=<%s>, i%2=%d\n", token, i % 2); +#endif + if (i % 2) { + /* Odd-numbered ordinal is a value. */ + + value = token; + + /* Incoming protocol messages get tagged as MSIM_TYPE_RAW, which + * represents an untyped piece of data. msim_msg_get_* will + * convert to appropriate types for caller, and handle unescaping if needed. */ + msg = msim_msg_append(msg, g_strdup(key), MSIM_TYPE_RAW, g_strdup(value)); +#ifdef MSIM_DEBUG_PARSE + purple_debug_info("msim", "insert string: |%s|=|%s|\n", key, value); +#endif + } else { + /* Even numbered indexes are key names. */ + key = token; + } + } + g_strfreev(tokens); + + /* Can free now since all data was copied to hash key/values */ + g_free(raw); + + return msg; +} + +/** Search for and return the node in msg, matching name, or NULL. + * + * @param msg Message to search within. + * @param name Field name to search for. + * + * @return The GList * node for the MsimMessageElement with the given name, or NULL if not found or name is NULL. + * + * For internal use - users probably want to use msim_msg_get() to + * access the MsimMessageElement *, instead of the GList * container. + * + */ +static GList * +msim_msg_get_node(MsimMessage *msg, const gchar *name) +{ + GList *node; + + if (!name || !msg) { + return NULL; + } + + /* Linear search for the given name. O(n) but n is small. */ + for (node = msg; node != NULL; node = g_list_next(node)) { + MsimMessageElement *elem; + + elem = (MsimMessageElement *)node->data; + + g_return_val_if_fail(elem != NULL, NULL); + g_return_val_if_fail(elem->name != NULL, NULL); + + if (strcmp(elem->name, name) == 0) { + return node; + } + } + return NULL; +} + +/** Return the first MsimMessageElement * with given name in the MsimMessage *. + * + * @param name Name to search for. + * + * @return MsimMessageElement * matching name, or NULL. + * + * Note: useful fields of MsimMessageElement are 'data' and 'type', which + * you can access directly. But it is often more convenient to use + * another msim_msg_get_* that converts the data to what type you want. + */ +MsimMessageElement * +msim_msg_get(MsimMessage *msg, const gchar *name) +{ + GList *node; + + node = msim_msg_get_node(msg, name); + if (node) { + return (MsimMessageElement *)node->data; + } else { + return NULL; + } +} + +/** Return the data of an element of a given name, as a string. + * + * @param name Name of element. + * + * @return gchar * The data as a string, or NULL if not found. + * Caller must g_free(). + * + * Note that msim_msg_pack_element_data() is similar, but returns a string + * for inclusion into a raw protocol string (escaped and everything). + * This function unescapes the string for you, if needed. + */ +gchar * +msim_msg_get_string(MsimMessage *msg, const gchar *name) +{ + MsimMessageElement *elem; + + elem = msim_msg_get(msg, name); + if (!elem) { + return NULL; + } + + return msim_msg_get_string_from_element(elem); +} + +gchar * +msim_msg_get_string_from_element(MsimMessageElement *elem) +{ + g_return_val_if_fail(elem != NULL, NULL); + switch (elem->type) { + case MSIM_TYPE_INTEGER: + return g_strdup_printf("%d", GPOINTER_TO_UINT(elem->data)); + + case MSIM_TYPE_RAW: + /* Raw element from incoming message - if its a string, it'll + * be escaped. */ + return msim_unescape((gchar *)elem->data); + + case MSIM_TYPE_STRING: + /* Already unescaped. */ + return g_strdup((gchar *)elem->data); + + default: + purple_debug_info("msim", "msim_msg_get_string_element: type %d unknown, name %s\n", + elem->type, elem->name ? elem->name : "(NULL)"); + return NULL; + } +} + +/** Return an element as a new list. Caller frees with msim_msg_list_free(). */ +GList * +msim_msg_get_list(MsimMessage *msg, const gchar *name) +{ + MsimMessageElement *elem; + + elem = msim_msg_get(msg, name); + if (!elem) { + return NULL; + } + + return msim_msg_get_list_from_element(elem); +} + +GList * +msim_msg_get_list_from_element(MsimMessageElement *elem) +{ + g_return_val_if_fail(elem != NULL, NULL); + switch (elem->type) { + case MSIM_TYPE_LIST: + return msim_msg_list_copy((GList *)elem->data); + + case MSIM_TYPE_RAW: + return msim_msg_list_parse((gchar *)elem->data); + + default: + purple_debug_info("msim_msg_get_list", "type %d unknown, name %s\n", + elem->type, elem->name ? elem->name : "(NULL)"); + return NULL; + } +} + +/** + * Parse a \x1c-separated "dictionary" of key=value pairs into a hash table. + * + * @param raw The text of the dictionary to parse. Often the + * value for the 'body' field. + * + * @return A new MsimMessage *. Must msim_msg_free() when done. + */ +MsimMessage * +msim_msg_dictionary_parse(gchar *raw) +{ + MsimMessage *dict; + gchar *item; + gchar **items; + gchar **elements; + guint i; + + g_return_val_if_fail(raw != NULL, NULL); + + dict = msim_msg_new(NULL); + + for (items = g_strsplit(raw, "\x1c", 0), i = 0; + (item = items[i]); + i++) { + gchar *key, *value; + + elements = g_strsplit(item, "=", 2); + + key = elements[0]; + if (!key) { + purple_debug_info("msim", "msim_msg_parse_dictionary(%s): null key\n", + raw); + g_strfreev(elements); + break; + } + + value = elements[1]; + if (!value) { + purple_debug_info("msim", "msim_msg_parse_dictionary(%s): null value\n", + raw); + g_strfreev(elements); + break; + } + +#ifdef MSIM_DEBUG_PARSE + purple_debug_info("msim_msg_parse_dictionary","-- %s: %s\n", key ? key : "(NULL)", + value ? value : "(NULL)"); +#endif + /* TODO: free key; right now it is treated as static */ + dict = msim_msg_append(dict, g_strdup(key), MSIM_TYPE_RAW, g_strdup(value)); + + g_strfreev(elements); + } + + g_strfreev(items); + + return dict; +} + +/** Return an element as a new dictionary. Caller frees with msim_msg_free(). */ +MsimMessage * +msim_msg_get_dictionary(MsimMessage *msg, const gchar *name) +{ + MsimMessageElement *elem; + + elem = msim_msg_get(msg, name); + if (!elem) { + return NULL; + } + + return msim_msg_get_dictionary_from_element(elem); +} + +MsimMessage * +msim_msg_get_dictionary_from_element(MsimMessageElement *elem) +{ + g_return_val_if_fail(elem != NULL, NULL); + switch (elem->type) { + case MSIM_TYPE_DICTIONARY: + return msim_msg_clone((MsimMessage *)elem->data); + + case MSIM_TYPE_RAW: + return msim_msg_dictionary_parse((gchar *)elem->data); + + default: + purple_debug_info("msim_msg_get_dictionary", "type %d unknown, name %s\n", + elem->type, elem->name ? elem->name : "(NULL)"); + return NULL; + } +} + +/** Return the data of an element of a given name, as an unsigned integer. + * + * @param name Name of element. + * + * @return guint Numeric representation of data, or 0 if could not be converted / not found. + * + * Useful to obtain an element's data if you know it should be an integer, + * even if it is not stored as an MSIM_TYPE_INTEGER. MSIM_TYPE_STRING will + * be converted handled correctly, for example. + */ +guint +msim_msg_get_integer(MsimMessage *msg, const gchar *name) +{ + MsimMessageElement *elem; + + elem = msim_msg_get(msg, name); + + if (!elem) { + return 0; + } + + return msim_msg_get_integer_from_element(elem); +} + + +guint +msim_msg_get_integer_from_element(MsimMessageElement *elem) +{ + g_return_val_if_fail(elem != NULL, 0); + switch (elem->type) { + case MSIM_TYPE_INTEGER: + return GPOINTER_TO_UINT(elem->data); + + case MSIM_TYPE_RAW: + case MSIM_TYPE_STRING: + /* TODO: find out if we need larger integers */ + return (guint)atoi((gchar *)elem->data); + + default: + return 0; + } +} + +/** Return the data of an element of a given name, as a binary GString. + * + * @param binary_data A pointer to a new pointer, which will be filled in with the binary data. CALLER MUST g_free(). + * + * @param binary_length A pointer to an integer, which will be set to the binary data length. + * + * @return TRUE if successful, FALSE if not. + */ +gboolean +msim_msg_get_binary(MsimMessage *msg, const gchar *name, + gchar **binary_data, gsize *binary_length) +{ + MsimMessageElement *elem; + + elem = msim_msg_get(msg, name); + if (!elem) { + return FALSE; + } + + return msim_msg_get_binary_from_element(elem, binary_data, binary_length); +} + +gboolean +msim_msg_get_binary_from_element(MsimMessageElement *elem, gchar **binary_data, gsize *binary_length) +{ + GString *gs; + + g_return_val_if_fail(elem != NULL, FALSE); + + switch (elem->type) { + case MSIM_TYPE_RAW: + /* Incoming messages are tagged with MSIM_TYPE_RAW, and + * converted appropriately. They can still be "strings", just they won't + * be tagged as MSIM_TYPE_STRING (as MSIM_TYPE_STRING is intended to be used + * by msimprpl code for things like instant messages - stuff that should be + * escaped if needed). DWIM. + */ + + /* Previously, incoming messages were stored as MSIM_TYPE_STRING. + * This was fine for integers and strings, since they can easily be + * converted in msim_get_*, as desirable. However, it does not work + * well for binary strings. Consider: + * + * If incoming base64'd elements were tagged as MSIM_TYPE_STRING. + * msim_msg_get_binary() sees MSIM_TYPE_STRING, base64 decodes, returns. + * everything is fine. + * But then, msim_send() is called on the incoming message, which has + * a base64'd MSIM_TYPE_STRING that really is encoded binary. The values + * will be escaped since strings are escaped, and / becomes /2; no good. + * + */ + *binary_data = (gchar *)purple_base64_decode((const gchar *)elem->data, binary_length); + return TRUE; + + case MSIM_TYPE_BINARY: + gs = (GString *)elem->data; + + /* Duplicate data, so caller can g_free() it. */ + *binary_data = g_new0(char, gs->len); + memcpy(*binary_data, gs->str, gs->len); + + *binary_length = gs->len; + + return TRUE; + + + /* Rejected because if it isn't already a GString, have to g_new0 it and + * then caller has to ALSO free the GString! + * + * return (GString *)elem->data; */ + + default: + purple_debug_info("msim", "msim_msg_get_binary: unhandled type %d for key %s\n", + elem->type, elem->name ? elem->name : "(NULL)"); + return FALSE; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/protocols/myspace/message.h Mon Aug 27 21:59:11 2007 +0000 @@ -0,0 +1,117 @@ +/** MySpaceIM protocol messages + * + * \author Jeff Connelly + * + * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im> + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _MYSPACE_MESSAGE_H +#define _MYSPACE_MESSAGE_H + +#include <glib.h> + +/* Types */ +#define MsimMessage GList /* #define instead of typedef to avoid casting */ +typedef struct _MsimMessageElement +{ + const gchar *name; /**< Textual name of element. */ + guint type; /**< MSIM_TYPE_* code. */ + gpointer data; /**< Pointer to data, or GUINT_TO_POINTER for int/bool. */ +} MsimMessageElement; + +typedef gchar MsimMessageType; + +#define msim_msg_get_next_element_node(msg) ((MsimMessage *)(msg->next)) + +/* Protocol field types */ +#define MSIM_TYPE_RAW '-' +#define MSIM_TYPE_INTEGER 'i' +#define MSIM_TYPE_STRING 's' +#define MSIM_TYPE_BINARY 'b' +#define MSIM_TYPE_BOOLEAN 'f' +#define MSIM_TYPE_DICTIONARY 'd' +#define MSIM_TYPE_LIST 'l' + +gchar *msim_escape(const gchar *msg); +gchar *msim_unescape(const gchar *msg); + +MsimMessage *msim_msg_new(gchar *first_key, ...); +/* No sentinel attribute, because can leave off varargs if not_empty is FALSE. */ + +MsimMessage *msim_msg_clone(MsimMessage *old); +void msim_msg_free_element_data(MsimMessageElement *elem); +void msim_msg_free(MsimMessage *msg); +MsimMessage *msim_msg_append(MsimMessage *msg, const gchar *name, MsimMessageType type, gpointer data); +MsimMessage *msim_msg_insert_before(MsimMessage *msg, const gchar *name_before, const gchar *name, MsimMessageType type, gpointer data); +gchar *msim_msg_dump_to_str(MsimMessage *msg); +gchar *msim_msg_pack_element_data(MsimMessageElement *elem); +void msim_msg_dump(const char *fmt_string, MsimMessage *msg); +gchar *msim_msg_pack(MsimMessage *msg); +gchar *msim_msg_pack_dict(MsimMessage *msg); + +GList *msim_msg_list_copy(GList *old); +void msim_msg_list_free(GList *l); +GList *msim_msg_list_parse(const gchar *raw); + +/* Defined in myspace.h */ +struct _MsimSession; + +/* Based on http://permalink.gmane.org/gmane.comp.parsers.sparse/695 + * Define macros for useful gcc attributes. */ +#ifdef __GNUC__ +#define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__) +#define FORMAT_ATTR(pos) __attribute__ ((__format__ (__printf__, pos, pos+1))) +#define NORETURN_ATTR __attribute__ ((__noreturn__)) +/* __sentinel__ attribute was introduced in gcc 3.5 */ +#if (GCC_VERSION >= 3005) + #define SENTINEL_ATTR __attribute__ ((__sentinel__(0))) +#else + #define SENTINEL_ATTR +#endif /* gcc >= 3.5 */ +#else + #define FORMAT_ATTR(pos) + #define NORETURN_ATTR + #define SENTINEL_ATTR +#endif + +/* Cause gcc to emit "a missing sentinel in function call" if forgot + * to write NULL as last, terminating parameter. */ +gboolean msim_send(struct _MsimSession *session, ...) SENTINEL_ATTR; + +gboolean msim_msg_send(struct _MsimSession *session, MsimMessage *msg); + +MsimMessage *msim_parse(gchar *raw); +MsimMessage *msim_msg_dictionary_parse(gchar *raw); + +MsimMessageElement *msim_msg_get(MsimMessage *msg, const gchar *name); + +/* Retrieve data by name */ +gchar *msim_msg_get_string(MsimMessage *msg, const gchar *name); +GList *msim_msg_get_list(MsimMessage *msg, const gchar *name); +MsimMessage *msim_msg_get_dictionary(MsimMessage *msg, const gchar *name); +guint msim_msg_get_integer(MsimMessage *msg, const gchar *name); +gboolean msim_msg_get_binary(MsimMessage *msg, const gchar *name, gchar **binary_data, gsize *binary_length); + +/* Retrieve data by element (MsimMessageElement *), returned from msim_msg_get() */ +gchar *msim_msg_get_string_from_element(MsimMessageElement *elem); +GList *msim_msg_get_list_from_element(MsimMessageElement *elem); +MsimMessage *msim_msg_get_dictionary_from_element(MsimMessageElement *elem); +guint msim_msg_get_integer_from_element(MsimMessageElement *elem); +gboolean msim_msg_get_binary_from_element(MsimMessageElement *elem, + gchar **binary_data, gsize *binary_length); + +#endif /* _MYSPACE_MESSAGE_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/protocols/myspace/myspace.c Mon Aug 27 21:59:11 2007 +0000 @@ -0,0 +1,3181 @@ +/* MySpaceIM Protocol Plugin + * + * \author Jeff Connelly + * + * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im> + * + * Based on Purple's "C Plugin HOWTO" hello world example. + * + * Code also drawn from mockprpl: + * http://snarfed.org/space/purple+mock+protocol+plugin + * Copyright (C) 2004-2007, Ryan Barrett <mockprpl@ryanb.org> + * + * and some constructs also based on existing Purple plugins, which are: + * Copyright (C) 2003, Robbert Haarman <purple@inglorion.net> + * Copyright (C) 2003, Ethan Blanton <eblanton@cs.purdue.edu> + * Copyright (C) 2000-2003, Rob Flynn <rob@tgflinux.com> + * Copyright (C) 1998-1999, Mark Spencer <markster@marko.net> + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define PURPLE_PLUGIN + +#include "myspace.h" + +/* Internal functions */ + +#ifdef MSIM_DEBUG_MSG +static void print_hash_item(gpointer key, gpointer value, gpointer user_data); +#endif + +static int msim_send_really_raw(PurpleConnection *gc, const char *buf, int total_bytes); +static gboolean msim_login_challenge(MsimSession *session, MsimMessage *msg); +static const gchar *msim_compute_login_response(const gchar nonce[2 * NONCE_SIZE], const gchar *email, const gchar *password, guint *response_len); + +static gboolean msim_incoming_bm_record_cv(MsimSession *session, MsimMessage *msg); +static gboolean msim_incoming_bm(MsimSession *session, MsimMessage *msg); +static gboolean msim_incoming_status(MsimSession *session, MsimMessage *msg); +static gboolean msim_incoming_im(MsimSession *session, MsimMessage *msg); +/* static gboolean msim_incoming_zap(MsimSession *session, MsimMessage *msg); - in zap.c */ +static gboolean msim_incoming_action(MsimSession *session, MsimMessage *msg); +static gboolean msim_incoming_media(MsimSession *session, MsimMessage *msg); +static gboolean msim_incoming_unofficial_client(MsimSession *session, + MsimMessage *msg); + +#ifdef MSIM_SEND_CLIENT_VERSION +static gboolean msim_send_unofficial_client(MsimSession *session, gchar *username); +#endif + +static void msim_get_info_cb(MsimSession *session, MsimMessage *userinfo, gpointer data); + +static void msim_set_status_code(MsimSession *session, guint code, gchar *statstring); + +static gboolean msim_process_server_info(MsimSession *session, MsimMessage *msg); +static gboolean msim_web_challenge(MsimSession *session, MsimMessage *msg); +static gboolean msim_process_reply(MsimSession *session, MsimMessage *msg); + +static gboolean msim_preprocess_incoming(MsimSession *session, MsimMessage *msg); + +#ifdef MSIM_USE_KEEPALIVE +static gboolean msim_check_alive(gpointer data); +#endif + +static gboolean msim_we_are_logged_on(MsimSession *session, MsimMessage *msg); + +static gboolean msim_process(MsimSession *session, MsimMessage *msg); + +static MsimMessage *msim_do_postprocessing(MsimMessage *msg, const gchar *uid_field_name, const gchar *uid_before, guint uid); +static void msim_postprocess_outgoing_cb(MsimSession *session, MsimMessage *userinfo, gpointer data); +static gboolean msim_postprocess_outgoing(MsimSession *session, MsimMessage *msg, const gchar *username, const gchar *uid_field_name, const gchar *uid_before); + +static gboolean msim_error(MsimSession *session, MsimMessage *msg); + +static void msim_check_inbox_cb(MsimSession *session, MsimMessage *userinfo, gpointer data); +static gboolean msim_check_inbox(gpointer data); + +static void msim_input_cb(gpointer gc_uncasted, gint source, PurpleInputCondition cond); + + +static void msim_connect_cb(gpointer data, gint source, const gchar *error_message); + +static void msim_import_friends(PurplePluginAction *action); +static void msim_import_friends_cb(MsimSession *session, MsimMessage *reply, gpointer user_data); +static gboolean msim_get_contact_list(MsimSession *session, int what_to_do_after); + +static gboolean msim_uri_handler(const gchar *proto, const gchar *cmd, GHashTable *params); +static void msim_uri_handler_addContact_cb(MsimSession *session, MsimMessage *userinfo, gpointer data); +static void msim_uri_handler_sendIM_cb(MsimSession *session, MsimMessage *userinfo, gpointer data); + +/** + * Load the plugin. + */ +gboolean +msim_load(PurplePlugin *plugin) +{ + /* If compiled to use RC4 from libpurple, check if it is really there. */ + if (!purple_ciphers_find_cipher("rc4")) { + purple_debug_error("msim", "rc4 not in libpurple, but it is required - not loading MySpaceIM plugin!\n"); + purple_notify_error(plugin, _("Missing Cipher"), + _("The RC4 cipher could not be found"), + _("Upgrade " + "to a libpurple with RC4 support (>= 2.0.1). MySpaceIM " + "plugin will not be loaded.")); + return FALSE; + } + return TRUE; +} + +/** + * Get possible user status types. Based on mockprpl. + * + * @return GList of status types. + */ +GList * +msim_status_types(PurpleAccount *acct) +{ + GList *types; + PurpleStatusType *status; + + purple_debug_info("myspace", "returning status types\n"); + + types = NULL; + + /* Statuses are almost all the same. Define a macro to reduce code repetition. */ +#define _MSIM_ADD_NEW_STATUS(prim) status = \ + purple_status_type_new_with_attrs( \ + prim, /* PurpleStatusPrimitive */ \ + NULL, /* id - use default */ \ + NULL, /* name - use default */ \ + TRUE, /* savable */ \ + TRUE, /* user_settable */ \ + FALSE, /* not independent */ \ + \ + /* Attributes - each status can have a message. */ \ + "message", \ + _("Message"), \ + purple_value_new(PURPLE_TYPE_STRING), \ + NULL); \ + \ + \ + types = g_list_append(types, status) + + + _MSIM_ADD_NEW_STATUS(PURPLE_STATUS_AVAILABLE); + _MSIM_ADD_NEW_STATUS(PURPLE_STATUS_AWAY); + _MSIM_ADD_NEW_STATUS(PURPLE_STATUS_OFFLINE); + _MSIM_ADD_NEW_STATUS(PURPLE_STATUS_INVISIBLE); + + + return types; +} + +/** + * Return the icon name for a buddy and account. + * + * @param acct The account to find the icon for, or NULL for protocol icon. + * @param buddy The buddy to find the icon for, or NULL for the account icon. + * + * @return The base icon name string. + */ +const gchar * +msim_list_icon(PurpleAccount *acct, PurpleBuddy *buddy) +{ + /* Use a MySpace icon submitted by hbons at + * http://developer.pidgin.im/wiki/MySpaceIM. */ + return "myspace"; +} + +#ifdef MSIM_DEBUG_MSG +static void +print_hash_item(gpointer key, gpointer value, gpointer user_data) +{ + purple_debug_info("msim", "%s=%s\n", + key ? (gchar *)key : "(NULL)", + value ? (gchar *)value : "(NULL)"); +} +#endif + +/** + * Send raw data (given as a NUL-terminated string) to the server. + * + * @param session + * @param msg The raw data to send, in a NUL-terminated string. + * + * @return TRUE if succeeded, FALSE if not. + * + */ +gboolean +msim_send_raw(MsimSession *session, const gchar *msg) +{ + g_return_val_if_fail(MSIM_SESSION_VALID(session), FALSE); + g_return_val_if_fail(msg != NULL, FALSE); + + purple_debug_info("msim", "msim_send_raw: writing <%s>\n", msg); + + return msim_send_really_raw(session->gc, msg, strlen(msg)) == + strlen(msg); +} + +/** Send raw data to the server, possibly with embedded NULs. + * + * Used in prpl_info struct, so that plugins can have the most possible + * control of what is sent over the connection. Inside this prpl, + * msim_send_raw() is used, since it sends NUL-terminated strings (easier). + * + * @param gc PurpleConnection + * @param buf Buffer to send + * @param total_bytes Size of buffer to send + * + * @return Bytes successfully sent, or -1 on error. + */ +static int +msim_send_really_raw(PurpleConnection *gc, const char *buf, int total_bytes) +{ + int total_bytes_sent; + MsimSession *session; + + g_return_val_if_fail(gc != NULL, -1); + g_return_val_if_fail(buf != NULL, -1); + g_return_val_if_fail(total_bytes >= 0, -1); + + session = (MsimSession *)gc->proto_data; + + g_return_val_if_fail(MSIM_SESSION_VALID(session), -1); + + /* Loop until all data is sent, or a failure occurs. */ + total_bytes_sent = 0; + do { + int bytes_sent; + + bytes_sent = send(session->fd, buf + total_bytes_sent, + total_bytes - total_bytes_sent, 0); + + if (bytes_sent < 0) { + purple_debug_info("msim", "msim_send_raw(%s): send() failed: %s\n", + buf, g_strerror(errno)); + return total_bytes_sent; + } + total_bytes_sent += bytes_sent; + + } while(total_bytes_sent < total_bytes); + + return total_bytes_sent; +} + + +/** + * Start logging in to the MSIM servers. + * + * @param acct Account information to use to login. + */ +void +msim_login(PurpleAccount *acct) +{ + PurpleConnection *gc; + const gchar *host; + int port; + + g_return_if_fail(acct != NULL); + g_return_if_fail(acct->username != NULL); + + purple_debug_info("msim", "logging in %s\n", acct->username); + + gc = purple_account_get_connection(acct); + gc->proto_data = msim_session_new(acct); + gc->flags |= PURPLE_CONNECTION_HTML | PURPLE_CONNECTION_NO_URLDESC; + +#ifdef MSIM_MAX_PASSWORD_LENGTH + /* Passwords are limited in length. */ + if (strlen(acct->password) > MSIM_MAX_PASSWORD_LENGTH) { + gchar *str; + + str = g_strdup_printf( + _("Sorry, passwords over %d characters in length (yours is " + "%d) are not supported by MySpace."), + MSIM_MAX_PASSWORD_LENGTH, + (int)strlen(acct->password)); + + /* Notify an error message also, because this is important! */ + purple_notify_error(acct, g_strdup(_("MySpaceIM Error")), str, NULL); + + purple_connection_error(gc, str); + + g_free(str); + } +#endif + + /* 1. connect to server */ + purple_connection_update_progress(gc, _("Connecting"), + 0, /* which connection step this is */ + 4); /* total number of steps */ + + host = purple_account_get_string(acct, "server", MSIM_SERVER); + port = purple_account_get_int(acct, "port", MSIM_PORT); + + /* From purple.sf.net/api: + * """Note that this function name can be misleading--although it is called + * "proxy connect," it is used for establishing any outgoing TCP connection, + * whether through a proxy or not.""" */ + + /* Calls msim_connect_cb when connected. */ + if (!purple_proxy_connect(gc, acct, host, port, msim_connect_cb, gc)) { + /* TODO: try other ports if in auto mode, then save + * working port and try that first next time. */ + purple_connection_error(gc, _("Couldn't create socket")); + return; + } +} + +/** + * Process a login challenge, sending a response. + * + * @param session + * @param msg Login challenge message. + * + * @return TRUE if successful, FALSE if not + */ +static gboolean +msim_login_challenge(MsimSession *session, MsimMessage *msg) +{ + PurpleAccount *account; + const gchar *response; + guint response_len; + gchar *nc; + gsize nc_len; + + g_return_val_if_fail(MSIM_SESSION_VALID(session), FALSE); + g_return_val_if_fail(msg != NULL, FALSE); + + g_return_val_if_fail(msim_msg_get_binary(msg, "nc", &nc, &nc_len), FALSE); + + account = session->account; + + g_return_val_if_fail(account != NULL, FALSE); + + purple_connection_update_progress(session->gc, _("Reading challenge"), 1, 4); + + purple_debug_info("msim", "nc is %d bytes, decoded\n", nc_len); + + if (nc_len != MSIM_AUTH_CHALLENGE_LENGTH) { + purple_debug_info("msim", "bad nc length: %x != 0x%x\n", nc_len, MSIM_AUTH_CHALLENGE_LENGTH); + purple_connection_error(session->gc, _("Unexpected challenge length from server")); + return FALSE; + } + + purple_connection_update_progress(session->gc, _("Logging in"), 2, 4); + + response_len = 0; + response = msim_compute_login_response(nc, account->username, account->password, &response_len); + + g_free(nc); + + return msim_send(session, + "login2", MSIM_TYPE_INTEGER, MSIM_AUTH_ALGORITHM, + /* This is actually user's email address. */ + "username", MSIM_TYPE_STRING, g_strdup(account->username), + /* GString and gchar * response will be freed in msim_msg_free() in msim_send(). */ + "response", MSIM_TYPE_BINARY, g_string_new_len(response, response_len), + "clientver", MSIM_TYPE_INTEGER, MSIM_CLIENT_VERSION, + "langid", MSIM_TYPE_INTEGER, MSIM_LANGUAGE_ID_ENGLISH, + "imlang", MSIM_TYPE_STRING, g_strdup(MSIM_LANGUAGE_NAME_ENGLISH), + "reconn", MSIM_TYPE_INTEGER, 0, + "status", MSIM_TYPE_INTEGER, 100, + "id", MSIM_TYPE_INTEGER, 1, + NULL); +} + +/** + * Compute the base64'd login challenge response based on username, password, nonce, and IPs. + * + * @param nonce The base64 encoded nonce ('nc') field from the server. + * @param email User's email address (used as login name). + * @param password User's cleartext password. + * @param response_len Will be written with response length. + * + * @return Binary login challenge response, ready to send to the server. + * Must be g_free()'d when finished. NULL if error. + */ +static const gchar * +msim_compute_login_response(const gchar nonce[2 * NONCE_SIZE], + const gchar *email, const gchar *password, guint *response_len) +{ + PurpleCipherContext *key_context; + PurpleCipher *sha1; + PurpleCipherContext *rc4; + + guchar hash_pw[HASH_SIZE]; + guchar key[HASH_SIZE]; + gchar *password_utf16le, *password_utf8_lc; + guchar *data; + guchar *data_out; + size_t data_len, data_out_len; + gsize conv_bytes_read, conv_bytes_written; + GError *conv_error; +#ifdef MSIM_DEBUG_LOGIN_CHALLENGE + int i; +#endif + + g_return_val_if_fail(nonce != NULL, NULL); + g_return_val_if_fail(email != NULL, NULL); + g_return_val_if_fail(password != NULL, NULL); + g_return_val_if_fail(response_len != NULL, NULL); + + /* Convert password to lowercase (required for passwords containing + * uppercase characters). MySpace passwords are lowercase, + * see ticket #2066. */ + password_utf8_lc = g_utf8_strdown(password, -1); + + /* Convert ASCII password to UTF16 little endian */ + purple_debug_info("msim", "converting password to UTF-16LE\n"); + conv_error = NULL; + password_utf16le = g_convert(password_utf8_lc, -1, "UTF-16LE", "UTF-8", + &conv_bytes_read, &conv_bytes_written, &conv_error); + g_free(password_utf8_lc); + + g_return_val_if_fail(conv_bytes_read == strlen(password), NULL); + + if (conv_error != NULL) { + purple_debug_error("msim", + "g_convert password UTF8->UTF16LE failed: %s", + conv_error->message); + g_error_free(conv_error); + return NULL; + } + + /* Compute password hash */ + purple_cipher_digest_region("sha1", (guchar *)password_utf16le, + conv_bytes_written, sizeof(hash_pw), hash_pw, NULL); + g_free(password_utf16le); + +#ifdef MSIM_DEBUG_LOGIN_CHALLENGE + purple_debug_info("msim", "pwhash = "); + for (i = 0; i < sizeof(hash_pw); i++) + purple_debug_info("msim", "%.2x ", hash_pw[i]); + purple_debug_info("msim", "\n"); +#endif + + /* key = sha1(sha1(pw) + nonce2) */ + sha1 = purple_ciphers_find_cipher("sha1"); + key_context = purple_cipher_context_new(sha1, NULL); + purple_cipher_context_append(key_context, hash_pw, HASH_SIZE); + purple_cipher_context_append(key_context, (guchar *)(nonce + NONCE_SIZE), NONCE_SIZE); + purple_cipher_context_digest(key_context, sizeof(key), key, NULL); + +#ifdef MSIM_DEBUG_LOGIN_CHALLENGE + purple_debug_info("msim", "key = "); + for (i = 0; i < sizeof(key); i++) { + purple_debug_info("msim", "%.2x ", key[i]); + } + purple_debug_info("msim", "\n"); +#endif + + rc4 = purple_cipher_context_new_by_name("rc4", NULL); + + /* Note: 'key' variable is 0x14 bytes (from SHA-1 hash), + * but only first 0x10 used for the RC4 key. */ + purple_cipher_context_set_option(rc4, "key_len", (gpointer)0x10); + purple_cipher_context_set_key(rc4, key); + + /* TODO: obtain IPs of network interfaces */ + + /* rc4 encrypt: + * nonce1+email+IP list */ + + data_len = NONCE_SIZE + strlen(email) + MSIM_LOGIN_IP_LIST_LEN; + data = g_new0(guchar, data_len); + memcpy(data, nonce, NONCE_SIZE); + memcpy(data + NONCE_SIZE, email, strlen(email)); + memcpy(data + NONCE_SIZE + strlen(email), MSIM_LOGIN_IP_LIST, MSIM_LOGIN_IP_LIST_LEN); + + data_out = g_new0(guchar, data_len); + + purple_cipher_context_encrypt(rc4, (const guchar *)data, + data_len, data_out, &data_out_len); + purple_cipher_context_destroy(rc4); + + g_assert(data_out_len == data_len); + +#ifdef MSIM_DEBUG_LOGIN_CHALLENGE + purple_debug_info("msim", "response=<%s>\n", data_out); +#endif + + *response_len = data_out_len; + + return (const gchar *)data_out; +} + +/** + * Schedule an IM to be sent once the user ID is looked up. + * + * @param gc Connection. + * @param who A user id, email, or username to send the message to. + * @param message Instant message text to send. + * @param flags Flags. + * + * @return 1 if successful or postponed, -1 if failed + * + * Allows sending to a user by username, email address, or userid. If + * a username or email address is given, the userid must be looked up. + * This function does that by calling msim_postprocess_outgoing(). + */ +int +msim_send_im(PurpleConnection *gc, const gchar *who, const gchar *message, + PurpleMessageFlags flags) +{ + MsimSession *session; + gchar *message_msim; + int rc; + + g_return_val_if_fail(gc != NULL, -1); + g_return_val_if_fail(who != NULL, -1); + g_return_val_if_fail(message != NULL, -1); + + /* 'flags' has many options, not used here. */ + + session = (MsimSession *)gc->proto_data; + + g_return_val_if_fail(MSIM_SESSION_VALID(session), -1); + + message_msim = html_to_msim_markup(session, message); + + if (msim_send_bm(session, who, message_msim, MSIM_BM_INSTANT)) { + /* Return 1 to have Purple show this IM as being sent, 0 to not. I always + * return 1 even if the message could not be sent, since I don't know if + * it has failed yet--because the IM is only sent after the userid is + * retrieved from the server (which happens after this function returns). + */ + /* TODO: maybe if message is delayed, don't echo to conv window, + * but do echo it to conv window manually once it is actually + * sent? Would be complicated. */ + rc = 1; + } else { + rc = -1; + } + + g_free(message_msim); + + /* + * In MySpace, you login with your email address, but don't talk to other + * users using their email address. So there is currently an asymmetry in the + * IM windows when using this plugin: + * + * you@example.com: hello + * some_other_user: what's going on? + * you@example.com: just coding a prpl + * + * TODO: Make the sent IM's appear as from the user's username, instead of + * their email address. Purple uses the login (in MSIM, the email)--change this. + */ + + return rc; +} + +/** Send a buddy message of a given type. + * + * @param session + * @param who Username to send message to. + * @param text Message text to send. Not freed; will be copied. + * @param type A MSIM_BM_* constant. + * + * @return TRUE if success, FALSE if fail. + * + * Buddy messages ('bm') include instant messages, action messages, status messages, etc. + * + */ +gboolean +msim_send_bm(MsimSession *session, const gchar *who, const gchar *text, + int type) +{ + gboolean rc; + MsimMessage *msg; + const gchar *from_username; + + g_return_val_if_fail(MSIM_SESSION_VALID(session), FALSE); + g_return_val_if_fail(who != NULL, FALSE); + g_return_val_if_fail(text != NULL, FALSE); + + from_username = session->account->username; + + g_return_val_if_fail(from_username != NULL, FALSE); + + purple_debug_info("msim", "sending %d message from %s to %s: %s\n", + type, from_username, who, text); + + msg = msim_msg_new( + "bm", MSIM_TYPE_INTEGER, GUINT_TO_POINTER(type), + "sesskey", MSIM_TYPE_INTEGER, GUINT_TO_POINTER(session->sesskey), + /* 't' will be inserted here */ + "cv", MSIM_TYPE_INTEGER, GUINT_TO_POINTER(MSIM_CLIENT_VERSION), + "msg", MSIM_TYPE_STRING, g_strdup(text), + NULL); + + rc = msim_postprocess_outgoing(session, msg, who, "t", "cv"); + + msim_msg_free(msg); + + return rc; +} + + +/** Record the client version in the buddy list, from an incoming message. */ +static gboolean +msim_incoming_bm_record_cv(MsimSession *session, MsimMessage *msg) +{ + gchar *username, *cv; + gboolean ret; + MsimUser *user; + + username = msim_msg_get_string(msg, "_username"); + cv = msim_msg_get_string(msg, "cv"); + + g_return_val_if_fail(username != NULL, FALSE); + if (!cv) { + /* No client version to record, don't worry about it. */ + return FALSE; + } + + user = msim_find_user(session, username); + + if (user) { + user->client_cv = atol(cv); + ret = TRUE; + } else { + ret = FALSE; + } + + g_free(username); + g_free(cv); + + return ret; +} + +/** Handle an incoming buddy message. */ +static gboolean +msim_incoming_bm(MsimSession *session, MsimMessage *msg) +{ + guint bm; + + bm = msim_msg_get_integer(msg, "bm"); + + msim_incoming_bm_record_cv(session, msg); + + switch (bm) { + case MSIM_BM_STATUS: + return msim_incoming_status(session, msg); + case MSIM_BM_INSTANT: + return msim_incoming_im(session, msg); + case MSIM_BM_ACTION: + return msim_incoming_action(session, msg); + case MSIM_BM_MEDIA: + return msim_incoming_media(session, msg); + case MSIM_BM_UNOFFICIAL_CLIENT: + return msim_incoming_unofficial_client(session, msg); + default: + /* Not really an IM, but show it for informational + * purposes during development. */ + return msim_incoming_im(session, msg); + } +} + +/** + * Handle an incoming instant message. + * + * @param session The session + * @param msg Message from the server, containing 'f' (userid from) and 'msg'. + * Should also contain username in _username from preprocessing. + * + * @return TRUE if successful. + */ +static gboolean +msim_incoming_im(MsimSession *session, MsimMessage *msg) +{ + gchar *username, *msg_msim_markup, *msg_purple_markup; + + g_return_val_if_fail(MSIM_SESSION_VALID(session), FALSE); + g_return_val_if_fail(msg != NULL, FALSE); + + username = msim_msg_get_string(msg, "_username"); + g_return_val_if_fail(username != NULL, FALSE); + + msg_msim_markup = msim_msg_get_string(msg, "msg"); + g_return_val_if_fail(msg_msim_markup != NULL, FALSE); + + msg_purple_markup = msim_markup_to_html(session, msg_msim_markup); + g_free(msg_msim_markup); + + serv_got_im(session->gc, username, msg_purple_markup, + PURPLE_MESSAGE_RECV, time(NULL)); + + g_free(username); + g_free(msg_purple_markup); + + return TRUE; +} + +/** + * Process unrecognized information. + * + * @param session + * @param msg An MsimMessage that was unrecognized, or NULL. + * @param note Information on what was unrecognized, or NULL. + */ +void +msim_unrecognized(MsimSession *session, MsimMessage *msg, gchar *note) +{ + /* TODO: Some more context, outwardly equivalent to a backtrace, + * for helping figure out what this msg is for. What was going on? + * But not too much information so that a user + * posting this dump reveals confidential information. + */ + + /* TODO: dump unknown msgs to file, so user can send them to me + * if they wish, to help add support for new messages (inspired + * by Alexandr Shutko, who maintains OSCAR protocol documentation). */ + + purple_debug_info("msim", "Unrecognized data on account for %s\n", + (session && session->account && session->account->username) ? + session->account->username : "(NULL)"); + if (note) { + purple_debug_info("msim", "(Note: %s)\n", note); + } + + if (msg) { + msim_msg_dump("Unrecognized message dump: %s\n", msg); + } +} + +/** + * Handle an incoming action message. + * + * @param session + * @param msg + * + * @return TRUE if successful. + * + */ +static gboolean +msim_incoming_action(MsimSession *session, MsimMessage *msg) +{ + gchar *msg_text, *username; + gboolean rc; + + g_return_val_if_fail(MSIM_SESSION_VALID(session), FALSE); + g_return_val_if_fail(msg != NULL, FALSE); + + msg_text = msim_msg_get_string(msg, "msg"); + g_return_val_if_fail(msg_text != NULL, FALSE); + + username = msim_msg_get_string(msg, "_username"); + g_return_val_if_fail(username != NULL, FALSE); + + purple_debug_info("msim", "msim_incoming_action: action <%s> from <%d>\n", + msg_text, username); + + if (g_str_equal(msg_text, "%typing%")) { + /* TODO: find out if msim repeatedly sends typing messages, so we can + * give it a timeout. Right now, there does seem to be an inordinately + * amount of time between typing stopped-typing notifications. */ + serv_got_typing(session->gc, username, 0, PURPLE_TYPING); + rc = TRUE; + } else if (g_str_equal(msg_text, "%stoptyping%")) { + serv_got_typing_stopped(session->gc, username); + rc = TRUE; + } else if (strstr(msg_text, "!!!ZAP_SEND!!!=RTE_BTN_ZAPS_")) { + rc = msim_incoming_zap(session, msg); + } else { + msim_unrecognized(session, msg, + "got to msim_incoming_action but unrecognized value for 'msg'"); + rc = FALSE; + } + + g_free(msg_text); + g_free(username); + + return rc; +} + +/* Process an incoming media (message background?) message. */ +static gboolean +msim_incoming_media(MsimSession *session, MsimMessage *msg) +{ + gchar *username, *text; + + username = msim_msg_get_string(msg, "_username"); + text = msim_msg_get_string(msg, "msg"); + + g_return_val_if_fail(username != NULL, FALSE); + g_return_val_if_fail(text != NULL, FALSE); + + purple_debug_info("msim", "msim_incoming_media: from %s, got msg=%s\n", username, text); + + /* Media messages are sent when the user opens a window to someone. + * Tell libpurple they started typing and stopped typing, to inform the Psychic + * Mode plugin so it too can open a window to the user. */ + serv_got_typing(session->gc, username, 0, PURPLE_TYPING); + serv_got_typing_stopped(session->gc, username); + + g_free(username); + + return TRUE; +} + +/* Process an incoming "unofficial client" message. The plugin for + * Miranda IM sends this message with the plugin information. */ +static gboolean +msim_incoming_unofficial_client(MsimSession *session, MsimMessage *msg) +{ + MsimUser *user; + gchar *username, *client_info; + + username = msim_msg_get_string(msg, "_username"); + client_info = msim_msg_get_string(msg, "msg"); + + g_return_val_if_fail(username != NULL, FALSE); + g_return_val_if_fail(client_info != NULL, FALSE); + + purple_debug_info("msim", "msim_incoming_unofficial_client: %s is using client %s\n", + username, client_info); + + user = msim_find_user(session, username); + + g_return_val_if_fail(user != NULL, FALSE); + + if (user->client_info) { + g_free(user->client_info); + } + user->client_info = client_info; + + g_free(username); + /* Do not free client_info - the MsimUser now owns it. */ + + return TRUE; +} + + +#ifdef MSIM_SEND_CLIENT_VERSION +/** Send our client version to another unofficial client that understands it. */ +static gboolean +msim_send_unofficial_client(MsimSession *session, gchar *username) +{ + gchar *our_info; + gboolean ret; + + our_info = g_strdup_printf("Libpurple %d.%d.%d - msimprpl %s", + PURPLE_MAJOR_VERSION, + PURPLE_MINOR_VERSION, + PURPLE_MICRO_VERSION, + MSIM_PRPL_VERSION_STRING); + + ret = msim_send_bm(session, username, our_info, MSIM_BM_UNOFFICIAL_CLIENT); + + return ret; +} +#endif + +/** + * Handle when our user starts or stops typing to another user. + * + * @param gc + * @param name The buddy name to which our user is typing to + * @param state PURPLE_TYPING, PURPLE_TYPED, PURPLE_NOT_TYPING + * + * @return 0 + */ +unsigned int +msim_send_typing(PurpleConnection *gc, const gchar *name, + PurpleTypingState state) +{ + const gchar *typing_str; + MsimSession *session; + + g_return_val_if_fail(gc != NULL, 0); + g_return_val_if_fail(name != NULL, 0); + + session = (MsimSession *)gc->proto_data; + + g_return_val_if_fail(MSIM_SESSION_VALID(session), 0); + + switch (state) { + case PURPLE_TYPING: + typing_str = "%typing%"; + break; + + case PURPLE_TYPED: + case PURPLE_NOT_TYPING: + default: + typing_str = "%stoptyping%"; + break; + } + + purple_debug_info("msim", "msim_send_typing(%s): %d (%s)\n", name, state, typing_str); + msim_send_bm(session, name, typing_str, MSIM_BM_ACTION); + return 0; +} + + + +/** Callback for msim_get_info(), for when user info is received. */ +static void +msim_get_info_cb(MsimSession *session, MsimMessage *user_info_msg, + gpointer data) +{ + MsimMessage *msg; + gchar *username; + PurpleNotifyUserInfo *user_info; + MsimUser *user; + gboolean temporary_user; + + g_return_if_fail(MSIM_SESSION_VALID(session)); + + /* Get user{name,id} from msim_get_info, passed as an MsimMessage for + orthogonality. */ + msg = (MsimMessage *)data; + g_return_if_fail(msg != NULL); + + username = msim_msg_get_string(msg, "user"); + if (!username) { + purple_debug_info("msim", "msim_get_info_cb: no 'user' in msg"); + return; + } + + msim_msg_free(msg); + purple_debug_info("msim", "msim_get_info_cb: got for user: %s\n", username); + + user = msim_find_user(session, username); + + if (!user) { + /* User isn't on blist, create a temporary user to store info. */ + temporary_user = TRUE; + user = g_new0(MsimUser, 1); + } else { + temporary_user = FALSE; + } + + /* Update user structure with new information */ + msim_store_user_info(session, user_info_msg, user); + + user_info = purple_notify_user_info_new(); + + /* Append data from MsimUser to PurpleNotifyUserInfo for display, full */ + msim_append_user_info(session, user_info, user, TRUE); + + purple_notify_userinfo(session->gc, username, user_info, NULL, NULL); + purple_debug_info("msim", "msim_get_info_cb: username=%s\n", username); + + purple_notify_user_info_destroy(user_info); + /* TODO: do not free username, since it will be used by user_info? */ + + if (temporary_user) { + g_free(user->client_info); + g_free(user->gender); + g_free(user->location); + g_free(user->headline); + g_free(user->display_name); + g_free(user->username); + g_free(user->band_name); + g_free(user->song_name); + g_free(user->image_url); + g_free(user); + } + +} + +/** Retrieve a user's profile. + * @param username Username, user ID, or email address to lookup. + */ +void +msim_get_info(PurpleConnection *gc, const gchar *username) +{ + MsimSession *session; + MsimUser *user; + guint uid; + gchar *user_to_lookup; + MsimMessage *user_msg; + + g_return_if_fail(gc != NULL); + g_return_if_fail(username != NULL); + + session = (MsimSession *)gc->proto_data; + + g_return_if_fail(MSIM_SESSION_VALID(session)); + + /* Obtain uid of buddy. */ + user = msim_find_user(session, username); + + /* If is on buddy list, lookup by uid since it is faster. */ + if (user && (uid = purple_blist_node_get_int(&user->buddy->node, "UserID"))) { + user_to_lookup = g_strdup_printf("%d", uid); + } else { + /* Looking up buddy not on blist. Lookup by whatever user entered. */ + user_to_lookup = g_strdup(username); + } + + /* Pass the username to msim_get_info_cb(), because since we lookup + * by userid, the userinfo message will only contain the uid (not + * the username) but it would be useful to display the username too. + */ + user_msg = msim_msg_new( + "user", MSIM_TYPE_STRING, g_strdup(username), + NULL); + purple_debug_info("msim", "msim_get_info, setting up lookup, user=%s\n", username); + + msim_lookup_user(session, user_to_lookup, msim_get_info_cb, user_msg); + + g_free(user_to_lookup); +} + +/** Set your status - callback for when user manually sets it. */ +void +msim_set_status(PurpleAccount *account, PurpleStatus *status) +{ + PurpleStatusType *type; + MsimSession *session; + guint status_code; + const gchar *statstring; + + session = (MsimSession *)account->gc->proto_data; + + g_return_if_fail(MSIM_SESSION_VALID(session)); + + type = purple_status_get_type(status); + + switch (purple_status_type_get_primitive(type)) { + case PURPLE_STATUS_AVAILABLE: + purple_debug_info("msim", "msim_set_status: available (%d->%d)\n", PURPLE_STATUS_AVAILABLE, + MSIM_STATUS_CODE_ONLINE); + status_code = MSIM_STATUS_CODE_ONLINE; + break; + + case PURPLE_STATUS_INVISIBLE: + purple_debug_info("msim", "msim_set_status: invisible (%d->%d)\n", PURPLE_STATUS_INVISIBLE, + MSIM_STATUS_CODE_OFFLINE_OR_HIDDEN); + status_code = MSIM_STATUS_CODE_OFFLINE_OR_HIDDEN; + break; + + case PURPLE_STATUS_AWAY: + purple_debug_info("msim", "msim_set_status: away (%d->%d)\n", PURPLE_STATUS_AWAY, + MSIM_STATUS_CODE_AWAY); + status_code = MSIM_STATUS_CODE_AWAY; + break; + + default: + purple_debug_info("msim", "msim_set_status: unknown " + "status interpreting as online"); + status_code = MSIM_STATUS_CODE_ONLINE; + break; + } + + statstring = purple_status_get_attr_string(status, "message"); + + if (!statstring) { + statstring = g_strdup(""); + } + + msim_set_status_code(session, status_code, g_strdup(statstring)); +} + +/** Go idle. */ +void +msim_set_idle(PurpleConnection *gc, int time) +{ + MsimSession *session; + + g_return_if_fail(gc != NULL); + + session = (MsimSession *)gc->proto_data; + + g_return_if_fail(MSIM_SESSION_VALID(session)); + + if (time == 0) { + /* Going back from idle. In msim, idle is mutually exclusive + * from the other states (you can only be away or idle, but not + * both, for example), so by going non-idle I go online. + */ + /* TODO: find out how to keep old status string? */ + msim_set_status_code(session, MSIM_STATUS_CODE_ONLINE, g_strdup("")); + } else { + /* msim doesn't support idle time, so just go idle */ + msim_set_status_code(session, MSIM_STATUS_CODE_IDLE, g_strdup("")); + } +} + +/** Set status using an MSIM_STATUS_CODE_* value. + * @param status_code An MSIM_STATUS_CODE_* value. + * @param statstring Status string, must be a dynamic string (will be freed by msim_send). + */ +static void +msim_set_status_code(MsimSession *session, guint status_code, gchar *statstring) +{ + g_return_if_fail(MSIM_SESSION_VALID(session)); + g_return_if_fail(statstring != NULL); + + purple_debug_info("msim", "msim_set_status_code: going to set status to code=%d,str=%s\n", + status_code, statstring); + + if (!msim_send(session, + "status", MSIM_TYPE_INTEGER, status_code, + "sesskey", MSIM_TYPE_INTEGER, session->sesskey, + "statstring", MSIM_TYPE_STRING, statstring, + "locstring", MSIM_TYPE_STRING, g_strdup(""), + NULL)) + { + purple_debug_info("msim", "msim_set_status: failed to set status"); + } + +} + +/** After a uid is resolved to username, tag it with the username and submit for processing. + * + * @param session + * @param userinfo Response messsage to resolving request. + * @param data MsimMessage *, the message to attach information to. + */ +static void +msim_incoming_resolved(MsimSession *session, MsimMessage *userinfo, + gpointer data) +{ + gchar *username; + MsimMessage *msg, *body; + + g_return_if_fail(MSIM_SESSION_VALID(session)); + g_return_if_fail(userinfo != NULL); + + body = msim_msg_get_dictionary(userinfo, "body"); + g_return_if_fail(body != NULL); + + username = msim_msg_get_string(body, "UserName"); + g_return_if_fail(username != NULL); + /* Note: username will be owned by 'msg' below. */ + + msg = (MsimMessage *)data; + g_return_if_fail(msg != NULL); + + /* TODO: more elegant solution than below. attach whole message? */ + /* Special elements name beginning with '_', we'll use internally within the + * program (did not come directly from the wire). */ + msg = msim_msg_append(msg, "_username", MSIM_TYPE_STRING, username); + + /* TODO: attach more useful information, like ImageURL */ + + msim_process(session, msg); + + /* TODO: Free copy cloned from msim_preprocess_incoming(). */ + //XXX msim_msg_free(msg); + msim_msg_free(body); +} + +/* Lookup a username by userid, from buddy list. + * + * @param wanted_uid + * + * @return Username of wanted_uid, if on blist, or NULL. Static string. + * + */ +static const gchar * +msim_uid2username_from_blist(MsimSession *session, guint wanted_uid) +{ + GSList *buddies, *cur; + gchar *ret; + + buddies = purple_find_buddies(session->account, NULL); + + if (!buddies) + { + purple_debug_info("msim", "msim_uid2username_from_blist: no buddies?"); + return NULL; + } + + ret = NULL; + + for (cur = buddies; cur != NULL; cur = g_slist_next(cur)) + { + PurpleBuddy *buddy; + guint uid; + const gchar *name; + + /* See finch/gnthistory.c */ + buddy = cur->data; + + uid = purple_blist_node_get_int(&buddy->node, "UserID"); + name = purple_buddy_get_name(buddy); + + if (uid == wanted_uid) + { + ret = g_strdup(name); + break; + } + } + + g_slist_free(buddies); + return ret; +} + +/** Preprocess incoming messages, resolving as needed, calling msim_process() when ready to process. + * + * @param session + * @param msg MsimMessage *, freed by caller. + */ +static gboolean +msim_preprocess_incoming(MsimSession *session, MsimMessage *msg) +{ + g_return_val_if_fail(MSIM_SESSION_VALID(session), FALSE); + g_return_val_if_fail(msg != NULL, FALSE); + + if (msim_msg_get(msg, "bm") && msim_msg_get(msg, "f")) { + guint uid; + const gchar *username; + + /* 'f' = userid message is from, in buddy messages */ + uid = msim_msg_get_integer(msg, "f"); + + username = msim_uid2username_from_blist(session, uid); + + if (username) { + /* Know username already, use it. */ + purple_debug_info("msim", "msim_preprocess_incoming: tagging with _username=%s\n", + username); + msg = msim_msg_append(msg, "_username", MSIM_TYPE_STRING, g_strdup(username)); + return msim_process(session, msg); + + } else { + gchar *from; + + /* Send lookup request. */ + /* XXX: where is msim_msg_get_string() freed? make _strdup and _nonstrdup. */ + purple_debug_info("msim", "msim_incoming: sending lookup, setting up callback\n"); + from = msim_msg_get_string(msg, "f"); + msim_lookup_user(session, from, msim_incoming_resolved, msim_msg_clone(msg)); + g_free(from); + + /* indeterminate */ + return TRUE; + } + } else { + /* Nothing to resolve - send directly to processing. */ + return msim_process(session, msg); + } +} + +#ifdef MSIM_USE_KEEPALIVE +/** Check if the connection is still alive, based on last communication. */ +static gboolean +msim_check_alive(gpointer data) +{ + MsimSession *session; + time_t delta; + gchar *errmsg; + + session = (MsimSession *)data; + + g_return_val_if_fail(MSIM_SESSION_VALID(session), FALSE); + + delta = time(NULL) - session->last_comm; + //purple_debug_info("msim", "msim_check_alive: delta=%d\n", delta); + if (delta >= MSIM_KEEPALIVE_INTERVAL) { + errmsg = g_strdup_printf(_("Connection to server lost (no data received within %d seconds)"), (int)delta); + + purple_debug_info("msim", "msim_check_alive: %s > interval of %d, presumed dead\n", + errmsg, MSIM_KEEPALIVE_INTERVAL); + purple_connection_error(session->gc, errmsg); + + purple_notify_error(session->gc, NULL, errmsg, NULL); + + g_free(errmsg); + + return FALSE; + } + + return TRUE; +} +#endif + +/** Handle mail reply checks. */ +static void +msim_check_inbox_cb(MsimSession *session, MsimMessage *reply, gpointer data) +{ + MsimMessage *body; + GString *notification; + guint old_inbox_status; + guint i, n; + const gchar *froms[5], *tos[5], *urls[5], *subjects[5]; + + /* Information for each new inbox message type. */ + static struct + { + const gchar *key; + guint bit; + const gchar *url; + const gchar *text; + } message_types[] = { + { "Mail", MSIM_INBOX_MAIL, "http://messaging.myspace.com/index.cfm?fuseaction=mail.inbox", NULL }, + { "BlogComment", MSIM_INBOX_BLOG_COMMENT, "http://blog.myspace.com/index.cfm?fuseaction=blog", NULL }, + { "ProfileComment", MSIM_INBOX_PROFILE_COMMENT, "http://home.myspace.com/index.cfm?fuseaction=user", NULL }, + { "FriendRequest", MSIM_INBOX_FRIEND_REQUEST, "http://messaging.myspace.com/index.cfm?fuseaction=mail.friendRequests", NULL }, + { "PictureComment", MSIM_INBOX_PICTURE_COMMENT, "http://home.myspace.com/index.cfm?fuseaction=user", NULL } + }; + + /* Can't write _()'d strings in array initializers. Workaround. */ + message_types[0].text = _("New mail messages"); + message_types[1].text = _("New blog comments"); + message_types[2].text = _("New profile comments"); + message_types[3].text = _("New friend requests!"); + message_types[4].text = _("New picture comments"); + + g_return_if_fail(reply != NULL); + + msim_msg_dump("msim_check_inbox_cb: reply=%s\n", reply); + + body = msim_msg_get_dictionary(reply, "body"); + g_return_if_fail(body != NULL); + + notification = g_string_new(""); + + old_inbox_status = session->inbox_status; + + n = 0; + + for (i = 0; i < sizeof(message_types) / sizeof(message_types[0]); ++i) { + const gchar *key; + guint bit; + + key = message_types[i].key; + bit = message_types[i].bit; + + if (msim_msg_get(body, key)) { + /* Notify only on when _changes_ from no mail -> has mail + * (edge triggered) */ + if (!(session->inbox_status & bit)) { + purple_debug_info("msim", "msim_check_inbox_cb: got %s, at %d\n", + key ? key : "(NULL)", n); + + subjects[n] = message_types[i].text; + froms[n] = _("MySpace"); + tos[n] = session->username; + /* TODO: append token, web challenge, so automatically logs in. + * Would also need to free strings because they won't be static + */ + urls[n] = message_types[i].url; + + ++n; + } else { + purple_debug_info("msim", + "msim_check_inbox_cb: already notified of %s\n", + key ? key : "(NULL)"); + } + + session->inbox_status |= bit; + } + } + + if (n) { + purple_debug_info("msim", + "msim_check_inbox_cb: notifying of %d\n", n); + + /* TODO: free strings with callback _if_ change to dynamic (w/ token) */ + purple_notify_emails(session->gc, /* handle */ + n, /* count */ + TRUE, /* detailed */ + subjects, froms, tos, urls, + NULL, /* PurpleNotifyCloseCallback cb */ + NULL); /* gpointer user_data */ + + } + + msim_msg_free(body); +} + +/* Send request to check if there is new mail. */ +static gboolean +msim_check_inbox(gpointer data) +{ + MsimSession *session; + + session = (MsimSession *)data; + + purple_debug_info("msim", "msim_check_inbox: checking mail\n"); + g_return_val_if_fail(msim_send(session, + "persist", MSIM_TYPE_INTEGER, 1, + "sesskey", MSIM_TYPE_INTEGER, session->sesskey, + "cmd", MSIM_TYPE_INTEGER, MSIM_CMD_GET, + "dsn", MSIM_TYPE_INTEGER, MG_CHECK_MAIL_DSN, + "lid", MSIM_TYPE_INTEGER, MG_CHECK_MAIL_LID, + "uid", MSIM_TYPE_INTEGER, session->userid, + "rid", MSIM_TYPE_INTEGER, + msim_new_reply_callback(session, msim_check_inbox_cb, NULL), + "body", MSIM_TYPE_STRING, g_strdup(""), + NULL), TRUE); + + /* Always return true, so that we keep checking for mail. */ + return TRUE; +} + +/** Called when the session key arrives. */ +static gboolean +msim_we_are_logged_on(MsimSession *session, MsimMessage *msg) +{ + MsimMessage *body; + + g_return_val_if_fail(MSIM_SESSION_VALID(session), FALSE); + g_return_val_if_fail(msg != NULL, FALSE); + + session->sesskey = msim_msg_get_integer(msg, "sesskey"); + purple_debug_info("msim", "SESSKEY=<%d>\n", session->sesskey); + + /* What is proof? Used to be uid, but now is 52 base64'd bytes... */ + + /* Comes with: proof,profileid,userid,uniquenick -- all same values + * some of the time, but can vary. This is our own user ID. */ + session->userid = msim_msg_get_integer(msg, "userid"); + + /* Save uid to account so this account can be looked up by uid. */ + purple_account_set_int(session->account, "uid", session->userid); + + /* Not sure what profileid is used for. */ + if (msim_msg_get_integer(msg, "profileid") != session->userid) { + msim_unrecognized(session, msg, + "Profile ID didn't match user ID, don't know why"); + } + + /* We now know are our own username, only after we're logged in.. + * which is weird, but happens because you login with your email + * address and not username. Will be freed in msim_session_destroy(). */ + session->username = msim_msg_get_string(msg, "uniquenick"); + + /* If a local alias wasn't set, set it to user's username. */ + if (!session->account->alias || !strlen(session->account->alias)) + session->account->alias = session->username; + + /* The session is now set up, ready to be connected. This emits the + * signedOn signal, so clients can now do anything with msimprpl, and + * we're ready for it (session key, userid, username all setup). */ + purple_connection_update_progress(session->gc, _("Connected"), 3, 4); + purple_connection_set_state(session->gc, PURPLE_CONNECTED); + + + /* Additional post-connect operations */ + + + if (msim_msg_get_integer(msg, "uniquenick") == session->userid) { + purple_debug_info("msim_we_are_logged_on", "TODO: pick username"); + } + + body = msim_msg_new( + "UserID", MSIM_TYPE_INTEGER, session->userid, + NULL); + + /* Request IM info about ourself. */ + msim_send(session, + "persist", MSIM_TYPE_STRING, g_strdup("persist"), + "sesskey", MSIM_TYPE_INTEGER, session->sesskey, + "dsn", MSIM_TYPE_INTEGER, MG_OWN_MYSPACE_INFO_DSN, + "uid", MSIM_TYPE_INTEGER, session->userid, + "lid", MSIM_TYPE_INTEGER, MG_OWN_MYSPACE_INFO_LID, + "rid", MSIM_TYPE_INTEGER, session->next_rid++, + "body", MSIM_TYPE_DICTIONARY, body, + NULL); + + /* Request MySpace info about ourself. */ + msim_send(session, + "persist", MSIM_TYPE_STRING, g_strdup("persist"), + "sesskey", MSIM_TYPE_INTEGER, session->sesskey, + "dsn", MSIM_TYPE_INTEGER, MG_OWN_IM_INFO_DSN, + "uid", MSIM_TYPE_INTEGER, session->userid, + "lid", MSIM_TYPE_INTEGER, MG_OWN_IM_INFO_LID, + "rid", MSIM_TYPE_INTEGER, session->next_rid++, + "body", MSIM_TYPE_STRING, g_strdup(""), + NULL); + + /* TODO: set options (persist cmd=514,dsn=1,lid=10) */ + /* TODO: set blocklist */ + + /* Notify servers of our current status. */ + purple_debug_info("msim", "msim_we_are_logged_on: notifying servers of status\n"); + msim_set_status(session->account, + purple_account_get_active_status(session->account)); + + /* TODO: setinfo */ + /* + body = msim_msg_new( + "TotalFriends", MSIM_TYPE_INTEGER, 666, + NULL); + msim_send(session, + "setinfo", MSIM_TYPE_BOOLEAN, TRUE, + "sesskey", MSIM_TYPE_INTEGER, session->sesskey, + "info", MSIM_TYPE_DICTIONARY, body, + NULL); + */ + + /* Disable due to problems with timeouts. TODO: fix. */ +#ifdef MSIM_USE_KEEPALIVE + purple_timeout_add(MSIM_KEEPALIVE_INTERVAL_CHECK, + (GSourceFunc)msim_check_alive, session); +#endif + + /* Check mail if they want to. */ + if (purple_account_get_check_mail(session->account)) { + purple_timeout_add(MSIM_MAIL_INTERVAL_CHECK, + (GSourceFunc)msim_check_inbox, session); + msim_check_inbox(session); + } + + msim_get_contact_list(session, MSIM_CONTACT_LIST_INITIAL_FRIENDS); + + return TRUE; +} + +/** + * Process a message. + * + * @param session + * @param msg A message from the server, ready for processing (possibly with resolved username information attached). Caller frees. + * + * @return TRUE if successful. FALSE if processing failed. + */ +static gboolean +msim_process(MsimSession *session, MsimMessage *msg) +{ + g_return_val_if_fail(session != NULL, FALSE); + g_return_val_if_fail(msg != NULL, FALSE); + +#ifdef MSIM_DEBUG_MSG + msim_msg_dump("ready to process: %s\n", msg); +#endif + + if (msim_msg_get_integer(msg, "lc") == 1) { + return msim_login_challenge(session, msg); + } else if (msim_msg_get_integer(msg, "lc") == 2) { + return msim_we_are_logged_on(session, msg); + } else if (msim_msg_get(msg, "bm")) { + return msim_incoming_bm(session, msg); + } else if (msim_msg_get(msg, "rid")) { + return msim_process_reply(session, msg); + } else if (msim_msg_get(msg, "error")) { + return msim_error(session, msg); + } else if (msim_msg_get(msg, "ka")) { + return TRUE; + } else { + msim_unrecognized(session, msg, "in msim_process"); + return FALSE; + } +} + +/** Process the initial server information from the server. */ +static gboolean +msim_process_server_info(MsimSession *session, MsimMessage *msg) +{ + MsimMessage *body; + + body = msim_msg_get_dictionary(msg, "body"); + g_return_val_if_fail(body != NULL, FALSE); + + /* Example body: +AdUnitRefreshInterval=10. +AlertPollInterval=360. +AllowChatRoomEmoticonSharing=False. +ChatRoomUserIDs=78744676;163733130;1300326231;123521495;142663391. +CurClientVersion=673. +EnableIMBrowse=True. +EnableIMStuffAvatars=False. +EnableIMStuffZaps=False. +MaxAddAllFriends=100. +MaxContacts=1000. +MinClientVersion=594. +MySpaceIM_ENGLISH=78744676. +MySpaceNowTimer=720. +PersistenceDataTimeout=900. +UseWebChallenge=1. +WebTicketGoHome=False + + Anything useful? TODO: use what is useful, and use it. +*/ + purple_debug_info("msim_process_server_info", + "maximum contacts: %d\n", + msim_msg_get_integer(body, "MaxContacts")); + + session->server_info = body; + /* session->server_info freed in msim_session_destroy */ + + return TRUE; +} + +/** Process a web challenge, used to login to the web site. */ +static gboolean +msim_web_challenge(MsimSession *session, MsimMessage *msg) +{ + /* TODO: web challenge, store token */ + return FALSE; +} + +/** + * Process a persistance message reply from the server. + * + * @param session + * @param msg Message reply from server. + * + * @return TRUE if successful. + * + * msim_lookup_user sets callback for here + */ +static gboolean +msim_process_reply(MsimSession *session, MsimMessage *msg) +{ + MSIM_USER_LOOKUP_CB cb; + gpointer data; + guint rid, cmd, dsn, lid; + + g_return_val_if_fail(MSIM_SESSION_VALID(session), FALSE); + g_return_val_if_fail(msg != NULL, FALSE); + + msim_store_user_info(session, msg, NULL); + + rid = msim_msg_get_integer(msg, "rid"); + cmd = msim_msg_get_integer(msg, "cmd"); + dsn = msim_msg_get_integer(msg, "dsn"); + lid = msim_msg_get_integer(msg, "lid"); + + /* Unsolicited messages */ + if (cmd == (MSIM_CMD_BIT_REPLY | MSIM_CMD_GET)) { + if (dsn == MG_SERVER_INFO_DSN && lid == MG_SERVER_INFO_LID) { + return msim_process_server_info(session, msg); + } else if (dsn == MG_WEB_CHALLENGE_DSN && lid == MG_WEB_CHALLENGE_LID) { + return msim_web_challenge(session, msg); + } + } + + /* If a callback is registered for this userid lookup, call it. */ + cb = g_hash_table_lookup(session->user_lookup_cb, GUINT_TO_POINTER(rid)); + data = g_hash_table_lookup(session->user_lookup_cb_data, GUINT_TO_POINTER(rid)); + + if (cb) { + purple_debug_info("msim", "msim_process_reply: calling callback now\n"); + msim_msg_dump("for msg=%s\n", msg); + /* Clone message, so that the callback 'cb' can use it (needs to free it also). */ + cb(session, msim_msg_clone(msg), data); + g_hash_table_remove(session->user_lookup_cb, GUINT_TO_POINTER(rid)); + g_hash_table_remove(session->user_lookup_cb_data, GUINT_TO_POINTER(rid)); + } else { + purple_debug_info("msim", + "msim_process_reply: no callback for rid %d\n", rid); + } + + return TRUE; +} + +/** + * Handle an error from the server. + * + * @param session + * @param msg The message. + * + * @return TRUE if successfully reported error. + */ +static gboolean +msim_error(MsimSession *session, MsimMessage *msg) +{ + gchar *errmsg, *full_errmsg; + guint err; + + g_return_val_if_fail(MSIM_SESSION_VALID(session), FALSE); + g_return_val_if_fail(msg != NULL, FALSE); + + err = msim_msg_get_integer(msg, "err"); + errmsg = msim_msg_get_string(msg, "errmsg"); + + full_errmsg = g_strdup_printf(_("Protocol error, code %d: %s"), err, + errmsg ? errmsg : "no 'errmsg' given"); + + g_free(errmsg); + + purple_debug_info("msim", "msim_error (sesskey=%d): %s\n", + session->sesskey, full_errmsg); + + purple_notify_error(session->account, g_strdup(_("MySpaceIM Error")), + full_errmsg, NULL); + + /* Destroy session if fatal. */ + if (msim_msg_get(msg, "fatal")) { + purple_debug_info("msim", "fatal error, closing\n"); + purple_connection_error(session->gc, full_errmsg); + } + + return TRUE; +} + +/** + * Process incoming status messages. + * + * @param session + * @param msg Status update message. Caller frees. + * + * @return TRUE if successful. + */ +static gboolean +msim_incoming_status(MsimSession *session, MsimMessage *msg) +{ + PurpleBuddyList *blist; + MsimUser *user; + GList *list; + gchar *status_headline; + gint status_code, purple_status_code; + gchar *username; + + g_return_val_if_fail(MSIM_SESSION_VALID(session), FALSE); + g_return_val_if_fail(msg != NULL, FALSE); + + msim_msg_dump("msim_status msg=%s\n", msg); + + /* Helpfully looked up by msim_incoming_resolve() for us. */ + username = msim_msg_get_string(msg, "_username"); + g_return_val_if_fail(username != NULL, FALSE); + + { + gchar *ss; + + ss = msim_msg_get_string(msg, "msg"); + purple_debug_info("msim", + "msim_status: updating status for <%s> to <%s>\n", + username, ss ? ss : "(NULL)"); + g_free(ss); + } + + /* Example fields: + * |s|0|ss|Offline + * |s|1|ss|:-)|ls||ip|0|p|0 + */ + list = msim_msg_get_list(msg, "msg"); + + status_code = msim_msg_get_integer_from_element(g_list_nth_data(list, MSIM_STATUS_ORDINAL_ONLINE)); + purple_debug_info("msim", "msim_status: %s's status code = %d\n", username, status_code); + status_headline = msim_msg_get_string_from_element(g_list_nth_data(list, MSIM_STATUS_ORDINAL_HEADLINE)); + + blist = purple_get_blist(); + + /* Add buddy if not found */ + user = msim_find_user(session, username); + if (!user) { + PurpleBuddy *buddy; + + purple_debug_info("msim", + "msim_status: making new buddy for %s\n", username); + buddy = purple_buddy_new(session->account, username, NULL); + purple_blist_add_buddy(buddy, NULL, NULL, NULL); + + user = msim_get_user_from_buddy(buddy); + + /* All buddies on list should have 'uid' integer associated with them. */ + purple_blist_node_set_int(&buddy->node, "UserID", msim_msg_get_integer(msg, "f")); + + msim_store_user_info(session, msg, NULL); + } else { + purple_debug_info("msim", "msim_status: found buddy %s\n", username); + } + + /* don't copy; let the MsimUser own the headline, memory-wise */ + user->headline = status_headline; + + /* Set user status */ + switch (status_code) { + case MSIM_STATUS_CODE_OFFLINE_OR_HIDDEN: + purple_status_code = PURPLE_STATUS_OFFLINE; + break; + + case MSIM_STATUS_CODE_ONLINE: + purple_status_code = PURPLE_STATUS_AVAILABLE; + break; + + case MSIM_STATUS_CODE_AWAY: + purple_status_code = PURPLE_STATUS_AWAY; + break; + + case MSIM_STATUS_CODE_IDLE: + /* will be handled below */ + purple_status_code = -1; + break; + + default: + purple_debug_info("msim", "msim_status for %s, unknown status code %d, treating as available\n", + username, status_code); + purple_status_code = PURPLE_STATUS_AVAILABLE; + } + + purple_prpl_got_user_status(session->account, username, purple_primitive_get_id_from_type(purple_status_code), NULL); + + if (status_code == MSIM_STATUS_CODE_IDLE) { + purple_debug_info("msim", "msim_status: got idle: %s\n", username); + purple_prpl_got_user_idle(session->account, username, TRUE, time(NULL)); + } else { + /* All other statuses indicate going back to non-idle. */ + purple_prpl_got_user_idle(session->account, username, FALSE, time(NULL)); + } + +#ifdef MSIM_SEND_CLIENT_VERSION + if (status_code == MSIM_STATUS_CODE_ONLINE) { + /* Secretly whisper to unofficial clients our own version as they come online */ + msim_send_unofficial_client(session, username); + } +#endif + + if (status_code != MSIM_STATUS_CODE_OFFLINE_OR_HIDDEN) { + /* Get information when they come online. + * TODO: periodically refresh? + */ + purple_debug_info("msim_incoming_status", "%s came online, looking up\n", username); + msim_lookup_user(session, username, NULL, NULL); + } + + g_free(username); + msim_msg_list_free(list); + + return TRUE; +} + +/** Add a buddy to user's buddy list. */ +void +msim_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group) +{ + MsimSession *session; + MsimMessage *msg; + /* MsimMessage *msg_persist; */ + MsimMessage *body; + + session = (MsimSession *)gc->proto_data; + purple_debug_info("msim", "msim_add_buddy: want to add %s to %s\n", + buddy->name, (group && group->name) ? group->name : "(no group)"); + + msg = msim_msg_new( + "addbuddy", MSIM_TYPE_BOOLEAN, TRUE, + "sesskey", MSIM_TYPE_INTEGER, session->sesskey, + /* "newprofileid" will be inserted here with uid. */ + "reason", MSIM_TYPE_STRING, g_strdup(""), + NULL); + + if (!msim_postprocess_outgoing(session, msg, buddy->name, "newprofileid", "reason")) { + purple_notify_error(NULL, NULL, _("Failed to add buddy"), _("'addbuddy' command failed.")); + msim_msg_free(msg); + return; + } + msim_msg_free(msg); + + /* TODO: if addbuddy fails ('error' message is returned), delete added buddy from + * buddy list since Purple adds it locally. */ + + body = msim_msg_new( + "ContactID", MSIM_TYPE_STRING, g_strdup("<uid>"), + "GroupName", MSIM_TYPE_STRING, g_strdup(group->name), + "Position", MSIM_TYPE_INTEGER, 1000, + "Visibility", MSIM_TYPE_INTEGER, 1, + "NickName", MSIM_TYPE_STRING, g_strdup(""), + "NameSelect", MSIM_TYPE_INTEGER, 0, + NULL); + + /* TODO: Update blocklist. */ + +#if 0 + msg_persist = msim_msg_new( + "persist", MSIM_TYPE_INTEGER, 1, + "sesskey", MSIM_TYPE_INTEGER, session->sesskey, + "cmd", MSIM_TYPE_INTEGER, MSIM_CMD_BIT_ACTION | MSIM_CMD_PUT, + "dsn", MSIM_TYPE_INTEGER, MC_CONTACT_INFO_DSN, + "lid", MSIM_TYPE_INTEGER, MC_CONTACT_INFO_LID, + /* TODO: Use msim_new_reply_callback to get rid. */ + "rid", MSIM_TYPE_INTEGER, session->next_rid++, + "body", MSIM_TYPE_DICTIONARY, body, + NULL); + + if (!msim_postprocess_outgoing(session, msg_persist, buddy->name, "body", NULL)) + { + purple_notify_error(NULL, NULL, _("Failed to add buddy"), _("persist command failed")); + msim_msg_free(msg_persist); + return; + } + msim_msg_free(msg_persist); +#endif + +} + +/** Perform actual postprocessing on a message, adding userid as specified. + * + * @param msg The message to postprocess. + * @param uid_before Name of field where to insert new field before, or NULL for end. + * @param uid_field_name Name of field to add uid to. + * @param uid The userid to insert. + * + * If the field named by uid_field_name already exists, then its string contents will + * be used for the field, except "<uid>" will be replaced by the userid. + * + * If the field named by uid_field_name does not exist, it will be added before the + * field named by uid_before, as an integer, with the userid. + * + * Does not handle sending, or scheduling userid lookup. For that, see msim_postprocess_outgoing(). + */ +static MsimMessage * +msim_do_postprocessing(MsimMessage *msg, const gchar *uid_before, + const gchar *uid_field_name, guint uid) +{ + msim_msg_dump("msim_do_postprocessing msg: %s\n", msg); + + /* First, check - if the field already exists, replace <uid> within it */ + if (msim_msg_get(msg, uid_field_name)) { + MsimMessageElement *elem; + gchar *fmt_string; + gchar *uid_str, *new_str; + + /* Warning: this is a delicate, but safe, operation */ + + elem = msim_msg_get(msg, uid_field_name); + + /* Get the packed element, flattening it. This allows <uid> to be + * replaced within nested data structures, since the replacement is done + * on the linear, packed data, not on a complicated data structure. + * + * For example, if the field was originally a dictionary or a list, you + * would have to iterate over all the items in it to see what needs to + * be replaced. But by packing it first, the <uid> marker is easily replaced + * just by a string replacement. + */ + fmt_string = msim_msg_pack_element_data(elem); + + uid_str = g_strdup_printf("%d", uid); + new_str = purple_strreplace(fmt_string, "<uid>", uid_str); + g_free(uid_str); + g_free(fmt_string); + + /* Free the old element data */ + msim_msg_free_element_data(elem->data); + + /* Replace it with our new data */ + elem->data = new_str; + elem->type = MSIM_TYPE_RAW; + + } else { + /* Otherwise, insert new field into outgoing message. */ + msg = msim_msg_insert_before(msg, uid_before, uid_field_name, MSIM_TYPE_INTEGER, GUINT_TO_POINTER(uid)); + } + + msim_msg_dump("msim_postprocess_outgoing_cb: postprocessed msg=%s\n", msg); + + return msg; +} + +/** Callback for msim_postprocess_outgoing() to add a userid to a message, and send it (once receiving userid). + * + * @param session + * @param userinfo The user information reply message, containing the user ID + * @param data The message to postprocess and send. + * + * The data message should contain these fields: + * + * _uid_field_name: string, name of field to add with userid from userinfo message + * _uid_before: string, name of field before field to insert, or NULL for end + * + * +*/ +static void +msim_postprocess_outgoing_cb(MsimSession *session, MsimMessage *userinfo, + gpointer data) +{ + gchar *uid_field_name, *uid_before, *username; + guint uid; + MsimMessage *msg, *body; + + msg = (MsimMessage *)data; + + msim_msg_dump("msim_postprocess_outgoing_cb() got msg=%s\n", msg); + + /* Obtain userid from userinfo message. */ + body = msim_msg_get_dictionary(userinfo, "body"); + g_return_if_fail(body != NULL); + + uid = msim_msg_get_integer(body, "UserID"); + msim_msg_free(body); + + username = msim_msg_get_string(msg, "_username"); + + if (!uid) { + gchar *msg; + + msg = g_strdup_printf(_("No such user: %s"), username); + purple_notify_error(NULL, NULL, _("User lookup"), msg); + g_free(msg); + g_free(username); + //msim_msg_free(msg); + return; + } + + uid_field_name = msim_msg_get_string(msg, "_uid_field_name"); + uid_before = msim_msg_get_string(msg, "_uid_before"); + + msg = msim_do_postprocessing(msg, uid_before, uid_field_name, uid); + + /* Send */ + if (!msim_msg_send(session, msg)) { + msim_msg_dump("msim_postprocess_outgoing_cb: sending failed for message: %s\n", msg); + } + + + /* Free field names AFTER sending message, because MsimMessage does NOT copy + * field names - instead, treats them as static strings (which they usually are). + */ + g_free(uid_field_name); + g_free(uid_before); + g_free(username); + //msim_msg_free(msg); +} + +/** Postprocess and send a message. + * + * @param session + * @param msg Message to postprocess. Will NOT be freed. + * @param username Username to resolve. Assumed to be a static string (will not be freed or copied). + * @param uid_field_name Name of new field to add, containing uid of username. Static string. + * @param uid_before Name of existing field to insert username field before. Static string. + * + * @return TRUE if successful. + */ +gboolean +msim_postprocess_outgoing(MsimSession *session, MsimMessage *msg, + const gchar *username, const gchar *uid_field_name, + const gchar *uid_before) +{ + PurpleBuddy *buddy; + guint uid; + gboolean rc; + + g_return_val_if_fail(msg != NULL, FALSE); + + /* Store information for msim_postprocess_outgoing_cb(). */ + msim_msg_dump("msim_postprocess_outgoing: msg before=%s\n", msg); + msg = msim_msg_append(msg, "_username", MSIM_TYPE_STRING, g_strdup(username)); + msg = msim_msg_append(msg, "_uid_field_name", MSIM_TYPE_STRING, g_strdup(uid_field_name)); + msg = msim_msg_append(msg, "_uid_before", MSIM_TYPE_STRING, g_strdup(uid_before)); + + /* First, try the most obvious. If numeric userid is given, use that directly. */ + if (msim_is_userid(username)) { + uid = atol(username); + } else { + /* Next, see if on buddy list and know uid. */ + buddy = purple_find_buddy(session->account, username); + if (buddy) { + uid = purple_blist_node_get_int(&buddy->node, "UserID"); + } else { + uid = 0; + } + + if (!buddy || !uid) + { + /* Don't have uid offhand - need to ask for it, and wait until hear back before sending. */ + purple_debug_info("msim", ">>> msim_postprocess_outgoing: couldn't find username %s in blist\n", + username ? username : "(NULL)"); + msim_msg_dump("msim_postprocess_outgoing - scheduling lookup, msg=%s\n", msg); + /* TODO: where is cloned message freed? Should be in _cb. */ + msim_lookup_user(session, username, msim_postprocess_outgoing_cb, msim_msg_clone(msg)); + return TRUE; /* not sure of status yet - haven't sent! */ + } + } + + /* Already have uid, postprocess and send msg immediately. */ + purple_debug_info("msim", "msim_postprocess_outgoing: found username %s has uid %d\n", + username ? username : "(NULL)", uid); + + msg = msim_do_postprocessing(msg, uid_before, uid_field_name, uid); + + msim_msg_dump("msim_postprocess_outgoing: msg after (uid immediate)=%s\n", msg); + + rc = msim_msg_send(session, msg); + + //msim_msg_free(msg); + + return rc; +} + +/** Remove a buddy from the user's buddy list. */ +void +msim_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group) +{ + MsimSession *session; + MsimMessage *delbuddy_msg; + MsimMessage *persist_msg; + MsimMessage *blocklist_msg; + GList *blocklist_updates; + + session = (MsimSession *)gc->proto_data; + + delbuddy_msg = msim_msg_new( + "delbuddy", MSIM_TYPE_BOOLEAN, TRUE, + "sesskey", MSIM_TYPE_INTEGER, session->sesskey, + /* 'delprofileid' with uid will be inserted here. */ + NULL); + + if (!msim_postprocess_outgoing(session, delbuddy_msg, buddy->name, "delprofileid", NULL)) { + purple_notify_error(NULL, NULL, _("Failed to remove buddy"), _("'delbuddy' command failed")); + msim_msg_free(delbuddy_msg); + return; + } + msim_msg_free(delbuddy_msg); + + persist_msg = msim_msg_new( + "persist", MSIM_TYPE_INTEGER, 1, + "sesskey", MSIM_TYPE_INTEGER, session->sesskey, + "cmd", MSIM_TYPE_INTEGER, MSIM_CMD_BIT_ACTION | MSIM_CMD_DELETE, + "dsn", MSIM_TYPE_INTEGER, MD_DELETE_BUDDY_DSN, + "lid", MSIM_TYPE_INTEGER, MD_DELETE_BUDDY_LID, + "uid", MSIM_TYPE_INTEGER, session->userid, + "rid", MSIM_TYPE_INTEGER, session->next_rid++, + /* <uid> will be replaced by postprocessing */ + "body", MSIM_TYPE_STRING, g_strdup("ContactID=<uid>"), + NULL); + + if (!msim_postprocess_outgoing(session, persist_msg, buddy->name, "body", NULL)) { + purple_notify_error(NULL, NULL, _("Failed to remove buddy"), _("persist command failed")); + msim_msg_free(persist_msg); + return; + } + msim_msg_free(persist_msg); + + blocklist_updates = NULL; + blocklist_updates = g_list_prepend(blocklist_updates, "a-"); + blocklist_updates = g_list_prepend(blocklist_updates, "<uid>"); + blocklist_updates = g_list_prepend(blocklist_updates, "b-"); + blocklist_updates = g_list_prepend(blocklist_updates, "<uid>"); + blocklist_updates = g_list_reverse(blocklist_updates); + + blocklist_msg = msim_msg_new( + "blocklist", MSIM_TYPE_BOOLEAN, TRUE, + "sesskey", MSIM_TYPE_INTEGER, session->sesskey, + /* TODO: MsimMessage lists. Currently <uid> isn't replaced in lists. */ + //"idlist", MSIM_TYPE_STRING, g_strdup("a-|<uid>|b-|<uid>"), + "idlist", MSIM_TYPE_LIST, blocklist_updates, + NULL); + + if (!msim_postprocess_outgoing(session, blocklist_msg, buddy->name, "idlist", NULL)) { + purple_notify_error(NULL, NULL, _("Failed to remove buddy"), _("blocklist command failed")); + msim_msg_free(blocklist_msg); + return; + } + msim_msg_free(blocklist_msg); +} + +/** Return whether the buddy can be messaged while offline. + * + * The protocol supports offline messages in just the same way as online + * messages. + */ +gboolean +msim_offline_message(const PurpleBuddy *buddy) +{ + return TRUE; +} + +/** + * Callback when input available. + * + * @param gc_uncasted A PurpleConnection pointer. + * @param source File descriptor. + * @param cond PURPLE_INPUT_READ + * + * Reads the input, and calls msim_preprocess_incoming() to handle it. + */ +static void +msim_input_cb(gpointer gc_uncasted, gint source, PurpleInputCondition cond) +{ + PurpleConnection *gc; + PurpleAccount *account; + MsimSession *session; + gchar *end; + int n; + + g_return_if_fail(gc_uncasted != NULL); + g_return_if_fail(source >= 0); /* Note: 0 is a valid fd */ + + gc = (PurpleConnection *)(gc_uncasted); + account = purple_connection_get_account(gc); + session = gc->proto_data; + + /* libpurple/eventloop.h only defines these two */ + if (cond != PURPLE_INPUT_READ && cond != PURPLE_INPUT_WRITE) { + purple_debug_info("msim_input_cb", "unknown condition=%d\n", cond); + purple_connection_error(gc, _("Invalid input condition")); + return; + } + + g_return_if_fail(cond == PURPLE_INPUT_READ); + g_return_if_fail(MSIM_SESSION_VALID(session)); + + /* Mark down that we got data, so don't timeout. */ + session->last_comm = time(NULL); + + /* Only can handle so much data at once... + * If this happens, try recompiling with a higher MSIM_READ_BUF_SIZE. + * Should be large enough to hold the largest protocol message. + */ + if (session->rxoff >= MSIM_READ_BUF_SIZE) { + purple_debug_error("msim", + "msim_input_cb: %d-byte read buffer full! rxoff=%d\n", + MSIM_READ_BUF_SIZE, session->rxoff); + purple_connection_error(gc, _("Read buffer full")); + return; + } + + purple_debug_info("msim", "buffer at %d (max %d), reading up to %d\n", + session->rxoff, MSIM_READ_BUF_SIZE, + MSIM_READ_BUF_SIZE - session->rxoff); + + /* Read into buffer. On Win32, need recv() not read(). session->fd also holds + * the file descriptor, but it sometimes differs from the 'source' parameter. + */ + n = recv(session->fd, session->rxbuf + session->rxoff, MSIM_READ_BUF_SIZE - session->rxoff, 0); + + if (n < 0 && errno == EAGAIN) { + return; + } else if (n < 0) { + purple_debug_error("msim", "msim_input_cb: read error, ret=%d, " + "error=%s, source=%d, fd=%d (%X))\n", + n, strerror(errno), source, session->fd, session->fd); + purple_connection_error(gc, _("Read error")); + return; + } else if (n == 0) { + purple_debug_info("msim", "msim_input_cb: server disconnected\n"); + purple_connection_error(gc, _("Server has disconnected")); + return; + } + + if (n + session->rxoff >= MSIM_READ_BUF_SIZE) { + purple_debug_info("msim_input_cb", "received %d bytes, pushing rxoff to %d, over buffer size of %d\n", + n, n + session->rxoff, MSIM_READ_BUF_SIZE); + /* TODO: g_realloc like msn, yahoo, irc, jabber? */ + purple_connection_error(gc, _("Read buffer full")); + } + + /* Null terminate */ + purple_debug_info("msim", "msim_input_cb: going to null terminate " + "at n=%d\n", n); + session->rxbuf[session->rxoff + n] = 0; + +#ifdef MSIM_CHECK_EMBEDDED_NULLS + /* Check for embedded NULs. I don't handle them, and they shouldn't occur. */ + if (strlen(session->rxbuf + session->rxoff) != n) { + /* Occurs after login, but it is not a null byte. */ + purple_debug_info("msim", "msim_input_cb: strlen=%d, but read %d bytes" + "--null byte encountered?\n", + strlen(session->rxbuf + session->rxoff), n); + //purple_connection_error(gc, "Invalid message - null byte on input"); + return; + } +#endif + + session->rxoff += n; + purple_debug_info("msim", "msim_input_cb: read=%d\n", n); + +#ifdef MSIM_DEBUG_RXBUF + purple_debug_info("msim", "buf=<%s>\n", session->rxbuf); +#endif + + /* Look for \\final\\ end markers. If found, process message. */ + while((end = strstr(session->rxbuf, MSIM_FINAL_STRING))) { + MsimMessage *msg; + +#ifdef MSIM_DEBUG_RXBUF + purple_debug_info("msim", "in loop: buf=<%s>\n", session->rxbuf); +#endif + *end = 0; + msg = msim_parse(g_strdup(session->rxbuf)); + if (!msg) { + purple_debug_info("msim", "msim_input_cb: couldn't parse rxbuf\n"); + purple_connection_error(gc, _("Unparseable message")); + } else { + /* Process message and then free it (processing function should + * clone message if it wants to keep it afterwards.) */ + if (!msim_preprocess_incoming(session, msg)) { + msim_msg_dump("msim_input_cb: preprocessing message failed on msg: %s\n", msg); + } + msim_msg_free(msg); + } + + /* Move remaining part of buffer to beginning. */ + session->rxoff -= strlen(session->rxbuf) + strlen(MSIM_FINAL_STRING); + memmove(session->rxbuf, end + strlen(MSIM_FINAL_STRING), + MSIM_READ_BUF_SIZE - (end + strlen(MSIM_FINAL_STRING) - session->rxbuf)); + + /* Clear end of buffer */ + //memset(end, 0, MSIM_READ_BUF_SIZE - (end - session->rxbuf)); + } +} + +/* Setup a callback, to be called when a reply is received with the returned rid. + * + * @param cb The callback, an MSIM_USER_LOOKUP_CB. + * @param data Arbitrary user data to be passed to callback (probably an MsimMessage *). + * + * @return The request/reply ID, used to link replies with requests, or -1. + * Put the rid in your request, 'rid' field. + * + * TODO: Make more generic and more specific: + * 1) MSIM_USER_LOOKUP_CB - make it for PERSIST_REPLY, not just user lookup + * 2) data - make it an MsimMessage? + */ +guint +msim_new_reply_callback(MsimSession *session, MSIM_USER_LOOKUP_CB cb, + gpointer data) +{ + guint rid; + + g_return_val_if_fail(MSIM_SESSION_VALID(session), -1); + + rid = session->next_rid++; + + g_hash_table_insert(session->user_lookup_cb, GUINT_TO_POINTER(rid), cb); + g_hash_table_insert(session->user_lookup_cb_data, GUINT_TO_POINTER(rid), data); + + return rid; +} + +/** + * Callback when connected. Sets up input handlers. + * + * @param data A PurpleConnection pointer. + * @param source File descriptor. + * @param error_message + */ +static void +msim_connect_cb(gpointer data, gint source, const gchar *error_message) +{ + PurpleConnection *gc; + MsimSession *session; + + g_return_if_fail(data != NULL); + + gc = (PurpleConnection *)data; + session = (MsimSession *)gc->proto_data; + + if (source < 0) { + purple_connection_error(gc, _("Couldn't connect to host")); + purple_connection_error(gc, g_strdup_printf( + _("Couldn't connect to host: %s (%d)"), + error_message ? error_message : "no message given", + source)); + return; + } + + session->fd = source; + + gc->inpa = purple_input_add(source, PURPLE_INPUT_READ, msim_input_cb, gc); +} + + +/** + * Close the connection. + * + * @param gc The connection. + */ +void +msim_close(PurpleConnection *gc) +{ + MsimSession *session; + + if (gc == NULL) { + return; + } + + session = (MsimSession *)gc->proto_data; + if (session == NULL) + return; + + gc->proto_data = NULL; + + if (!MSIM_SESSION_VALID(session)) { + return; + } + + if (session->gc->inpa) { + purple_input_remove(session->gc->inpa); + } + + msim_session_destroy(session); +} + + +/** + * Obtain the status text for a buddy. + * + * @param buddy The buddy to obtain status text for. + * + * @return Status text, or NULL if error. Caller g_free()'s. + * + */ +char * +msim_status_text(PurpleBuddy *buddy) +{ + MsimSession *session; + MsimUser *user; + const gchar *display_name, *headline; + + g_return_val_if_fail(buddy != NULL, NULL); + + user = msim_get_user_from_buddy(buddy); + + session = (MsimSession *)buddy->account->gc->proto_data; + g_return_val_if_fail(MSIM_SESSION_VALID(session), NULL); + + display_name = headline = NULL; + + /* Retrieve display name and/or headline, depending on user preference. */ + if (purple_account_get_bool(session->account, "show_display_name", TRUE)) { + display_name = user->display_name; + } + + if (purple_account_get_bool(session->account, "show_headline", FALSE)) { + headline = user->headline; + } + + /* Return appropriate combination of display name and/or headline, or neither. */ + + if (display_name && headline) { + return g_strconcat(display_name, " ", headline, NULL); + } else if (display_name) { + return g_strdup(display_name); + } else if (headline) { + return g_strdup(headline); + } + + return NULL; +} + +/** + * Obtain the tooltip text for a buddy. + * + * @param buddy Buddy to obtain tooltip text on. + * @param user_info Variable modified to have the tooltip text. + * @param full TRUE if should obtain full tooltip text. + * + */ +void +msim_tooltip_text(PurpleBuddy *buddy, PurpleNotifyUserInfo *user_info, + gboolean full) +{ + MsimUser *user; + + g_return_if_fail(buddy != NULL); + g_return_if_fail(user_info != NULL); + + user = msim_get_user_from_buddy(buddy); + + if (PURPLE_BUDDY_IS_ONLINE(buddy)) { + MsimSession *session; + + session = (MsimSession *)buddy->account->gc->proto_data; + + g_return_if_fail(MSIM_SESSION_VALID(session)); + + /* TODO: if (full), do something different? */ + + /* TODO: request information? have to figure out how to do + * the asynchronous lookup like oscar does (tooltip shows + * 'retrieving...' if not yet available, then changes when it is). + * + * Right now, only show what we have on hand. + */ + + /* Show abbreviated user info. */ + msim_append_user_info(session, user_info, user, FALSE); + } +} + +/** Add contact from server to buddy list, after looking up username. + * Callback from msim_add_contact_from_server(). + * + * @param data An MsimMessage * of the contact information. Will be freed. + */ +static void +msim_add_contact_from_server_cb(MsimSession *session, MsimMessage *user_lookup_info, gpointer data) +{ + MsimMessage *contact_info, *user_lookup_info_body; + PurpleGroup *group; + PurpleBuddy *buddy; + MsimUser *user; + gchar *username, *group_name; + guint uid; + + contact_info = (MsimMessage *)data; + purple_debug_info("msim_add_contact_from_server_cb", "contact_info addr=%X\n", contact_info); + uid = msim_msg_get_integer(contact_info, "ContactID"); + + if (!user_lookup_info) { + username = g_strdup(msim_uid2username_from_blist(session, uid)); + g_return_if_fail(username != NULL); + } else { + user_lookup_info_body = msim_msg_get_dictionary(user_lookup_info, "body"); + username = msim_msg_get_string(user_lookup_info_body, "UserName"); + msim_msg_free(user_lookup_info_body); + g_return_if_fail(username != NULL); + } + + purple_debug_info("msim_add_contact_from_server_cb", + "*** about to add/update username=%s\n", username); + + /* 1. Creates a new group, or gets existing group if it exists (or so + * the documentation claims). */ + group_name = msim_msg_get_string(contact_info, "GroupName"); + if (group_name) { + group = purple_group_new(group_name); + purple_debug_info("msim_add_contact_from_server_cb", + "adding to GroupName: %s\n", group_name); + g_free(group_name); + } else { + group = purple_group_new(_("IM Friends")); + } + + /* 2. Get or create buddy */ + buddy = purple_find_buddy(session->account, username); + if (!buddy) { + purple_debug_info("msim_add_contact_from_server_cb", + "creating new buddy: %s\n", username); + buddy = purple_buddy_new(session->account, username, NULL); + } + + /* Add group to beginning. See #2752. */ + purple_blist_add_group(group, NULL); + + /* TODO: use 'Position' in contact_info to take into account where buddy is */ + purple_blist_add_buddy(buddy, NULL, group, NULL /* insertion point */); + + /* 3. Update buddy information */ + user = msim_get_user_from_buddy(buddy); + + /* All buddies on list should have 'uid' integer associated with them. */ + purple_blist_node_set_int(&buddy->node, "UserID", uid); + + /* Stores a few fields in the MsimUser, relevant to the buddy itself. + * AvatarURL, Headline, ContactID. */ + msim_store_user_info(session, contact_info, NULL); + + /* TODO: other fields, store in 'user' */ + + msim_msg_free(contact_info); +} + +/** Add first ContactID in contact_info to buddy's list. Used to add + * server-side buddies to client-side list. + * + * @return TRUE if added. + * */ +static gboolean +msim_add_contact_from_server(MsimSession *session, MsimMessage *contact_info) +{ + guint uid; + const gchar *username; + + uid = msim_msg_get_integer(contact_info, "ContactID"); + g_return_val_if_fail(uid != 0, FALSE); + + /* Lookup the username, since NickName and IMName is unreliable */ + username = msim_uid2username_from_blist(session, uid); + if (!username) { + gchar *uid_str; + + uid_str = g_strdup_printf("%d", uid); + purple_debug_info("msim_add_contact_from_server", + "contact_info addr=%X\n", contact_info); + msim_lookup_user(session, uid_str, msim_add_contact_from_server_cb, (gpointer)msim_msg_clone(contact_info)); + g_free(uid_str); + } else { + msim_add_contact_from_server_cb(session, NULL, (gpointer)msim_msg_clone(contact_info)); + } + + /* Say that the contact was added, even if we're still looking up + * their username. */ + return TRUE; +} + +/** Called when contact list is received from server. */ +static void +msim_got_contact_list(MsimSession *session, MsimMessage *reply, gpointer user_data) +{ + MsimMessage *body, *body_node; + gchar *msg; + guint buddy_count; + + msim_msg_dump("msim_got_contact_list: reply=%s", reply); + + body = msim_msg_get_dictionary(reply, "body"); + g_return_if_fail(body != NULL); + + buddy_count = 0; + + for (body_node = body; + body_node != NULL; + body_node = msim_msg_get_next_element_node(body_node)) + { + MsimMessageElement *elem; + + elem = (MsimMessageElement *)body_node->data; + + if (g_str_equal(elem->name, "ContactID")) + { + /* Will look for first contact in body_node */ + if (msim_add_contact_from_server(session, body_node)) { + ++buddy_count; + } + } + } + + switch (GPOINTER_TO_UINT(user_data)) { + case MSIM_CONTACT_LIST_IMPORT_ALL_FRIENDS: + msg = g_strdup_printf(_("%d buddies were added or updated"), buddy_count); + purple_notify_info(session->account, _("Add contacts from server"), msg, NULL); + g_free(msg); + break; + + case MSIM_CONTACT_LIST_IMPORT_TOP_FRIENDS: + /* TODO */ + break; + + case MSIM_CONTACT_LIST_INITIAL_FRIENDS: + /* Nothing */ + break; + } + + msim_msg_free(body); +} + +/* Get contact list, calling msim_got_contact_list() with what_to_do_after as user_data gpointer. */ +static gboolean +msim_get_contact_list(MsimSession *session, int what_to_do_after) +{ + return msim_send(session, + "persist", MSIM_TYPE_INTEGER, 1, + "sesskey", MSIM_TYPE_INTEGER, session->sesskey, + "cmd", MSIM_TYPE_INTEGER, MSIM_CMD_GET, + "dsn", MSIM_TYPE_INTEGER, MG_LIST_ALL_CONTACTS_DSN, + "lid", MSIM_TYPE_INTEGER, MG_LIST_ALL_CONTACTS_LID, + "uid", MSIM_TYPE_INTEGER, session->userid, + "rid", MSIM_TYPE_INTEGER, + msim_new_reply_callback(session, msim_got_contact_list, GUINT_TO_POINTER(what_to_do_after)), + "body", MSIM_TYPE_STRING, g_strdup(""), + NULL); +} + + +/** Called when friends have been imported to buddy list on server. */ +static void +msim_import_friends_cb(MsimSession *session, MsimMessage *reply, gpointer user_data) +{ + MsimMessage *body; + gchar *completed; + msim_msg_dump("msim_import_friends_cb=%s", reply); + + /* Check if the friends were imported successfully. */ + body = msim_msg_get_dictionary(reply, "body"); + g_return_if_fail(body != NULL); + completed = msim_msg_get_string(body, "Completed"); + g_return_if_fail(body != NULL); + msim_msg_free(body); + if (!g_str_equal(completed, "True")) + { + purple_debug_info("msim_import_friends_cb", + "failed to import friends: %s", completed); + purple_notify_error(session->account, _("Add friends from MySpace.com"), + _("Importing friends failed"), NULL); + g_free(completed); + return; + } + g_free(completed); + + purple_debug_info("msim_import_friends_cb", + "added friends to server-side buddy list, requesting new contacts from server"); + + msim_get_contact_list(session, MSIM_CONTACT_LIST_IMPORT_ALL_FRIENDS); + + /* TODO: show, X friends have been added */ +} + +/** Import friends from myspace.com. */ +static void msim_import_friends(PurplePluginAction *action) +{ + PurpleConnection *gc; + MsimSession *session; + gchar *group_name; + + gc = (PurpleConnection *)action->context; + session = (MsimSession *)gc->proto_data; + + group_name = "MySpace Friends"; + + g_return_if_fail(msim_send(session, + "persist", MSIM_TYPE_INTEGER, 1, + "sesskey", MSIM_TYPE_INTEGER, session->sesskey, + "cmd", MSIM_TYPE_INTEGER, MSIM_CMD_PUT, + "dsn", MSIM_TYPE_INTEGER, MC_IMPORT_ALL_FRIENDS_DSN, + "lid", MSIM_TYPE_INTEGER, MC_IMPORT_ALL_FRIENDS_LID, + "uid", MSIM_TYPE_INTEGER, session->userid, + "rid", MSIM_TYPE_INTEGER, + msim_new_reply_callback(session, msim_import_friends_cb, NULL), + "body", MSIM_TYPE_STRING, + g_strdup_printf("GroupName=%s", group_name), + NULL)); + + +} + +/** Actions menu for account. */ +GList * +msim_actions(PurplePlugin *plugin, gpointer context) +{ + PurpleConnection *gc; + GList *menu; + PurplePluginAction *act; + + gc = (PurpleConnection *)context; + + menu = NULL; + +#if 0 + /* TODO: find out how */ + act = purple_plugin_action_new(_("Find people..."), msim_); + menu = g_list_append(menu, act); + + act = purple_plugin_action_new(_("Change IM name..."), NULL); + menu = g_list_append(menu, act); +#endif + + act = purple_plugin_action_new(g_strdup_printf("%s", + _("Add friends from MySpace.com")), msim_import_friends); + menu = g_list_append(menu, act); + + return menu; +} + +/** Callbacks called by Purple, to access this plugin. */ +PurplePluginProtocolInfo prpl_info = { + /* options */ + OPT_PROTO_USE_POINTSIZE /* specify font size in sane point size */ + | OPT_PROTO_MAIL_CHECK, + + /* | OPT_PROTO_IM_IMAGE - TODO: direct images. */ + NULL, /* user_splits */ + NULL, /* protocol_options */ + NO_BUDDY_ICONS, /* icon_spec - TODO: eventually should add this */ + msim_list_icon, /* list_icon */ + NULL, /* list_emblems */ + msim_status_text, /* status_text */ + msim_tooltip_text, /* tooltip_text */ + msim_status_types, /* status_types */ + msim_blist_node_menu, /* blist_node_menu */ + NULL, /* chat_info */ + NULL, /* chat_info_defaults */ + msim_login, /* login */ + msim_close, /* close */ + msim_send_im, /* send_im */ + NULL, /* set_info */ + msim_send_typing, /* send_typing */ + msim_get_info, /* get_info */ + msim_set_status, /* set_status */ + msim_set_idle, /* set_idle */ + NULL, /* change_passwd */ + msim_add_buddy, /* add_buddy */ + NULL, /* add_buddies */ + msim_remove_buddy, /* remove_buddy */ + NULL, /* remove_buddies */ + NULL, /* add_permit */ + NULL, /* add_deny */ + NULL, /* rem_permit */ + NULL, /* rem_deny */ + NULL, /* set_permit_deny */ + NULL, /* join_chat */ + NULL, /* reject chat invite */ + NULL, /* get_chat_name */ + NULL, /* chat_invite */ + NULL, /* chat_leave */ + NULL, /* chat_whisper */ + NULL, /* chat_send */ + NULL, /* 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 */ + NULL, /* set_buddy_icon */ + NULL, /* remove_group */ + NULL, /* get_cb_real_name */ + NULL, /* set_chat_topic */ + NULL, /* find_blist_chat */ + NULL, /* roomlist_get_list */ + NULL, /* roomlist_cancel */ + NULL, /* roomlist_expand_category */ + NULL, /* can_receive_file */ + NULL, /* send_file */ + NULL, /* new_xfer */ + msim_offline_message, /* offline_message */ + NULL, /* whiteboard_prpl_ops */ + msim_send_really_raw, /* send_raw */ + NULL, /* roomlist_room_serialize */ +#ifdef MSIM_USE_ATTENTION_API + msim_send_attention, /* send_attention */ + msim_attention_types, /* attention_types */ +#else + NULL, /* _purple_reserved1 */ + NULL, /* _purple_reserved2 */ +#endif + NULL, /* _purple_reserved3 */ + NULL /* _purple_reserved4 */ +}; + + + +/** Based on MSN's plugin info comments. */ +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-myspace", /**< id */ + "MySpaceIM", /**< name */ + MSIM_PRPL_VERSION_STRING, /**< version */ + /** summary */ + "MySpaceIM Protocol Plugin", + /** description */ + "MySpaceIM Protocol Plugin", + "Jeff Connelly <jeff2@soc.pidgin.im>", /**< author */ + "http://developer.pidgin.im/wiki/MySpaceIM/", /**< homepage */ + + msim_load, /**< load */ + NULL, /**< unload */ + NULL, /**< destroy */ + NULL, /**< ui_info */ + &prpl_info, /**< extra_info */ + NULL, /**< prefs_info */ + msim_actions, /**< msim_actions */ + NULL, /**< reserved1 */ + NULL, /**< reserved2 */ + NULL, /**< reserved3 */ + NULL /**< reserved4 */ +}; + + +#ifdef MSIM_SELF_TEST +/** Test functions. + * Used to test or try out the internal workings of msimprpl. If you're reading + * this code for the first time, these functions can be instructive in learning + * how msimprpl is architected. + */ +void +msim_test_all(void) { + guint failures; + + + failures = 0; + failures += msim_test_msg(); + failures += msim_test_escaping(); + + if (failures) { + purple_debug_info("msim", "msim_test_all HAD FAILURES: %d\n", failures); + } else { + purple_debug_info("msim", "msim_test_all - all tests passed!\n"); + } + exit(0); +} + +/** Test MsimMessage for basic functionality. */ +int +msim_test_msg(void) +{ + MsimMessage *msg, *msg_cloned, *msg2; + GList *list; + gchar *packed, *packed_expected, *packed_cloned; + guint failures; + + failures = 0; + + purple_debug_info("msim", "\n\nTesting MsimMessage\n"); + msg = msim_msg_new(NULL); /* Create a new, empty message. */ + + /* Append some new elements. */ + msg = msim_msg_append(msg, "bx", MSIM_TYPE_BINARY, g_string_new_len(g_strdup("XXX"), 3)); + msg = msim_msg_append(msg, "k1", MSIM_TYPE_STRING, g_strdup("v1")); + msg = msim_msg_append(msg, "k1", MSIM_TYPE_INTEGER, GUINT_TO_POINTER(42)); + msg = msim_msg_append(msg, "k1", MSIM_TYPE_STRING, g_strdup("v43")); + msg = msim_msg_append(msg, "k1", MSIM_TYPE_STRING, g_strdup("v52/xxx\\yyy")); + msg = msim_msg_append(msg, "k1", MSIM_TYPE_STRING, g_strdup("v7")); + msim_msg_dump("msg debug str=%s\n", msg); + packed = msim_msg_pack(msg); + + purple_debug_info("msim", "msg packed=%s\n", packed); + + packed_expected = "\\bx\\WFhY\\k1\\v1\\k1\\42\\k1" + "\\v43\\k1\\v52/1xxx/2yyy\\k1\\v7\\final\\"; + + if (!g_str_equal(packed, packed_expected)) { + purple_debug_info("msim", "!!!(%d), msim_msg_pack not what expected: %s != %s\n", + ++failures, packed, packed_expected); + } + + + msg_cloned = msim_msg_clone(msg); + packed_cloned = msim_msg_pack(msg_cloned); + + purple_debug_info("msim", "msg cloned=%s\n", packed_cloned); + if (!g_str_equal(packed, packed_cloned)) { + purple_debug_info("msim", "!!!(%d), msim_msg_pack on cloned message not equal to original: %s != %s\n", + ++failures, packed_cloned, packed); + } + + g_free(packed); + g_free(packed_cloned); + msim_msg_free(msg_cloned); + msim_msg_free(msg); + + /* Try some of the more advanced functionality */ + list = NULL; + + list = g_list_prepend(list, "item3"); + list = g_list_prepend(list, "item2"); + list = g_list_prepend(list, "item1"); + list = g_list_prepend(list, "item0"); + + msg = msim_msg_new(NULL); + msg = msim_msg_append(msg, "string", MSIM_TYPE_STRING, g_strdup("string value")); + msg = msim_msg_append(msg, "raw", MSIM_TYPE_RAW, g_strdup("raw value")); + msg = msim_msg_append(msg, "integer", MSIM_TYPE_INTEGER, GUINT_TO_POINTER(3140)); + msg = msim_msg_append(msg, "boolean", MSIM_TYPE_BOOLEAN, GUINT_TO_POINTER(FALSE)); + msg = msim_msg_append(msg, "list", MSIM_TYPE_LIST, list); + + msim_msg_dump("msg with list=%s\n", msg); + purple_debug_info("msim", "msg with list packed=%s\n", msim_msg_pack(msg)); + + msg2 = msim_msg_new(NULL); + msg2 = msim_msg_append(msg2, "outer", MSIM_TYPE_STRING, g_strdup("outer value")); + msg2 = msim_msg_append(msg2, "body", MSIM_TYPE_DICTIONARY, msg); + msim_msg_dump("msg with dict=%s\n", msg2); /* msg2 now 'owns' msg */ + purple_debug_info("msim", "msg with dict packed=%s\n", msim_msg_pack(msg2)); + + msim_msg_free(msg2); + + return failures; +} + +/** Test protocol-level escaping/unescaping. */ +int +msim_test_escaping(void) +{ + guint failures; + gchar *raw, *escaped, *unescaped, *expected; + + failures = 0; + + purple_debug_info("msim", "\n\nTesting escaping\n"); + + raw = "hello/world\\hello/world"; + + escaped = msim_escape(raw); + purple_debug_info("msim", "msim_test_escaping: raw=%s, escaped=%s\n", raw, escaped); + expected = "hello/1world/2hello/1world"; + if (!g_str_equal(escaped, expected)) { + purple_debug_info("msim", "!!!(%d), msim_escape failed: %s != %s\n", + ++failures, escaped, expected); + } + + + unescaped = msim_unescape(escaped); + g_free(escaped); + purple_debug_info("msim", "msim_test_escaping: unescaped=%s\n", unescaped); + if (!g_str_equal(raw, unescaped)) { + purple_debug_info("msim", "!!!(%d), msim_unescape failed: %s != %s\n", + ++failures, raw, unescaped); + } + + return failures; +} +#endif + +static gboolean +msim_uri_handler(const gchar *proto, const gchar *cmd, GHashTable *params) +{ + PurpleAccount *account; + MsimSession *session; + GList *l; + gchar *uid_str, *cid_str; + guint uid, cid; + + if (g_ascii_strcasecmp(proto, "myim")) + return FALSE; + + /* Parameters are case-insensitive. */ + uid_str = g_hash_table_lookup(params, "uid"); + cid_str = g_hash_table_lookup(params, "cid"); + + uid = uid_str ? atol(uid_str) : 0; + cid = cid_str ? atol(cid_str) : 0; + + /* Need a contact. */ + g_return_val_if_fail(cid != 0, FALSE); + + /* TODO: if auto=true, "Add all the people on this page to my IM List!", on + * http://collect.myspace.com/index.cfm?fuseaction=im.friendslist. Don't need a cid. */ + + /* Convert numeric contact ID back to a string. Needed for looking up. Don't just + * directly use cid directly from parameters, because it might not be numeric. + * It is trivial to change this to allow cID to be a username, but that's not how + * the official MySpaceIM client works, so don't provide that functionality. */ + cid_str = g_strdup_printf("%d", cid); + + + /* Find our account with specified user id, or use first connected account if uid=0. */ + account = NULL; + l = purple_accounts_get_all(); + while (l) { + if (purple_account_is_connected(l->data) && + (uid == 0 || purple_account_get_int(l->data, "uid", 0) == uid)) { + account = l->data; + break; + } + l = l->next; + } + + if (!account) { + purple_notify_error(NULL, _("myim URL handler"), + _("No suitable MySpaceIM account could be found to open this myim URL."), + _("Enable the proper MySpaceIM account and try again.")); + g_free(cid_str); + return FALSE; + } + + session = (MsimSession *)account->gc->proto_data; + g_return_val_if_fail(session != NULL, FALSE); + + /* Lookup userid to username. TODO: push this down, to IM sending/contact + * adding functions. */ + + /* myim:sendIM?uID=USERID&cID=CONTACTID */ + if (!g_ascii_strcasecmp(cmd, "sendIM")) { + msim_lookup_user(session, cid_str, (MSIM_USER_LOOKUP_CB)msim_uri_handler_sendIM_cb, NULL); + g_free(cid_str); + return TRUE; + + /* myim:addContact?uID=USERID&cID=CONTACTID */ + } else if (!g_ascii_strcasecmp(cmd, "addContact")) { + msim_lookup_user(session, cid_str, (MSIM_USER_LOOKUP_CB)msim_uri_handler_addContact_cb, NULL); + g_free(cid_str); + return TRUE; + } + + return FALSE; +} + +/* TODO: move uid->username resolving to IM sending and buddy adding functions, + * so that user can manually add or IM by userid and username automatically + * looked up if possible? */ + +/** Handle a myim:sendIM URI command, after username has been looked up. */ +static void +msim_uri_handler_sendIM_cb(MsimSession *session, MsimMessage *userinfo, gpointer data) +{ + PurpleConversation *conv; + MsimMessage *body; + gchar *username; + + body = msim_msg_get_dictionary(userinfo, "body"); + username = msim_msg_get_string(body, "UserName"); + msim_msg_free(body); + + if (!username) { + guint uid; + + uid = msim_msg_get_integer(userinfo, "UserID"); + g_return_if_fail(uid != 0); + + username = g_strdup_printf("%d", uid); + } + + + conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, username, session->account); + if (!conv) { + purple_debug_info("msim_uri_handler", "creating new conversation for %s\n", username); + conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, session->account, username); + } + + /* Just open the window so the user can send an IM. */ + purple_conversation_present(conv); + + g_free(username); +} + +/** Handle a myim:addContact command, after username has been looked up. */ +static void +msim_uri_handler_addContact_cb(MsimSession *session, MsimMessage *userinfo, gpointer data) +{ + MsimMessage *body; + gchar *username; + + body = msim_msg_get_dictionary(userinfo, "body"); + username = msim_msg_get_string(body, "UserName"); + msim_msg_free(body); + + if (!username) { + guint uid; + + uid = msim_msg_get_integer(userinfo, "UserID"); + g_return_if_fail(uid != 0); + + username = g_strdup_printf("%d", uid); + } + + + purple_blist_request_add_buddy(session->account, username, _("Buddies"), NULL); + + g_free(username); +} + +/** Initialize plugin. */ +void +init_plugin(PurplePlugin *plugin) +{ +#ifdef MSIM_SELF_TEST + msim_test_all(); + exit(0); +#endif /* MSIM_SELF_TEST */ + + PurpleAccountOption *option; + static gboolean initialized = FALSE; + + + /* TODO: default to automatically try different ports. Make the user be + * able to set the first port to try (like LastConnectedPort in Windows client). */ + option = purple_account_option_string_new(_("Connect server"), "server", MSIM_SERVER); + prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + + option = purple_account_option_int_new(_("Connect port"), "port", MSIM_PORT); + prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + +#ifdef MSIM_USER_WANTS_TO_CONFIGURE_STATUS_TEXT + option = purple_account_option_bool_new(_("Show display name in status text"), "show_display_name", TRUE); + prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + + option = purple_account_option_bool_new(_("Show headline in status text"), "show_headline", TRUE); + prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); +#endif + +#ifdef MSIM_USER_WANTS_TO_DISABLE_EMOTICONS + option = purple_account_option_bool_new(_("Send emoticons"), "emoticons", FALSE); + prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); +#endif + +#ifdef MSIM_USER_REALLY_CARES_ABOUT_PRECISE_FONT_SIZES + option = purple_account_option_int_new(_("Screen resolution (dots per inch)"), "dpi", MSIM_DEFAULT_DPI); + prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + + option = purple_account_option_int_new(_("Base font size (points)"), "base_font_size", MSIM_BASE_FONT_POINT_SIZE); + prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); +#endif + + /* Code below only runs once. Based on oscar.c's oscar_init(). */ + if (initialized) + return; + + initialized = TRUE; + + purple_signal_connect(purple_get_core(), "uri-handler", &initialized, + PURPLE_CALLBACK(msim_uri_handler), NULL); +} + +PURPLE_INIT_PLUGIN(myspace, init_plugin, info);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/protocols/myspace/myspace.h Mon Aug 27 21:59:11 2007 +0000 @@ -0,0 +1,238 @@ +/* MySpaceIM Protocol Plugin, header file + * + * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im> + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _MYSPACE_MYSPACE_H +#define _MYSPACE_MYSPACE_H + +/* Other includes */ +#include <string.h> +#include <errno.h>/* for EAGAIN */ +#include <stdarg.h> +#include <math.h> + +#include <glib.h> + +#ifdef _WIN32 +#include "win32dep.h" +#else +/* For recv() and send(); needed to match Win32 */ +#include <sys/types.h> +#include <sys/socket.h> +#endif + +#include "internal.h" + +#include "notify.h" +#include "plugin.h" +#include "accountopt.h" +#include "version.h" +#include "cipher.h" /* for SHA-1 */ +#include "util.h" /* for base64 */ +#include "debug.h" /* for purple_debug_info */ +#include "xmlnode.h" +#include "core.h" + +/* MySpaceIM includes */ +#include "persist.h" +#include "message.h" +#include "session.h" +#include "zap.h" +#include "markup.h" +#include "user.h" + +/* Conditional compilation options */ +/* Send third-party client version? (Recognized by us and Miranda's plugin) */ +/*#define MSIM_SEND_CLIENT_VERSION */ + +/* Debugging options */ +/*#define MSIM_DEBUG_MSG */ +/* Low-level and rarely needed */ +/*#define MSIM_DEBUG_PARSE */ +/*#define MSIM_DEBUG_LOGIN_CHALLENGE*/ +/*#define MSIM_DEBUG_RXBUF */ + +/* Define to cause init_plugin() to run some tests and print + * the results to the Purple debug log, then exit. Useful to + * run with 'pidgin -d' to see the output. Don't define if + * you want to actually use the plugin! */ +/*#define MSIM_SELF_TEST */ + +/* Use the attention API for zaps? */ +/* Can't have until >=2.2.0, since is a new API. */ +#define MSIM_USE_ATTENTION_API + +/* Constants */ + +/* Maximum length of a password that is acceptable. This is the limit + * on the official client (build 679) and on the 'new password' field at + * http://settings.myspace.com/index.cfm?fuseaction=user.changepassword + * (though curiously, not on the 'current password' field). */ + +/* Not defined; instead have the client reject the password, until libpurple + * supports specifying a length limit on the protocol's password. */ +/* #define MSIM_MAX_PASSWORD_LENGTH 10 */ + +/* Build version of MySpaceIM to report to servers (1.0.xxx.0) */ +#define MSIM_CLIENT_VERSION 697 + +/* Language codes from http://www.microsoft.com/globaldev/reference/oslocversion.mspx */ +#define MSIM_LANGUAGE_ID_ENGLISH 1033 +#define MSIM_LANGUAGE_NAME_ENGLISH "ENGLISH" + +/* msimprpl version string of this plugin */ +#define MSIM_PRPL_VERSION_STRING "0.16" + +/* Default server */ +#define MSIM_SERVER "im.myspace.akadns.net" +#define MSIM_PORT 1863 /* TODO: alternate ports and automatic */ + +/* Time between keepalives (seconds) - if no data within this time, is dead. */ +#define MSIM_KEEPALIVE_INTERVAL (3 * 60) + +/* Time to check if alive (milliseconds) */ +#define MSIM_KEEPALIVE_INTERVAL_CHECK (30 * 1000) + +/* Time to check for new mail (milliseconds) */ +#define MSIM_MAIL_INTERVAL_CHECK (60 * 1000) + + +/* Constants */ +#define HASH_SIZE 0x14 /**< Size of SHA-1 hash for login */ +#define NONCE_SIZE 0x20 /**< Half of decoded 'nc' field */ +#define MSIM_READ_BUF_SIZE (15 * 1024) /**< Receive buffer size */ +#define MSIM_FINAL_STRING "\\final\\" /**< Message end marker */ + +/* Messages */ +#define MSIM_BM_INSTANT 1 +#define MSIM_BM_STATUS 100 +#define MSIM_BM_ACTION 121 +#define MSIM_BM_MEDIA 122 +#define MSIM_BM_PROFILE 124 +#define MSIM_BM_UNOFFICIAL_CLIENT 200 + +/* Authentication algorithm for login2 */ +#define MSIM_AUTH_ALGORITHM 196610 + +/* Recognized challenge length */ +#define MSIM_AUTH_CHALLENGE_LENGTH 0x40 + +/* TODO: obtain IPs of network interfaces from user's machine, instead of + * hardcoding these values below (used in msim_compute_login_response). + * This is not immediately + * important because you can still connect and perform basic + * functions of the protocol. There is also a high chance that the addreses + * are RFC1918 private, so the servers couldn't do anything with them + * anyways except make note of that fact. Probably important for any + * kind of direct connection, or file transfer functionality. + */ + +#define MSIM_LOGIN_IP_LIST "\x00\x00\x00\x00\x05\x7f\x00\x00\x01\x00\x00\x00\x00\x0a\x00\x00\x40\xc0\xa8\x58\x01\xc0\xa8\x3c\x01" +#define MSIM_LOGIN_IP_LIST_LEN 25 + +/* Indexes into status string (0|1|2|3|..., but 0 always empty) */ +#define MSIM_STATUS_ORDINAL_EMPTY 0 +#define MSIM_STATUS_ORDINAL_UNKNOWNs 1 +#define MSIM_STATUS_ORDINAL_ONLINE 2 +#define MSIM_STATUS_ORDINAL_UNKNOWNss 3 +#define MSIM_STATUS_ORDINAL_HEADLINE 4 +#define MSIM_STATUS_ORDINAL_UNKNOWNls 5 +#define MSIM_STATUS_ORDINAL_UNKNOWN 6 +#define MSIM_STATUS_ORDINAL_UNKNOWN1 7 +#define MSIM_STATUS_ORDINAL_UNKNOWNp 8 +#define MSIM_STATUS_ORDINAL_UNKNOWN2 9 + +/* Status codes - states a buddy (or you!) can be in. */ +#define MSIM_STATUS_CODE_OFFLINE_OR_HIDDEN 0 +#define MSIM_STATUS_CODE_ONLINE 1 +#define MSIM_STATUS_CODE_IDLE 2 +#define MSIM_STATUS_CODE_AWAY 5 + + +/* Inbox status bitfield values for MsimSession.inbox_status. */ +#define MSIM_INBOX_MAIL (1 << 0) +#define MSIM_INBOX_BLOG_COMMENT (1 << 1) +#define MSIM_INBOX_PROFILE_COMMENT (1 << 2) +#define MSIM_INBOX_FRIEND_REQUEST (1 << 3) +#define MSIM_INBOX_PICTURE_COMMENT (1 << 4) + +/* Codes for msim_got_contact_list(), to tell what to do afterwards. */ +#define MSIM_CONTACT_LIST_INITIAL_FRIENDS 0 +#define MSIM_CONTACT_LIST_IMPORT_ALL_FRIENDS 1 +#define MSIM_CONTACT_LIST_IMPORT_TOP_FRIENDS 2 + +#ifdef MSIM_USE_ATTENTION_API +#define MsimAttentionType PurpleAttentionType +#else +/* Different kinds of attention alerts. Not yet in libpurple, so define + * our own structure here. */ +typedef struct _MsimAttentionType MsimAttentionType; + +/** A type of "attention" message (zap, nudge, buzz, etc. depending on the + * protocol) that can be sent and received. */ +struct _MsimAttentionType { + PurpleStoredImage *icon; + const gchar *description; /**< Shown before sending. */ + const gchar *incoming_description; /**< Shown when sent. */ + const gchar *outgoing_description; /**< Shown when received. */ +}; +#endif + +/* Functions */ +gboolean msim_load(PurplePlugin *plugin); +GList *msim_status_types(PurpleAccount *acct); + +const gchar *msim_list_icon(PurpleAccount *acct, PurpleBuddy *buddy); +gboolean msim_send_raw(MsimSession *session, const gchar *msg); + +void msim_login(PurpleAccount *acct); +int msim_send_im(PurpleConnection *gc, const gchar *who, const gchar *message, PurpleMessageFlags flags); +unsigned int msim_send_typing(PurpleConnection *gc, const gchar *name, PurpleTypingState state); + +void msim_get_info(PurpleConnection *gc, const gchar *name); + +void msim_set_status(PurpleAccount *account, PurpleStatus *status); +void msim_set_idle(PurpleConnection *gc, int time); + +void msim_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group); +void msim_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group); + +gboolean msim_offline_message(const PurpleBuddy *buddy); + +void msim_close(PurpleConnection *gc); + +char *msim_status_text(PurpleBuddy *buddy); +void msim_tooltip_text(PurpleBuddy *buddy, PurpleNotifyUserInfo *user_info, gboolean full); +GList *msim_actions(PurplePlugin *plugin, gpointer context); + +#ifdef MSIM_SELF_TEST +void msim_test_all(void) __attribute__((__noreturn__)); +int msim_test_msg(void); +int msim_test_escaping(void); +#endif + +gboolean msim_send_bm(MsimSession *session, const gchar *who, const gchar *text, int type); + + +void msim_unrecognized(MsimSession *session, MsimMessage *msg, gchar *note); +guint msim_new_reply_callback(MsimSession *session, MSIM_USER_LOOKUP_CB cb, gpointer data); + + +void init_plugin(PurplePlugin *plugin); + +#endif /* !_MYSPACE_MYSPACE_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/protocols/myspace/persist.h Mon Aug 27 21:59:11 2007 +0000 @@ -0,0 +1,90 @@ +/* MySpaceIM Protocol Plugin, persist commands + * + * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im> + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _MYSPACE_PERSIST_H +#define _MYSPACE_PERSIST_H + +/** Command codes */ +#define MSIM_CMD_GET 1 +#define MSIM_CMD_PUT 2 +#define MSIM_CMD_DELETE 3 + +/** Command bit fields */ +#define MSIM_CMD_BIT_CODE 255 /*< Bits specifying command code */ +#define MSIM_CMD_BIT_REPLY 256 /**< 1=reply, 0=request */ +#define MSIM_CMD_BIT_ACTION 512 /**< 1=action, 0=information */ +#define MSIM_CMD_BIT_ERROR 1024 /**< 1=error, 0=normal */ + +/** Macros to read cmd bitfield. */ +#define MSIM_CMD_GET_CODE(x) (x & MSIM_CMD_BIT_CODE) +#define MSIM_CMD_IS_REPLY(x) (x & MSIM_CMD_BIT_REPLY) +#define MSIM_CMD_IS_REQUEST(x) !(x & MSIM_CMD_BIT_REPLY) +#define MSIM_CMD_IS_ACTION(x) (x & MSIM_CMD_BIT_ACTION) +#define MSIM_CMD_IS_INFO(x) !(x & MSIM_CMD_BIT_ACTION) +#define MSIM_CMD_IS_ERROR(x) (x & MSIM_CMD_BIT_ERROR) +#define MSIM_CMD_IS_NORMAL(x) !(x & MSIM_CMD_BIT_ERROR) + +/** Define a set of _DSN and _LID constants for a persistance request. */ +#define MSIM_PERSIST_DSN_LID(name,dsn,lid) \ + static const int name##_DSN = dsn; \ + static const int name##_LID = lid; + +/* Can't do this, errors: + * persist.h:51:3: error: '#' is not followed by a macro parameter + * In file included from myspace.c:37: + * persist.h:56: error: expected ')' before numeric constant + * So instead, I define const ints above. +#define MSIM_PERSIST_DSN_LID(name,dsn,lid) \ + #define name##_DSN dsn \ + #define name##_LID lid +#endif +*/ + +/** Messages to Get information dsn lid */ +MSIM_PERSIST_DSN_LID(MG_LIST_ALL_CONTACTS, 0, 1) +MSIM_PERSIST_DSN_LID(MG_USER_INFO_BY_ID, 0, 2) +MSIM_PERSIST_DSN_LID(MG_OWN_IM_INFO, 1, 4) +MSIM_PERSIST_DSN_LID(MG_IM_INFO_BY_ID, 1, 17) +MSIM_PERSIST_DSN_LID(MG_LIST_ALL_GROUPS, 2, 6) +MSIM_PERSIST_DSN_LID(MG_MYSPACE_INFO_BY_ID, 4, 3) +MSIM_PERSIST_DSN_LID(MG_OWN_MYSPACE_INFO, 4, 5) +MSIM_PERSIST_DSN_LID(MG_MYSPACE_INFO_BY_STRING, 5, 7) +MSIM_PERSIST_DSN_LID(MG_CHECK_MAIL, 7, 18) +MSIM_PERSIST_DSN_LID(MG_WEB_CHALLENGE, 17, 26) +MSIM_PERSIST_DSN_LID(MG_USER_SONG, 21, 28) +MSIM_PERSIST_DSN_LID(MG_SERVER_INFO, 101, 20) + +/** Messages to Change/send information */ +MSIM_PERSIST_DSN_LID(MC_USER_PREFERENCES, 1, 10) +MSIM_PERSIST_DSN_LID(MC_CONTACT_INFO, 0, 9) +MSIM_PERSIST_DSN_LID(MC_IMPORT_ALL_FRIENDS, 14, 21) +MSIM_PERSIST_DSN_LID(MC_INVITE, 16, 25) + +/** Messages to Delete information */ +MSIM_PERSIST_DSN_LID(MD_DELETE_BUDDY, 0, 8) + +/** Error codes */ +#define MERR_PARSE 1 +#define MERR_NOT_LOGGED_IN 2 +#define MERR_ANOTHER_LOGIN 6 +#define MERR_BAD_EMAIL 259 +#define MERR_BAD_PASSWORD 260 +#define MERR_BAD_UID_IN_PERSISTR 4352 + +#endif /* !_MYSPACE_PERSIST_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/protocols/myspace/release.sh Mon Aug 27 21:59:11 2007 +0000 @@ -0,0 +1,48 @@ +#!/bin/bash +# Created:20070618 +# By Jeff Connelly + +# Package a new msimprpl for release. Must be run with bash. + +VERSION=0.16 +make +# Include 'myspace' directory in archive, so it can easily be unextracted +# into ~/pidgin/libpurple/protocols at the correct location. +# (if this command fails, run it manually). +# This convenient command requires bash. +cd ../../.. +tar -cf libpurple/protocols/msimprpl-$VERSION.tar libpurple/protocols/myspace/{CHANGES,ChangeLog,LICENSE,Makefile.*,*.c,*.h,README,release.sh,.deps/*} autogen.sh configure.ac +cd libpurple/protocols/myspace +gzip ../msimprpl-$VERSION.tar + +mv ~/pidgin/config.h ~/pidgin/config.h- +make -f Makefile.mingw +mv ~/pidgin/config.h- ~/pidgin/config.h +cp ~/pidgin/win32-install-dir/plugins/libmyspace.dll . +# Zip is more common with Win32 users. Just include a few files in this archive, +# but (importantly) preserve the install directory structure! +mkdir -p win32-archive/plugins +cp libmyspace.dll win32-archive/plugins +mkdir -p win32-archive/pixmaps/pidgin/protocols/{48,22,16} +cp ~/pidgin/win32-install-dir/pixmaps/pidgin/protocols/48/myspace.png \ + win32-archive/pixmaps/pidgin/protocols/48/ +cp ~/pidgin/win32-install-dir/pixmaps/pidgin/protocols/22/myspace.png \ + win32-archive/pixmaps/pidgin/protocols/22/ +cp ~/pidgin/win32-install-dir/pixmaps/pidgin/protocols/16/myspace.png \ + win32-archive/pixmaps/pidgin/protocols/16/ +mkdir -p win32-archive/pixmaps/pidgin/emotes/default +cp ~/pidgin/win32-install-dir/pixmaps/pidgin/emotes/default/theme \ + win32-archive/pixmaps/pidgin/emotes/default/theme +# Emoticons in MySpaceIM but not Pidgin 2.1.0 +cp ~/pidgin/win32-install-dir/pixmaps/pidgin/emotes/default/{sinister,sidefrown,pirate,mohawk,messed,bulgy-eyes}.png \ + win32-archive/pixmaps/pidgin/emotes/default/ + +# Use DOS line endings and .txt file extension for convenience +u2d < README > win32-archive/msimprpl-README.txt +u2d < LICENSE > win32-archive/msimprpl-LICENSE.txt +u2d < CHANGES > win32-archive/msimprpl-CHANGES.txt +cd win32-archive +zip -r ../../msimprpl-$VERSION-win32.zip * +cd .. +rm -rf win32-archive +ls -l ../msimprpl-$VERSION*
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/protocols/myspace/session.c Mon Aug 27 21:59:11 2007 +0000 @@ -0,0 +1,95 @@ +/* MySpaceIM Protocol Plugin, session + * + * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im> + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "myspace.h" + +/* Session methods */ + +/** + * Create a new MSIM session. + * + * @param acct The account to create the session from. + * + * @return Pointer to a new session. Free with msim_session_destroy. + */ +MsimSession * +msim_session_new(PurpleAccount *acct) +{ + MsimSession *session; + + g_return_val_if_fail(acct != NULL, NULL); + + session = g_new0(MsimSession, 1); + + session->magic = MSIM_SESSION_STRUCT_MAGIC; + session->account = acct; + session->gc = purple_account_get_connection(acct); + session->sesskey = 0; + session->userid = 0; + session->username = NULL; + session->fd = -1; + + /* TODO: Remove. */ + session->user_lookup_cb = g_hash_table_new_full(g_direct_hash, + g_direct_equal, NULL, NULL); /* do NOT free function pointers! (values) */ + session->user_lookup_cb_data = g_hash_table_new_full(g_direct_hash, + g_direct_equal, NULL, NULL);/* TODO: we don't know what the values are, + they could be integers inside gpointers + or strings, so I don't freed them. + Figure this out, once free cache. */ + + /* Created in msim_process_server_info() */ + session->server_info = NULL; + + session->rxoff = 0; + session->rxbuf = g_new0(gchar, MSIM_READ_BUF_SIZE); + session->next_rid = 1; + session->last_comm = time(NULL); + session->inbox_status = 0; + + return session; +} + +/** + * Free a session. + * + * @param session The session to destroy. + */ +void +msim_session_destroy(MsimSession *session) +{ + g_return_if_fail(MSIM_SESSION_VALID(session)); + + session->magic = -1; + + g_free(session->rxbuf); + g_free(session->username); + + /* TODO: Remove. */ + g_hash_table_destroy(session->user_lookup_cb); + g_hash_table_destroy(session->user_lookup_cb_data); + + if (session->server_info) { + msim_msg_free(session->server_info); + } + + g_free(session); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/protocols/myspace/session.h Mon Aug 27 21:59:11 2007 +0000 @@ -0,0 +1,57 @@ +/* MySpaceIM Protocol Plugin, session + * + * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im> + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _MYSPACE_SESSION_H +#define _MYSPACE_SESSION_H + +/* Random number in every MsimSession, to ensure it is valid. */ +#define MSIM_SESSION_STRUCT_MAGIC 0xe4a6752b + +/* Everything needed to keep track of a session (proto_data field in PurpleConnection) */ +typedef struct _MsimSession +{ + guint magic; /**< MSIM_SESSION_STRUCT_MAGIC */ + PurpleAccount *account; + PurpleConnection *gc; + guint sesskey; /**< Session key from server */ + guint userid; /**< This user's numeric user ID */ + gchar *username; /**< This user's unique username */ + gint fd; /**< File descriptor to/from server */ + + /* TODO: Remove. */ + GHashTable *user_lookup_cb; /**< Username -> userid lookup callback */ + GHashTable *user_lookup_cb_data; /**< Username -> userid lookup callback data */ + + MsimMessage *server_info; /**< Parameters from server */ + + gchar *rxbuf; /**< Receive buffer */ + guint rxoff; /**< Receive buffer offset */ + guint next_rid; /**< Next request/response ID */ + time_t last_comm; /**< Time received last communication */ + guint inbox_status; /**< Bit field of inbox notifications */ +} MsimSession; + +/* Check if an MsimSession is valid */ +#define MSIM_SESSION_VALID(s) (session != NULL && session->magic == MSIM_SESSION_STRUCT_MAGIC) + + +MsimSession *msim_session_new(PurpleAccount *acct); +void msim_session_destroy(MsimSession *session); + +#endif /* !_MYSPACE_SESSION_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/protocols/myspace/user.c Mon Aug 27 21:59:11 2007 +0000 @@ -0,0 +1,437 @@ +/* MySpaceIM Protocol Plugin, header file + * + * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im> + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "myspace.h" + +static void msim_store_user_info_each(const gchar *key_str, gchar *value_str, MsimUser *user); +static gchar *msim_format_now_playing(gchar *band, gchar *song); +static void msim_downloaded_buddy_icon(PurpleUtilFetchUrlData *url_data, gpointer user_data, const gchar *url_text, + gsize len, const gchar *error_message); + +/** Format the "now playing" indicator, showing the artist and song. + * @return Return a new string (must be g_free()'d), or NULL. + */ +static gchar * +msim_format_now_playing(gchar *band, gchar *song) +{ + if ((band && strlen(band)) || (song && strlen(song))) { + return g_strdup_printf("%s - %s", + (band && strlen(band)) ? band : "Unknown Artist", + (song && strlen(song)) ? song : "Unknown Song"); + } else { + return NULL; + } +} +/** Get the MsimUser from a PurpleBuddy, creating it if needed. */ +MsimUser * +msim_get_user_from_buddy(PurpleBuddy *buddy) +{ + MsimUser *user; + + if (!buddy) { + return NULL; + } + + if (!buddy->proto_data) { + /* No MsimUser for this buddy; make one. */ + + /* TODO: where is this freed? */ + user = g_new0(MsimUser, 1); + user->buddy = buddy; + buddy->proto_data = (gpointer)user; + } + + user = (MsimUser *)(buddy->proto_data); + + return user; +} + +/** Find and return an MsimUser * representing a user on the buddy list, or NULL. */ +MsimUser * +msim_find_user(MsimSession *session, const gchar *username) +{ + PurpleBuddy *buddy; + MsimUser *user; + + buddy = purple_find_buddy(session->account, username); + if (!buddy) { + return NULL; + } + + user = msim_get_user_from_buddy(buddy); + + return user; +} + +/** Append user information to a PurpleNotifyUserInfo, given an MsimUser. + * Used by msim_tooltip_text() and msim_get_info_cb() to show a user's profile. + */ +void +msim_append_user_info(MsimSession *session, PurpleNotifyUserInfo *user_info, MsimUser *user, gboolean full) +{ + gchar *str; + guint uid; + guint cv; + + /* Useful to identify the account the tooltip refers to. + * Other prpls show this. */ + if (user->username) { + purple_notify_user_info_add_pair(user_info, _("User"), user->username); + } + + uid = purple_blist_node_get_int(&user->buddy->node, "UserID"); + + if (full) { + /* TODO: link to username, if available */ + purple_notify_user_info_add_pair(user_info, _("Profile"), + g_strdup_printf("<a href=\"http://myspace.com/%d\">http://myspace.com/%d</a>", + uid, uid)); + } + + + /* a/s/l...the vitals */ + if (user->age) { + purple_notify_user_info_add_pair(user_info, _("Age"), + g_strdup_printf("%d", user->age)); + } + + if (user->gender && strlen(user->gender)) { + purple_notify_user_info_add_pair(user_info, _("Gender"), user->gender); + } + + if (user->location && strlen(user->location)) { + purple_notify_user_info_add_pair(user_info, _("Location"), user->location); + } + + /* Other information */ + if (user->headline && strlen(user->headline)) { + purple_notify_user_info_add_pair(user_info, _("Headline"), user->headline); + } + + str = msim_format_now_playing(user->band_name, user->song_name); + if (str && strlen(str)) { + purple_notify_user_info_add_pair(user_info, _("Song"), str); + } + + /* Note: total friends only available if looked up by uid, not username. */ + if (user->total_friends) { + purple_notify_user_info_add_pair(user_info, _("Total Friends"), + g_strdup_printf("%d", user->total_friends)); + } + + if (full) { + /* Client information */ + + str = user->client_info; + cv = user->client_cv; + + if (str && cv != 0) { + purple_notify_user_info_add_pair(user_info, _("Client Version"), + g_strdup_printf("%s (build %d)", str, cv)); + } else if (str) { + purple_notify_user_info_add_pair(user_info, _("Client Version"), + g_strdup(str)); + } else if (cv) { + purple_notify_user_info_add_pair(user_info, _("Client Version"), + g_strdup_printf("Build %d", cv)); + } + } +} + +/** Store a field of information about a buddy. */ +void +msim_store_user_info_each(const gchar *key_str, gchar *value_str, MsimUser *user) +{ + if (g_str_equal(key_str, "UserID") || g_str_equal(key_str, "ContactID")) { + /* Save to buddy list, if it exists, for quick cached uid lookup with msim_uid2username_from_blist(). */ + if (user->buddy) + { + purple_debug_info("msim", "associating uid %s with username %s\n", key_str, user->buddy->name); + purple_blist_node_set_int(&user->buddy->node, "UserID", atol(value_str)); + } + /* Need to store in MsimUser, too? What if not on blist? */ + } else if (g_str_equal(key_str, "Age")) { + user->age = atol(value_str); + } else if (g_str_equal(key_str, "Gender")) { + user->gender = g_strdup(value_str); + } else if (g_str_equal(key_str, "Location")) { + user->location = g_strdup(value_str); + } else if (g_str_equal(key_str, "TotalFriends")) { + user->total_friends = atol(value_str); + } else if (g_str_equal(key_str, "DisplayName")) { + user->display_name = g_strdup(value_str); + } else if (g_str_equal(key_str, "BandName")) { + user->band_name = g_strdup(value_str); + } else if (g_str_equal(key_str, "SongName")) { + user->song_name = g_strdup(value_str); + } else if (g_str_equal(key_str, "UserName") || g_str_equal(key_str, "IMName") || g_str_equal(key_str, "NickName")) { + /* Ignore because PurpleBuddy knows this already */ + ; + } else if (g_str_equal(key_str, "ImageURL") || g_str_equal(key_str, "AvatarURL")) { + const gchar *previous_url; + + user->image_url = g_strdup(value_str); + + /* Instead of showing 'no photo' picture, show nothing. */ + if (g_str_equal(user->image_url, "http://x.myspace.com/images/no_pic.gif")) + { + purple_buddy_icons_set_for_user(user->buddy->account, + user->buddy->name, + NULL, 0, NULL); + return; + } + + /* TODO: use ETag for checksum */ + previous_url = purple_buddy_icons_get_checksum_for_user(user->buddy); + + /* Only download if URL changed */ + if (!previous_url || !g_str_equal(previous_url, user->image_url)) { + purple_util_fetch_url(user->image_url, TRUE, NULL, TRUE, msim_downloaded_buddy_icon, (gpointer)user); + } + } else if (g_str_equal(key_str, "LastImageUpdated")) { + /* TODO: use somewhere */ + user->last_image_updated = atol(value_str); + } else if (g_str_equal(key_str, "Headline")) { + user->headline = g_strdup(value_str); + } else { + /* TODO: other fields in MsimUser */ + gchar *msg; + + msg = g_strdup_printf("msim_store_user_info_each: unknown field %s=%s", + key_str, value_str); + + msim_unrecognized(NULL, NULL, msg); + + g_free(msg); + } +} + +/** Save buddy information to the buddy list from a user info reply message. + * + * @param session + * @param msg The user information reply, with any amount of information. + * @param user The structure to save to, or NULL to save in PurpleBuddy->proto_data. + * + * Variable information is saved to the passed MsimUser structure. Permanent + * information (UserID) is stored in the blist node of the buddy list (and + * ends up in blist.xml, persisted to disk) if it exists. + * + * If the function has no buddy information, this function + * is a no-op (and returns FALSE). + * + */ +gboolean +msim_store_user_info(MsimSession *session, MsimMessage *msg, MsimUser *user) +{ + gchar *username; + MsimMessage *body, *body_node; + + g_return_val_if_fail(MSIM_SESSION_VALID(session), FALSE); + g_return_val_if_fail(msg != NULL, FALSE); + + body = msim_msg_get_dictionary(msg, "body"); + if (!body) { + return FALSE; + } + + username = msim_msg_get_string(body, "UserName"); + + if (!username) { + purple_debug_info("msim", + "msim_process_reply: not caching body, no UserName\n"); + msim_msg_free(body); + g_free(username); + return FALSE; + } + + /* Null user = find and store in PurpleBuddy's proto_data */ + if (!user) { + user = msim_find_user(session, username); + if (!user) { + msim_msg_free(body); + g_free(username); + return FALSE; + } + } + + /* TODO: make looping over MsimMessage's easier. */ + for (body_node = body; + body_node != NULL; + body_node = msim_msg_get_next_element_node(body_node)) + { + const gchar *key_str; + gchar *value_str; + MsimMessageElement *elem; + + elem = (MsimMessageElement *)body_node->data; + key_str = elem->name; + + value_str = msim_msg_get_string_from_element(elem); + msim_store_user_info_each(key_str, value_str, user); + g_free(value_str); + } + + if (msim_msg_get_integer(msg, "dsn") == MG_OWN_IM_INFO_DSN && + msim_msg_get_integer(msg, "lid") == MG_OWN_IM_INFO_LID) { + /* TODO: do something with our own IM info, if we need it for some + * specific purpose. Otherwise it is available on the buddy list, + * if the user has themselves as their own buddy. + * + * However, much of the info is already available in MsimSession, + * stored in msim_we_are_logged_on(). */ + } else if (msim_msg_get_integer(msg, "dsn") == MG_OWN_MYSPACE_INFO_DSN && + msim_msg_get_integer(msg, "lid") == MG_OWN_MYSPACE_INFO_LID) { + /* TODO: same as above, but for MySpace info. */ + } + + msim_msg_free(body); + + return TRUE; +} + +/** + * Asynchronously lookup user information, calling callback when receive result. + * + * @param session + * @param user The user id, email address, or username. Not freed. + * @param cb Callback, called with user information when available. + * @param data An arbitray data pointer passed to the callback. + */ +/* TODO: change to not use callbacks */ +void +msim_lookup_user(MsimSession *session, const gchar *user, MSIM_USER_LOOKUP_CB cb, gpointer data) +{ + MsimMessage *body; + gchar *field_name; + guint rid, cmd, dsn, lid; + + g_return_if_fail(MSIM_SESSION_VALID(session)); + g_return_if_fail(user != NULL); + /* Callback can be null to not call anything, just lookup & store information. */ + /*g_return_if_fail(cb != NULL);*/ + + purple_debug_info("msim", "msim_lookup_userid: " + "asynchronously looking up <%s>\n", user); + + msim_msg_dump("msim_lookup_user: data=%s\n", (MsimMessage *)data); + + /* Setup callback. Response will be associated with request using 'rid'. */ + rid = msim_new_reply_callback(session, cb, data); + + /* Send request */ + + cmd = MSIM_CMD_GET; + + if (msim_is_userid(user)) { + field_name = "UserID"; + dsn = MG_MYSPACE_INFO_BY_ID_DSN; + lid = MG_MYSPACE_INFO_BY_ID_LID; + } else if (msim_is_email(user)) { + field_name = "Email"; + dsn = MG_MYSPACE_INFO_BY_STRING_DSN; + lid = MG_MYSPACE_INFO_BY_STRING_LID; + } else { + field_name = "UserName"; + dsn = MG_MYSPACE_INFO_BY_STRING_DSN; + lid = MG_MYSPACE_INFO_BY_STRING_LID; + } + + body = msim_msg_new( + field_name, MSIM_TYPE_STRING, g_strdup(user), + NULL); + + g_return_if_fail(msim_send(session, + "persist", MSIM_TYPE_INTEGER, 1, + "sesskey", MSIM_TYPE_INTEGER, session->sesskey, + "cmd", MSIM_TYPE_INTEGER, 1, + "dsn", MSIM_TYPE_INTEGER, dsn, + "uid", MSIM_TYPE_INTEGER, session->userid, + "lid", MSIM_TYPE_INTEGER, lid, + "rid", MSIM_TYPE_INTEGER, rid, + "body", MSIM_TYPE_DICTIONARY, body, + NULL)); +} + + +/** + * Check if a string is a userid (all numeric). + * + * @param user The user id, email, or name. + * + * @return TRUE if is userid, FALSE if not. + */ +gboolean +msim_is_userid(const gchar *user) +{ + g_return_val_if_fail(user != NULL, FALSE); + + return strspn(user, "0123456789") == strlen(user); +} + +/** + * Check if a string is an email address (contains an @). + * + * @param user The user id, email, or name. + * + * @return TRUE if is an email, FALSE if not. + * + * This function is not intended to be used as a generic + * means of validating email addresses, but to distinguish + * between a user represented by an email address from + * other forms of identification. + */ +gboolean +msim_is_email(const gchar *user) +{ + g_return_val_if_fail(user != NULL, FALSE); + + return strchr(user, '@') != NULL; +} + + +/** Callback for when a buddy icon finished being downloaded. */ +static void +msim_downloaded_buddy_icon(PurpleUtilFetchUrlData *url_data, + gpointer user_data, + const gchar *url_text, + gsize len, + const gchar *error_message) +{ + MsimUser *user; + + user = (MsimUser *)user_data; + + purple_debug_info("msim_downloaded_buddy_icon", + "Downloaded %d bytes\n", len); + + if (!url_text) { + purple_debug_info("msim_downloaded_buddy_icon", + "failed to download icon for %s", + user->buddy->name); + return; + } + + purple_buddy_icons_set_for_user(user->buddy->account, + user->buddy->name, + g_memdup((gchar *)url_text, len), len, + /* Use URL itself as buddy icon "checksum" (TODO: ETag) */ + user->image_url); /* checksum */ +} + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/protocols/myspace/user.h Mon Aug 27 21:59:11 2007 +0000 @@ -0,0 +1,55 @@ +/* MySpaceIM Protocol Plugin, header file + * + * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im> + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _MYSPACE_USER_H +#define _MYSPACE_USER_H + +/* Hold ephemeral information about buddies, for proto_data of PurpleBuddy. */ +/* GHashTable? */ +typedef struct _MsimUser +{ + PurpleBuddy *buddy; + guint client_cv; + gchar *client_info; + guint age; + gchar *gender; + gchar *location; + guint total_friends; + gchar *headline; + gchar *display_name; + /* Note: uid is in &buddy->node (set_blist_node_int), since it never changes */ + gchar *username; + gchar *band_name, *song_name; + gchar *image_url; + guint last_image_updated; +} MsimUser; + +/* Callback function pointer type for when a user's information is received, + * initiated from a user lookup. */ +typedef void (*MSIM_USER_LOOKUP_CB)(MsimSession *session, MsimMessage *userinfo, gpointer data); + +MsimUser *msim_get_user_from_buddy(PurpleBuddy *buddy); +MsimUser *msim_find_user(MsimSession *session, const gchar *username); +void msim_append_user_info(MsimSession *session, PurpleNotifyUserInfo *user_info, MsimUser *user, gboolean full); +gboolean msim_store_user_info(MsimSession *session, MsimMessage *msg, MsimUser *user); +gboolean msim_is_userid(const gchar *user); +gboolean msim_is_email(const gchar *user); +void msim_lookup_user(MsimSession *session, const gchar *user, MSIM_USER_LOOKUP_CB cb, gpointer data); + +#endif /* !_MYSPACE_USER_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/protocols/myspace/zap.c Mon Aug 27 21:59:11 2007 +0000 @@ -0,0 +1,265 @@ +/* MySpaceIM Protocol Plugin - zap support + * + * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im> + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "myspace.h" +#include "zap.h" + +static gboolean msim_send_zap(MsimSession *session, const gchar *username, guint code); +static void msim_send_zap_from_menu(PurpleBlistNode *node, gpointer zap_num_ptr); + + +/** Get zap types. */ +GList * +msim_attention_types(PurpleAccount *acct) +{ + static GList *types = NULL; + MsimAttentionType* attn; + + if (!types) { +#define _MSIM_ADD_NEW_ATTENTION(icn, nme, incoming, outgoing) \ + attn = g_new0(MsimAttentionType, 1); \ + attn->icon_name = icn; \ + attn->name = nme; \ + attn->incoming_description = incoming; \ + attn->outgoing_description = outgoing; \ + types = g_list_append(types, attn); + + /* TODO: icons for each zap */ + _MSIM_ADD_NEW_ATTENTION(NULL, _("zap"), _("zapped"), _("Zapping")); + _MSIM_ADD_NEW_ATTENTION(NULL, _("whack"), _("whacked"), _("Whacking")); + _MSIM_ADD_NEW_ATTENTION(NULL, _("torch"), _("torched"), _("Torching")); + _MSIM_ADD_NEW_ATTENTION(NULL, _("smooch"), _("smooched"), _("Smooching")); + _MSIM_ADD_NEW_ATTENTION(NULL, _("hug"), _("hugged"), _("Hugging")); + _MSIM_ADD_NEW_ATTENTION(NULL, _("bslap"), _("bslapped"), _("Bslapping")); + _MSIM_ADD_NEW_ATTENTION(NULL, _("goose"), _("goosed"), _("Goosing")); + _MSIM_ADD_NEW_ATTENTION(NULL, _("hi-five"), _("hi-fived"), _("Hi-fiving")); + _MSIM_ADD_NEW_ATTENTION(NULL, _("punk"), _("punk'd"), _("Punking")); + _MSIM_ADD_NEW_ATTENTION(NULL, _("raspberry"), _("raspberried"), _("Raspberry'ing")); + } + + return types; +} + +/** Send a zap */ +gboolean +msim_send_attention(PurpleConnection *gc, const gchar *username, guint code) +{ + GList *types; + MsimSession *session; + MsimAttentionType *attn; + PurpleBuddy *buddy; + + session = (MsimSession *)gc->proto_data; + + /* Look for this attention type, by the code index given. */ + types = msim_attention_types(gc->account); + attn = (MsimAttentionType *)g_list_nth_data(types, code); + + if (!attn) { + purple_debug_info("msim_send_attention", "got invalid zap code %d\n", code); + return FALSE; + } + + buddy = purple_find_buddy(session->account, username); + if (!buddy) { + return FALSE; + } + + msim_send_zap(session, username, code); + + return TRUE; +} + +/** Send a zap to a user. */ +static gboolean +msim_send_zap(MsimSession *session, const gchar *username, guint code) +{ + gchar *zap_string; + gboolean rc; +#ifndef MSIM_USE_ATTENTION_API + GList *types; + MsimAttentionType *attn; + gchar *zap_description; +#endif + + g_return_val_if_fail(session != NULL, FALSE); + g_return_val_if_fail(username != NULL, FALSE); + + +#ifdef MSIM_USE_ATTENTION_API + /* serv_send_attention(session->gc, username, code); */ +#else + types = msim_attention_types(session->account); + + attn = g_list_nth_data(types, code); + if (!attn) { + return FALSE; + } + + + zap_description = g_strdup_printf("*** Attention: %s %s ***", attn->outgoing_description, + username); + + serv_got_im(session->gc, username, zap_description, + PURPLE_MESSAGE_SEND | PURPLE_MESSAGE_SYSTEM, time(NULL)); + + g_free(zap_description); +#endif + + /* Construct and send the actual zap command. */ + zap_string = g_strdup_printf("!!!ZAP_SEND!!!=RTE_BTN_ZAPS_%d", code); + + if (!msim_send_bm(session, username, zap_string, MSIM_BM_ACTION)) { + purple_debug_info("msim_send_zap_from_menu", "msim_send_bm failed: zapping %s with %s", + username, zap_string); + rc = FALSE; + } else { + rc = TRUE; + } + + g_free(zap_string); + + return rc; + +} + +/** Zap someone. Callback from msim_blist_node_menu zap menu. */ +static void +msim_send_zap_from_menu(PurpleBlistNode *node, gpointer zap_num_ptr) +{ + PurpleBuddy *buddy; + PurpleAccount *account; + PurpleConnection *gc; + MsimSession *session; + guint zap; + + if (!PURPLE_BLIST_NODE_IS_BUDDY(node)) { + /* Only know about buddies for now. */ + return; + } + + g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); + + buddy = (PurpleBuddy *)node; + + /* Find the session */ + account = buddy->account; + gc = purple_account_get_connection(account); + session = (MsimSession *)gc->proto_data; + + zap = GPOINTER_TO_INT(zap_num_ptr); + +#ifdef MSIM_USE_ATTENTION_API + serv_send_attention(session->gc, buddy->name, zap); +#else + g_return_if_fail(msim_send_zap(session, buddy->name, zap)); +#endif +} + +/** Return menu, if any, for a buddy list node. */ +GList * +msim_blist_node_menu(PurpleBlistNode *node) +{ + GList *menu, *zap_menu; + GList *types; + PurpleMenuAction *act; + /* Warning: hardcoded to match that in msim_attention_types. */ + const gchar *zap_names[10]; + guint i; + + if (!PURPLE_BLIST_NODE_IS_BUDDY(node)) { + /* Only know about buddies for now. */ + return NULL; + } + + /* Names from official client. */ + types = msim_attention_types(NULL); + i = 0; + do + { + MsimAttentionType *attn; + + attn = (MsimAttentionType *)types->data; + zap_names[i] = attn->name; + ++i; + } while ((types = g_list_next(types))); + + menu = zap_menu = NULL; + + /* TODO: get rid of once is accessible directly in GUI */ + for (i = 0; i < sizeof(zap_names) / sizeof(zap_names[0]); ++i) { + act = purple_menu_action_new(zap_names[i], PURPLE_CALLBACK(msim_send_zap_from_menu), + GUINT_TO_POINTER(i), NULL); + zap_menu = g_list_append(zap_menu, act); + } + + act = purple_menu_action_new(_("Zap"), NULL, NULL, zap_menu); + menu = g_list_append(menu, act); + + return menu; +} + +/** Process an incoming zap. */ +gboolean +msim_incoming_zap(MsimSession *session, MsimMessage *msg) +{ + gchar *msg_text, *username; + gint zap; +#ifndef MSIM_USE_ATTENTION_API + const gchar *zap_past_tense[10]; + gchar *zap_text; + + zap_past_tense[0] = _("zapped"); + zap_past_tense[1] = _("whacked"); + zap_past_tense[2] = _("torched"); + zap_past_tense[3] = _("smooched"); + zap_past_tense[4] = _("hugged"); + zap_past_tense[5] = _("bslapped"); + zap_past_tense[6] = _("goosed"); + zap_past_tense[7] = _("hi-fived"); + zap_past_tense[8] = _("punk'd"); + zap_past_tense[9] = _("raspberried"); +#endif + + msg_text = msim_msg_get_string(msg, "msg"); + username = msim_msg_get_string(msg, "_username"); + + g_return_val_if_fail(msg_text != NULL, FALSE); + g_return_val_if_fail(username != NULL, FALSE); + + g_return_val_if_fail(sscanf(msg_text, "!!!ZAP_SEND!!!=RTE_BTN_ZAPS_%d", &zap) == 1, FALSE); + + zap = CLAMP(zap, 0, 9); + +#ifdef MSIM_USE_ATTENTION_API + serv_got_attention(session->gc, username, zap); +#else + zap_text = g_strdup_printf(_("*** You have been %s! ***"), zap_past_tense[zap]); + serv_got_im(session->gc, username, zap_text, + PURPLE_MESSAGE_RECV | PURPLE_MESSAGE_SYSTEM, time(NULL)); + g_free(zap_text); +#endif + + g_free(msg_text); + g_free(username); + + return TRUE; +} + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/protocols/myspace/zap.h Mon Aug 27 21:59:11 2007 +0000 @@ -0,0 +1,28 @@ +/* MySpaceIM Protocol Plugin - zap support + * + * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im> + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _MYSPACE_ZAP_H +#define _MYSPACE_ZAP_H + +GList *msim_attention_types(PurpleAccount *acct); +gboolean msim_send_attention(PurpleConnection *gc, const gchar *username, guint code); +GList *msim_blist_node_menu(PurpleBlistNode *node); +gboolean msim_incoming_zap(MsimSession *session, MsimMessage *msg); + +#endif /* !_MYSPACE_ZAP_H */
--- a/libpurple/protocols/oscar/oscar.c Fri Aug 17 02:26:42 2007 +0000 +++ b/libpurple/protocols/oscar/oscar.c Mon Aug 27 21:59:11 2007 +0000 @@ -3529,6 +3529,7 @@ PurpleConnection *gc; PurpleAccount *account; PurpleStatus *status; + PurplePresence *presence; const char *message, *itmsurl; char *tmp; va_list ap; @@ -3572,7 +3573,8 @@ aim_srv_setextrainfo(od, FALSE, 0, TRUE, tmp, itmsurl); g_free(tmp); - aim_srv_setidle(od, 0); + presence = purple_status_get_presence(status); + aim_srv_setidle(od, purple_presence_is_idle(presence) ? 0 : time(NULL) - purple_presence_get_idle_time(presence)); if (od->icq) { aim_icq_reqofflinemsgs(od);
--- a/libpurple/protocols/qq/sys_msg.c Fri Aug 17 02:26:42 2007 +0000 +++ b/libpurple/protocols/qq/sys_msg.c Mon Aug 27 21:59:11 2007 +0000 @@ -166,7 +166,7 @@ message = g_strdup_printf(_("You have been added by %s"), from); _qq_sys_msg_log_write(gc, message, from); purple_request_action(gc, NULL, message, - _("Would like to add him?"), 2, + _("Would you like to add him?"), 2, purple_connection_get_account(gc), name, NULL, g, 3, _("Cancel"), NULL,
--- a/libpurple/protocols/sametime/sametime.c Fri Aug 17 02:26:42 2007 +0000 +++ b/libpurple/protocols/sametime/sametime.c Mon Aug 27 21:59:11 2007 +0000 @@ -3183,13 +3183,12 @@ PurpleConnection *gc; struct mwPurplePluginData *pd; struct mwAwareIdBlock t = { mwAware_USER, b->name, NULL }; - const char *ret; - - gc = b->account->gc; - pd = gc->proto_data; - - ret = mwServiceAware_getText(pd->srvc_aware, &t); - + const char *ret = NULL; + + if ((gc = purple_account_get_connection(b->account)) + && (pd = gc->proto_data)) + ret = mwServiceAware_getText(pd->srvc_aware, &t); + return (ret && g_utf8_validate(ret, -1, NULL)) ? g_markup_escape_text(ret, -1): NULL; } @@ -3242,17 +3241,17 @@ static void mw_prpl_tooltip_text(PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboolean full) { PurpleConnection *gc; - struct mwPurplePluginData *pd; + struct mwPurplePluginData *pd = NULL; struct mwAwareIdBlock idb = { mwAware_USER, b->name, NULL }; - const char *message; + const char *message = NULL; const char *status; char *tmp; - gc = b->account->gc; - pd = gc->proto_data; - - message = mwServiceAware_getText(pd->srvc_aware, &idb); + if ((gc = purple_account_get_connection(b->account)) + && (pd = gc->proto_data)) + message = mwServiceAware_getText(pd->srvc_aware, &idb); + status = status_text(b); if(message != NULL && g_utf8_validate(message, -1, NULL) && purple_utf8_strcasecmp(status, message)) { @@ -3264,7 +3263,7 @@ purple_notify_user_info_add_pair(user_info, _("Status"), status); } - if(full) { + if(full && pd != NULL) { tmp = user_supports_text(pd->srvc_aware, b->name); if(tmp) { purple_notify_user_info_add_pair(user_info, _("Supports"), tmp);
--- a/libpurple/protocols/yahoo/Makefile.am Fri Aug 17 02:26:42 2007 +0000 +++ b/libpurple/protocols/yahoo/Makefile.am Mon Aug 27 21:59:11 2007 +0000 @@ -10,7 +10,7 @@ yahoochat.h \ yahoochat.c \ yahoo_aliases.c \ - yahoo_alisaes.h \ + yahoo_aliases.h \ yahoo_auth.c \ yahoo_auth.h \ yahoo_crypt.h \
--- a/libpurple/protocols/yahoo/yahoo.c Fri Aug 17 02:26:42 2007 +0000 +++ b/libpurple/protocols/yahoo/yahoo.c Mon Aug 27 21:59:11 2007 +0000 @@ -238,14 +238,18 @@ case 8: /* how many online buddies we have */ break; case 7: /* the current buddy */ - if (name && f) /* update the previous buddy before changing the variables */ - yahoo_update_status(gc, name, f); - name = pair->value; - if (name && g_utf8_validate(name, -1, NULL)) + /* update the previous buddy before changing the variables */ + if (f) { + if (message) + yahoo_friend_set_status_message(f, yahoo_string_decode(gc, message, unicode)); + if (name) + yahoo_update_status(gc, name, f); + } + name = message = NULL; + f = NULL; + if (pair->value && g_utf8_validate(pair->value, -1, NULL)) { + name = pair->value; f = yahoo_friend_find_or_new(gc, name); - else { - f = NULL; - name = NULL; } break; case 10: /* state */ @@ -568,6 +572,11 @@ purple_debug_info("yahoo", "Setting protocol to %d\n", f->protocol); } break; + case 317: /* Stealth Setting */ + if (f && (strtol(pair->value, NULL, 10) == 2)) { + f->presence = YAHOO_PRESENCE_PERM_OFFLINE; + } + break; /* case 242: */ /* this seems related to 241 */ /* break; */ } @@ -768,7 +777,13 @@ if (bud) yahoo_update_status(gc, from, f); } + } else if (!g_ascii_strncasecmp(msg, "WEBCAMINVITE", strlen("WEBCAMINVITE"))) { + PurpleConversation *conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, from, gc->account); + char *buf = g_strdup_printf(_("%s has sent you a webcam invite, which is not yet supported."), from); + purple_conversation_write(conv, NULL, buf, PURPLE_MESSAGE_SYSTEM|PURPLE_MESSAGE_NOTIFY, time(NULL)); + g_free(buf); } + } @@ -884,6 +899,8 @@ PurpleConversation *c; char *username, *str; + str = NULL; + account = purple_connection_get_account(gc); c = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, im->from); @@ -892,10 +909,13 @@ else username = g_markup_escape_text(im->from, -1); +#ifdef YAHOO_USE_ATTENTION_API + serv_got_attention(gc, username, YAHOO_BUZZ); +#else str = g_strdup_printf(_("%s just sent you a Buzz!"), username); purple_conversation_write(c, NULL, str, PURPLE_MESSAGE_SYSTEM|PURPLE_MESSAGE_NOTIFY, im->time); - +#endif g_free(username); g_free(str); g_free(m); @@ -950,11 +970,21 @@ char *id; char *who; char *msg; + int protocol; }; static void yahoo_buddy_add_authorize_cb(gpointer data) { struct yahoo_add_request *add_req = data; + + struct yahoo_packet *pkt; + struct yahoo_data *yd = add_req->gc->proto_data; + + pkt = yahoo_packet_new(YAHOO_SERVICE_AUTH_REQ_15, YAHOO_STATUS_AVAILABLE, 0); + yahoo_packet_hash(pkt, "ssiii", 1, add_req->id, 5, add_req->who, 241, add_req->protocol, + 13, 1, 334, 0); + yahoo_packet_send_and_free(pkt, yd); + g_free(add_req->id); g_free(add_req->who); g_free(add_req->msg); @@ -966,19 +996,20 @@ struct yahoo_packet *pkt; char *encoded_msg = NULL; struct yahoo_data *yd = add_req->gc->proto_data; - - if (msg) + PurpleAccount *account = purple_connection_get_account(add_req->gc); + + if (msg && *msg) encoded_msg = yahoo_string_encode(add_req->gc, msg, NULL); - pkt = yahoo_packet_new(YAHOO_SERVICE_REJECTCONTACT, + pkt = yahoo_packet_new(YAHOO_SERVICE_AUTH_REQ_15, YAHOO_STATUS_AVAILABLE, 0); - yahoo_packet_hash(pkt, "sss", - 1, purple_normalize(add_req->gc->account, - purple_account_get_username( - purple_connection_get_account( - add_req->gc))), - 7, add_req->who, + yahoo_packet_hash(pkt, "ssiiis", + 1, purple_normalize(account, purple_account_get_username(account)), + 5, add_req->who, + 13, 2, + 334, 0, + 97, 1, 14, encoded_msg ? encoded_msg : ""); yahoo_packet_send_and_free(pkt, yd); @@ -1008,6 +1039,132 @@ add_req); } +static void yahoo_buddy_denied_our_add(PurpleConnection *gc, const char *who, const char *reason) +{ + char *notify_msg; + struct yahoo_data *yd = gc->proto_data; + + if (who == NULL) + return; + + if (reason != NULL) { + char *msg2 = yahoo_string_decode(gc, reason, FALSE); + notify_msg = g_strdup_printf(_("%s has (retroactively) denied your request to add them to your list for the following reason: %s."), who, msg2); + g_free(msg2); + } else + notify_msg = g_strdup_printf(_("%s has (retroactively) denied your request to add them to your list."), who); + + purple_notify_info(gc, NULL, _("Add buddy rejected"), notify_msg); + g_free(notify_msg); + + g_hash_table_remove(yd->friends, who); + purple_prpl_got_user_status(purple_connection_get_account(gc), who, "offline", NULL); /* FIXME: make this set not on list status instead */ + /* TODO: Shouldn't we remove the buddy from our local list? */ +} + +static void yahoo_buddy_auth_req_15(PurpleConnection *gc, struct yahoo_packet *pkt) { + GSList *l = pkt->hash; + const char *msg = NULL; + + /* Buddy authorized/declined our addition */ + if (pkt->status == 1) { + const char *who = NULL; + int response = 0; + + while (l) { + struct yahoo_pair *pair = l->data; + + switch (pair->key) { + case 4: + who = pair->value; + break; + case 13: + response = strtol(pair->value, NULL, 10); + break; + case 14: + msg = pair->value; + break; + } + l = l->next; + } + + if (response == 1) /* Authorized */ + purple_debug_info("yahoo", "Received authorization from buddy '%s'.\n", who ? who : "(Unknown Buddy)"); + else if (response == 2) { /* Declined */ + purple_debug_info("yahoo", "Received authorization decline from buddy '%s'.\n", who ? who : "(Unknown Buddy)"); + yahoo_buddy_denied_our_add(gc, who, msg); + } else + purple_debug_error("yahoo", "Received unknown authorization response of %d from buddy '%s'.\n", response, who ? who : "(Unknown Buddy)"); + + } + /* Buddy requested authorization to add us. */ + else if (pkt->status == 3) { + struct yahoo_add_request *add_req; + const char *firstname = NULL, *lastname = NULL; + + add_req = g_new0(struct yahoo_add_request, 1); + add_req->gc = gc; + + while (l) { + struct yahoo_pair *pair = l->data; + + switch (pair->key) { + case 4: + add_req->who = g_strdup(pair->value); + break; + case 5: + add_req->id = g_strdup(pair->value); + break; + case 14: + msg = pair->value; + break; + case 216: + firstname = pair->value; + break; + case 241: + add_req->protocol = strtol(pair->value, NULL, 10); + break; + case 254: + lastname = pair->value; + break; + + } + l = l->next; + } + + if (add_req->id) { + char *alias = NULL; + if (msg) + add_req->msg = yahoo_string_decode(gc, msg, FALSE); + + if (firstname && lastname) + alias = g_strdup_printf("%s %s", firstname, lastname); + else if (firstname) + alias = g_strdup(firstname); + else if (lastname) + alias = g_strdup(lastname); + + + /* DONE! this is almost exactly the same as what MSN does, + * this should probably be moved to the core. + */ + purple_account_request_authorization(purple_connection_get_account(gc), add_req->who, add_req->id, + alias, add_req->msg, purple_find_buddy(purple_connection_get_account(gc),add_req->who) != NULL, + yahoo_buddy_add_authorize_cb, + yahoo_buddy_add_deny_reason_cb, + add_req); + g_free(alias); + } else { + g_free(add_req->id); + g_free(add_req->who); + /*g_free(add_req->msg);*/ + g_free(add_req); + } + } else { + purple_debug_error("yahoo", "Received authorization of unknown status (%d).\n", pkt->status); + } +} + static void yahoo_buddy_added_us(PurpleConnection *gc, struct yahoo_packet *pkt) { struct yahoo_add_request *add_req; char *msg = NULL; @@ -1055,13 +1212,12 @@ } } -static void yahoo_buddy_denied_our_add(PurpleConnection *gc, struct yahoo_packet *pkt) +/* I have no idea if this every gets called in version 15 */ +static void yahoo_buddy_denied_our_add_old(PurpleConnection *gc, struct yahoo_packet *pkt) { char *who = NULL; char *msg = NULL; GSList *l = pkt->hash; - GString *buf = NULL; - struct yahoo_data *yd = gc->proto_data; while (l) { struct yahoo_pair *pair = l->data; @@ -1077,22 +1233,7 @@ l = l->next; } - if (who) { - char *msg2; - buf = g_string_sized_new(0); - if (!msg) { - g_string_printf(buf, _("%s has (retroactively) denied your request to add them to your list."), who); - } else { - msg2 = yahoo_string_decode(gc, msg, FALSE); - g_string_printf(buf, _("%s has (retroactively) denied your request to add them to your list for the following reason: %s."), who, msg2); - g_free(msg2); - } - purple_notify_info(gc, NULL, _("Add buddy rejected"), buf->str); - g_string_free(buf, TRUE); - g_hash_table_remove(yd->friends, who); - purple_prpl_got_user_status(purple_connection_get_account(gc), who, "offline", NULL); /* FIXME: make this set not on list status instead */ - /* TODO: Shouldn't we remove the buddy from our local list? */ - } + yahoo_buddy_denied_our_add(gc, who, msg); } static void yahoo_process_contact(PurpleConnection *gc, struct yahoo_packet *pkt) @@ -1105,7 +1246,7 @@ yahoo_buddy_added_us(gc, pkt); break; case 7: - yahoo_buddy_denied_our_add(gc, pkt); + yahoo_buddy_denied_our_add_old(gc, pkt); break; default: break; @@ -2205,6 +2346,9 @@ case YAHOO_SERVICE_AUTH: yahoo_process_auth(gc, pkt); break; + case YAHOO_SERVICE_AUTH_REQ_15: + yahoo_buddy_auth_req_15(gc, pkt); + break; case YAHOO_SERVICE_ADDBUDDY: yahoo_process_addbuddy(gc, pkt); break; @@ -2785,7 +2929,7 @@ purple_connection_set_display_name(gc, purple_account_get_username(account)); yd->fd = -1; - yd->txhandler = -1; + yd->txhandler = 0; /* TODO: Is there a good grow size for the buffer? */ yd->txbuf = purple_circ_buffer_new(0); yd->friends = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, yahoo_friend_free); @@ -3662,8 +3806,9 @@ struct yahoo_data *yd = (struct yahoo_data *)gc->proto_data; struct yahoo_packet *pkt; PurpleGroup *g; - char *group = NULL; - char *group2 = NULL; + const char *group = NULL; + char *group2; + YahooFriend *f; if (!yd->logged_in) return; @@ -3671,6 +3816,8 @@ if (!yahoo_privacy_check(gc, purple_buddy_get_name(buddy))) return; + f = yahoo_friend_find(gc, purple_buddy_get_name(buddy)); + if (foo) group = foo->name; if (!group) { @@ -3695,6 +3842,8 @@ 301, "319", 303, "319" ); + if (f && f->protocol) + yahoo_packet_hash_int(pkt, 241, f->protocol); yahoo_packet_send_and_free(pkt, yd); g_free(group2); } @@ -3868,17 +4017,24 @@ static PurpleCmdRet yahoopurple_cmd_buzz(PurpleConversation *c, const gchar *cmd, gchar **args, gchar **error, void *data) { - PurpleAccount *account = purple_conversation_get_account(c); +#ifndef YAHOO_USE_ATTENTION_API const char *username = purple_account_get_username(account); +#endif if (*args && args[0]) return PURPLE_CMD_RET_FAILED; +#ifdef YAHOO_USE_ATTENTION_API + serv_send_attention(account->gc, c->name, YAHOO_BUZZ); +#else + purple_debug(PURPLE_DEBUG_INFO, "yahoo", "Sending <ding> on account %s to buddy %s.\n", username, c->name); purple_conv_im_send(PURPLE_CONV_IM(c), "<ding>"); purple_conversation_write(c, NULL, _("You have just sent a Buzz!"), PURPLE_MESSAGE_SYSTEM, time(NULL)); +#endif + return PURPLE_CMD_RET_OK; } @@ -3928,6 +4084,42 @@ { return TRUE; } + +gboolean yahoo_send_attention(PurpleConnection *gc, const char *username, guint type) +{ + PurpleConversation *c; + + c = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, + username, gc->account); + + g_return_val_if_fail(c != NULL, FALSE); + + purple_debug(PURPLE_DEBUG_INFO, "yahoo", + "Sending <ding> on account %s to buddy %s.\n", username, c->name); + /* TODO: find out how to send a <ding> without showing up as a blank line on + * the conversation window. */ + purple_conv_im_send(PURPLE_CONV_IM(c), "<ding>"); + + return TRUE; +} + +GList *yahoo_attention_types(PurpleAccount *account) +{ + PurpleAttentionType *attn; + static GList *list = NULL; + + if (!list) { + /* Yahoo only supports one attention command: the 'buzz'. */ + /* This is index number YAHOO_BUZZ. */ + attn = g_new0(PurpleAttentionType, 1); + attn->name = _("buzz"); + attn->incoming_description = _("buzzed"); + attn->outgoing_description = _("Buzzing"); + list = g_list_append(list, attn); + } + + return list; +} /************************** Plugin Initialization ****************************/ static void @@ -4137,9 +4329,15 @@ NULL, /* send_raw */ NULL, /* roomlist_room_serialize */ - /* padding */ +#ifdef YAHOO_USE_ATTENTION_API + yahoo_send_attention, + yahoo_attention_types, +#else NULL, NULL, +#endif + + /* padding */ NULL, NULL };
--- a/libpurple/protocols/yahoo/yahoo.h Fri Aug 17 02:26:42 2007 +0000 +++ b/libpurple/protocols/yahoo/yahoo.h Mon Aug 27 21:59:11 2007 +0000 @@ -67,6 +67,13 @@ #define YAHOO_STATUS_TYPE_INVISIBLE "invisible" #define YAHOO_STATUS_TYPE_MOBILE "mobile" +#define YAHOO_USE_ATTENTION_API + +#ifdef YAHOO_USE_ATTENTION_API +/* Index into attention types list. */ +#define YAHOO_BUZZ 0 +#endif + enum yahoo_status { YAHOO_STATUS_AVAILABLE = 0, YAHOO_STATUS_BRB, @@ -213,4 +220,7 @@ gboolean yahoo_privacy_check (PurpleConnection *gc, const char *who); +gboolean yahoo_send_attention(PurpleConnection *gc, const char *username, guint type); +GList *yahoo_attention_types(PurpleAccount *account); + #endif /* _YAHOO_H_ */
--- a/libpurple/protocols/yahoo/yahoo_friend.c Fri Aug 17 02:26:42 2007 +0000 +++ b/libpurple/protocols/yahoo/yahoo_friend.c Mon Aug 27 21:59:11 2007 +0000 @@ -196,6 +196,8 @@ struct yahoo_data *yd = gc->proto_data; struct yahoo_packet *pkt = NULL; YahooFriend *f; + const char *thirtyone, *thirteen; + int service = -1; if (!yd->logged_in) return; @@ -211,44 +213,48 @@ } if (presence == YAHOO_PRESENCE_PERM_OFFLINE) { - pkt = yahoo_packet_new(YAHOO_SERVICE_PRESENCE_PERM, - YAHOO_STATUS_AVAILABLE, yd->session_id); - - yahoo_packet_hash(pkt, "ssss", - 1, purple_connection_get_display_name(gc), - 31, "1", 13, "2", 7, name); + service = YAHOO_SERVICE_PRESENCE_PERM; + thirtyone = "1"; + thirteen = "2"; } else if (presence == YAHOO_PRESENCE_DEFAULT) { if (f->presence == YAHOO_PRESENCE_PERM_OFFLINE) { - pkt = yahoo_packet_new(YAHOO_SERVICE_PRESENCE_PERM, - YAHOO_STATUS_AVAILABLE, yd->session_id); - - yahoo_packet_hash(pkt, "ssss", - 1, purple_connection_get_display_name(gc), - 31, "2", 13, "2", 7, name); + service = YAHOO_SERVICE_PRESENCE_PERM; + thirtyone = "2"; + thirteen = "2"; } else if (yd->current_status == YAHOO_STATUS_INVISIBLE) { - pkt = yahoo_packet_new(YAHOO_SERVICE_PRESENCE_SESSION, - YAHOO_STATUS_AVAILABLE, yd->session_id); - yahoo_packet_hash(pkt, "ssss", - 1, purple_connection_get_display_name(gc), - 31, "2", 13, "1", 7, name); + service = YAHOO_SERVICE_PRESENCE_SESSION; + thirtyone = "2"; + thirteen = "1"; } } else if (presence == YAHOO_PRESENCE_ONLINE) { if (f->presence == YAHOO_PRESENCE_PERM_OFFLINE) { pkt = yahoo_packet_new(YAHOO_SERVICE_PRESENCE_PERM, YAHOO_STATUS_AVAILABLE, yd->session_id); - yahoo_packet_hash(pkt, "ssss", + yahoo_packet_hash(pkt, "ssssssss", 1, purple_connection_get_display_name(gc), - 31, "2", 13, "2", 7, name); + 31, "2", 13, "2", + 302, "319", 300, "319", + 7, name, + 301, "319", 303, "319"); yahoo_packet_send_and_free(pkt, yd); } - pkt = yahoo_packet_new(YAHOO_SERVICE_PRESENCE_SESSION, - YAHOO_STATUS_AVAILABLE, yd->session_id); - yahoo_packet_hash(pkt, "ssss", - 1, purple_connection_get_display_name(gc), - 31, "1", 13, "1", 7, name); + service = YAHOO_SERVICE_PRESENCE_SESSION; + thirtyone = "1"; + thirteen = "1"; } - if (pkt) + if (service > 0) { + pkt = yahoo_packet_new(service, + YAHOO_STATUS_AVAILABLE, yd->session_id); + + yahoo_packet_hash(pkt, "ssssssss", + 1, purple_connection_get_display_name(gc), + 31, thirtyone, 13, thirteen, + 302, "319", 300, "319", + 7, name, + 301, "319", 303, "319"); + yahoo_packet_send_and_free(pkt, yd); + } }
--- a/libpurple/protocols/yahoo/yahoo_packet.c Fri Aug 17 02:26:42 2007 +0000 +++ b/libpurple/protocols/yahoo/yahoo_packet.c Mon Aug 27 21:59:11 2007 +0000 @@ -294,7 +294,7 @@ if (writelen == 0) { purple_input_remove(yd->txhandler); - yd->txhandler = -1; + yd->txhandler = 0; return; } @@ -355,7 +355,7 @@ len = yahoo_packet_build(pkt, 0, yd->wm, yd->jp, &data); yahoo_packet_dump(data, len); - if (yd->txhandler == -1) + if (yd->txhandler == 0) ret = write(yd->fd, data, len); else { ret = -1; @@ -371,7 +371,7 @@ } if (ret < len) { - if (yd->txhandler == -1) + if (yd->txhandler == 0) yd->txhandler = purple_input_add(yd->fd, PURPLE_INPUT_WRITE, yahoo_packet_send_can_write, yd); purple_circ_buffer_append(yd->txbuf, data + ret, len - ret);
--- a/libpurple/protocols/yahoo/yahoo_packet.h Fri Aug 17 02:26:42 2007 +0000 +++ b/libpurple/protocols/yahoo/yahoo_packet.h Mon Aug 27 21:59:11 2007 +0000 @@ -98,6 +98,7 @@ YAHOO_SERVICE_AVATAR_UPDATE = 0xc7, YAHOO_SERVICE_VERIFY_ID_EXISTS = 0xc8, YAHOO_SERVICE_AUDIBLE = 0xd0, + YAHOO_SERVICE_AUTH_REQ_15 = 0xd6, YAHOO_SERVICE_CHGRP_15 = 0xe7, YAHOO_SERVICE_STATUS_15 = 0xf0, YAHOO_SERVICE_LIST_15 = 0Xf1,
--- a/libpurple/protocols/yahoo/yahoochat.c Fri Aug 17 02:26:42 2007 +0000 +++ b/libpurple/protocols/yahoo/yahoochat.c Mon Aug 27 21:59:11 2007 +0000 @@ -62,8 +62,9 @@ } pkt = yahoo_packet_new(YAHOO_SERVICE_CHATONLINE, YAHOO_STATUS_AVAILABLE,0); - yahoo_packet_hash(pkt, "sss", 1, purple_connection_get_display_name(gc), - 109, purple_connection_get_display_name(gc), 6, "abcde"); + yahoo_packet_hash(pkt, "ssss", 1, purple_connection_get_display_name(gc), + 109, purple_connection_get_display_name(gc), 6, "abcde", + 135, "ym8.1.0.415"); yahoo_packet_send_and_free(pkt, yd); } @@ -155,7 +156,7 @@ if (members) { g_hash_table_replace(components, g_strdup("members"), g_strdup(members->str)); } - if (!yahoo_privacy_check(gc, who) || + if (!yahoo_privacy_check(gc, who) || (purple_account_get_bool(purple_connection_get_account(gc), "ignore_invites", FALSE))) { purple_debug_info("yahoo", "Invite to conference %s from %s has been dropped.\n", room, who); @@ -640,7 +641,7 @@ GList *w; purple_debug_misc("yahoo", "leaving conference %s\n", room); - + pkt = yahoo_packet_new(YAHOO_SERVICE_CONFLOGOFF, YAHOO_STATUS_AVAILABLE, 0); yahoo_packet_hash_str(pkt, 1, dn); @@ -732,7 +733,7 @@ continue; yahoo_packet_hash(pkt, "ss", 52, name, 53, name); } - + yahoo_packet_send_and_free(pkt, yd); g_free(msg2); }
--- a/libpurple/prpl.h Fri Aug 17 02:26:42 2007 +0000 +++ b/libpurple/prpl.h Mon Aug 27 21:59:11 2007 +0000 @@ -30,6 +30,7 @@ #define _PURPLE_PRPL_H_ typedef struct _PurplePluginProtocolInfo PurplePluginProtocolInfo; +typedef struct _PurpleAttentionType PurpleAttentionType; /**************************************************************************/ /** @name Basic Protocol Information */ @@ -91,6 +92,20 @@ gboolean secret; }; +struct _PurpleAttentionType +{ + const char *name; /**< Shown in GUI elements */ + const char *incoming_description; /**< Shown when sent */ + const char *outgoing_description; /**< Shown when receied */ + const char *icon_name; /**< Icon to display (optional) */ + + /* Reserved fields for future purposes */ + gpointer _reserved1; + gpointer _reserved2; + gpointer _reserved3; + gpointer _reserved4; +}; + /** * Protocol options * @@ -177,10 +192,10 @@ { PurpleProtocolOptions options; /**< Protocol options. */ - GList *user_splits; /* A GList of PurpleAccountUserSplit */ - GList *protocol_options; /* A GList of PurpleAccountOption */ + GList *user_splits; /**< A GList of PurpleAccountUserSplit */ + GList *protocol_options; /**< A GList of PurpleAccountOption */ - PurpleBuddyIconSpec icon_spec; /* The icon spec. */ + PurpleBuddyIconSpec icon_spec; /**< The icon spec. */ /** * Returns the base icon name for the given buddy and account. @@ -268,22 +283,22 @@ int (*chat_send)(PurpleConnection *, int id, const char *message, PurpleMessageFlags flags); void (*keepalive)(PurpleConnection *); - /* new user registration */ + /** new user registration */ void (*register_user)(PurpleAccount *); /* get "chat buddy" info and away message */ void (*get_cb_info)(PurpleConnection *, int, const char *who); void (*get_cb_away)(PurpleConnection *, int, const char *who); - /* save/store buddy's alias on server list/roster */ + /** save/store buddy's alias on server list/roster */ void (*alias_buddy)(PurpleConnection *, const char *who, const char *alias); - /* change a buddy's group on a server list/roster */ + /** change a buddy's group on a server list/roster */ void (*group_buddy)(PurpleConnection *, const char *who, const char *old_group, const char *new_group); - /* rename a group on a server list/roster */ + /** rename a group on a server list/roster */ void (*rename_group)(PurpleConnection *, const char *old_name, PurpleGroup *group, GList *moved_buddies); @@ -291,10 +306,18 @@ void (*convo_closed)(PurpleConnection *, const char *who); - const char *(*normalize)(const PurpleAccount *, const char *); + /** + * Convert the username @a who to its canonical form. (For example, + * AIM treats "fOo BaR" and "foobar" as the same user; this function + * should return the same normalized string for both of those.) + */ + const char *(*normalize)(const PurpleAccount *, const char *who); - /* The prpl does NOT own a reference to img. If it needs one, it - * must purple_imgstore_ref(img) itself. */ + /** + * Set the buddy icon for the given connection to @a img. The prpl + * does NOT own a reference to @a img; if it needs one, it must + * #purple_imgstore_ref(@a img) itself. + */ void (*set_buddy_icon)(PurpleConnection *, PurpleStoredImage *img); void (*remove_group)(PurpleConnection *gc, PurpleGroup *group); @@ -318,7 +341,7 @@ PurpleWhiteboardPrplOps *whiteboard_prpl_ops; - /* For use in plugins that may understand the underlying protocol */ + /** For use in plugins that may understand the underlying protocol */ int (*send_raw)(PurpleConnection *gc, const char *buf, int len); /* room list serialize */ @@ -330,8 +353,10 @@ */ void (*unregister_user)(PurpleAccount *, PurpleAccountUnregistrationCb cb, void *user_data); - void (*_purple_reserved1)(void); - void (*_purple_reserved2)(void); + /* Attention API for sending & receiving zaps/nudges/buzzes etc. */ + gboolean (*send_attention)(PurpleConnection *gc, const char *username, guint type); + GList *(*attention_types)(PurpleAccount *acct); + void (*_purple_reserved3)(void); };
--- a/libpurple/purple-url-handler Fri Aug 17 02:26:42 2007 +0000 +++ b/libpurple/purple-url-handler Mon Aug 27 21:59:11 2007 +0000 @@ -44,6 +44,12 @@ else: return list +def convert(value): + try: + return int(value) + except: + return value + def findaccount(protocolname, accountname=""): # prefer connected accounts account = cpurple.PurpleAccountsFindConnected(accountname, protocolname) @@ -84,6 +90,32 @@ cpurple.PurpleBlistRequestAddBuddy(account, screenname, group, alias) +def aim(uri): + protocol = "prpl-aim" + match = re.match(r"^aim:([^?]*)(\?(.*))", uri) + if not match: + print "Invalid aim URI: %s" % uri + return + + command = urllib.unquote_plus(match.group(1)) + paramstring = match.group(3) + params = {} + if paramstring: + for param in paramstring.split("&"): + key, value = extendlist(param.split("=", 1), 2, "") + params[key] = urllib.unquote_plus(value) + accountname = params.get("account", "") + screenname = params.get("screenname", "") + + account = findaccount(protocol, accountname) + + if command.lower() == "goim": + goim(account, screenname, params.get("message")) + elif command.lower() == "gochat": + gochat(account, params) + elif command.lower() == "addbuddy": + addbuddy(account, screenname, params.get("group", "")) + def gg(uri): protocol = "prpl-gg" match = re.match(r"^gg:(.*)", uri) @@ -95,6 +127,32 @@ account = findaccount(protocol) goim(account, screenname) +def icq(uri): + protocol = "prpl-icq" + match = re.match(r"^icq:([^?]*)(\?(.*))", uri) + if not match: + print "Invalid icq URI: %s" % uri + return + + command = urllib.unquote_plus(match.group(1)) + paramstring = match.group(3) + params = {} + if paramstring: + for param in paramstring.split("&"): + key, value = extendlist(param.split("=", 1), 2, "") + params[key] = urllib.unquote_plus(value) + accountname = params.get("account", "") + screenname = params.get("screenname", "") + + account = findaccount(protocol, accountname) + + if command.lower() == "goim": + goim(account, screenname, params.get("message")) + elif command.lower() == "gochat": + gochat(account, params) + elif command.lower() == "addbuddy": + addbuddy(account, screenname, params.get("group", "")) + def irc(uri): protocol = "prpl-irc" match = re.match(r"^irc:(//([^/]*)/)?([^?]*)(\?(.*))?", uri) @@ -131,6 +189,34 @@ channel = "#" + channel gochat(account, {"server": server, "channel": channel, "password": params.get("key", "")}, params.get("msg")) +def msnim(uri): + protocol = "prpl-msn" + match = re.match(r"^msnim:([^?]*)(\?(.*))", uri) + if not match: + print "Invalid msnim URI: %s" % uri + return + + command = urllib.unquote_plus(match.group(1)) + paramstring = match.group(3) + params = {} + if paramstring: + for param in paramstring.split("&"): + key, value = extendlist(param.split("=", 1), 2, "") + params[key] = urllib.unquote_plus(value) + screenname = params.get("contact", "") + + account = findaccount(protocol) + + if command.lower() == "chat": + goim(account, screenname) + elif command.lower() == "add": + addbuddy(account, screenname) + +def myim(uri): + protocol = "prpl-myspace" + print "TODO: send uri: ", uri + assert False, "Not implemented" + def sip(uri): protocol = "prpl-simple" match = re.match(r"^sip:(.*)", uri) @@ -182,6 +268,32 @@ else: goim(account, screenname) +def ymsgr(uri): + protocol = "prpl-yahoo" + match = re.match(r"^ymsgr:([^?]*)(\?([^&]*)(&(.*))?)", uri) + if not match: + print "Invalid ymsgr URI: %s" % uri + return + + command = urllib.unquote_plus(match.group(1)) + screenname = urllib.unquote_plus(match.group(3)) + paramstring = match.group(5) + params = {} + if paramstring: + for param in paramstring.split("&"): + key, value = extendlist(param.split("=", 1), 2, "") + params[key] = urllib.unquote_plus(value) + + account = findaccount(protocol) + + if command.lower() == "sendim": + goim(account, screenname, params.get("m")) + elif command.lower() == "chat": + gochat(account, {"room": screenname}) + elif command.lower() == "addfriend": + addbuddy(account, screenname) + + def main(argv=sys.argv): if len(argv) != 2: print "Usage: %s URI" % argv[0] @@ -192,16 +304,26 @@ type = uri.split(":")[0] try: - if type == "gg": + if type == "aim": + aim(uri) + elif type == "gg": gg(uri) + elif type == "icq": + icq(uri) elif type == "irc": irc(uri) + elif type == "msnim": + msnim(uri) + elif type == "myim": + myim(uri) elif type == "sip": sip(uri) elif type == "xmpp": xmpp(uri) + elif type == "ymsgr": + ymsgr(uri) else: - cpurple.PurpleGotProtocolHandlerUri(uri) + print "Unknown protocol: %s" % type except dbus.dbus_bindings.DBusException: print "ERROR: Is there a libpurple-powered client (e.g. Pidgin or Finch) running?"
--- a/libpurple/request.c Fri Aug 17 02:26:42 2007 +0000 +++ b/libpurple/request.c Mon Aug 27 21:59:11 2007 +0000 @@ -1172,7 +1172,7 @@ void * purple_request_choice(void *handle, const char *title, const char *primary, - const char *secondary, unsigned int default_value, + const char *secondary, int default_value, const char *ok_text, GCallback ok_cb, const char *cancel_text, GCallback cancel_cb, PurpleAccount *account, const char *who, PurpleConversation *conv, @@ -1197,7 +1197,7 @@ void * purple_request_choice_varg(void *handle, const char *title, const char *primary, const char *secondary, - unsigned int default_value, + int default_value, const char *ok_text, GCallback ok_cb, const char *cancel_text, GCallback cancel_cb, PurpleAccount *account, const char *who, PurpleConversation *conv, @@ -1233,7 +1233,7 @@ void * purple_request_action(void *handle, const char *title, const char *primary, - const char *secondary, unsigned int default_action, + const char *secondary, int default_action, PurpleAccount *account, const char *who, PurpleConversation *conv, void *user_data, size_t action_count, ...) { @@ -1254,7 +1254,7 @@ void * purple_request_action_varg(void *handle, const char *title, const char *primary, const char *secondary, - unsigned int default_action, + int default_action, PurpleAccount *account, const char *who, PurpleConversation *conv, void *user_data, size_t action_count, va_list actions) {
--- a/libpurple/request.h Fri Aug 17 02:26:42 2007 +0000 +++ b/libpurple/request.h Mon Aug 27 21:59:11 2007 +0000 @@ -190,13 +190,13 @@ PurpleAccount *account, const char *who, PurpleConversation *conv, void *user_data); void *(*request_choice)(const char *title, const char *primary, - const char *secondary, unsigned int default_value, + const char *secondary, int default_value, const char *ok_text, GCallback ok_cb, const char *cancel_text, GCallback cancel_cb, PurpleAccount *account, const char *who, PurpleConversation *conv, void *user_data, va_list choices); void *(*request_action)(const char *title, const char *primary, - const char *secondary, unsigned int default_action, + const char *secondary, int default_action, PurpleAccount *account, const char *who, PurpleConversation *conv, void *user_data, size_t action_count, va_list actions); @@ -1215,7 +1215,7 @@ * @param cancel_cb The callback for the @c Cancel button. * @param account The PurpleAccount associated with this request, or NULL if none is * @param who The username of the buddy assocaited with this request, or NULL if none is - * @param conv The PurpleConversation associated with this request, or NULL if none is + * @param conv The PurpleConversation associated with this request, or NULL if none is * @param user_data The data to pass to the callback. * @param ... The choices. This argument list should be * terminated with a NULL parameter. @@ -1224,7 +1224,7 @@ */ void *purple_request_choice(void *handle, const char *title, const char *primary, const char *secondary, - unsigned int default_value, + int default_value, const char *ok_text, GCallback ok_cb, const char *cancel_text, GCallback cancel_cb, PurpleAccount *account, const char *who, PurpleConversation *conv, @@ -1246,7 +1246,7 @@ * @param cancel_cb The callback for the @c Cancel button. * @param account The PurpleAccount associated with this request, or NULL if none is * @param who The username of the buddy assocaited with this request, or NULL if none is - * @param conv The PurpleConversation associated with this request, or NULL if none is + * @param conv The PurpleConversation associated with this request, or NULL if none is * @param user_data The data to pass to the callback. * @param choices The choices. This argument list should be * terminated with a @c NULL parameter. @@ -1255,7 +1255,7 @@ */ void *purple_request_choice_varg(void *handle, const char *title, const char *primary, const char *secondary, - unsigned int default_value, + int default_value, const char *ok_text, GCallback ok_cb, const char *cancel_text, GCallback cancel_cb, PurpleAccount *account, const char *who, PurpleConversation *conv, @@ -1275,7 +1275,7 @@ * @param default_action The default value. * @param account The PurpleAccount associated with this request, or NULL if none is * @param who The username of the buddy assocaited with this request, or NULL if none is - * @param conv The PurpleConversation associated with this request, or NULL if none is + * @param conv The PurpleConversation associated with this request, or NULL if none is * @param user_data The data to pass to the callback. * @param action_count The number of actions. * @param ... A list of actions. These are pairs of @@ -1290,7 +1290,7 @@ */ void *purple_request_action(void *handle, const char *title, const char *primary, const char *secondary, - unsigned int default_action, + int default_action, PurpleAccount *account, const char *who, PurpleConversation *conv, void *user_data, size_t action_count, ...); @@ -1308,7 +1308,7 @@ * @param default_action The default value. * @param account The PurpleAccount associated with this request, or NULL if none is * @param who The username of the buddy assocaited with this request, or NULL if none is - * @param conv The PurpleConversation associated with this request, or NULL if none is + * @param conv The PurpleConversation associated with this request, or NULL if none is * @param user_data The data to pass to the callback. * @param action_count The number of actions. * @param actions A list of actions and callbacks. @@ -1317,7 +1317,7 @@ */ void *purple_request_action_varg(void *handle, const char *title, const char *primary, const char *secondary, - unsigned int default_action, + int default_action, PurpleAccount *account, const char *who, PurpleConversation *conv, void *user_data, size_t action_count, va_list actions); @@ -1338,7 +1338,7 @@ * @param cancel_cb The callback for the @c Cancel button. * @param account The PurpleAccount associated with this request, or NULL if none is * @param who The username of the buddy associated with this request, or NULL if none is - * @param conv The PurpleConversation associated with this request, or NULL if none is + * @param conv The PurpleConversation associated with this request, or NULL if none is * @param user_data The data to pass to the callback. * * @return A UI-specific handle. @@ -1411,7 +1411,7 @@ * @param cancel_cb The callback for the @c Cancel button. * @param account The PurpleAccount associated with this request, or NULL if none is * @param who The username of the buddy assocaited with this request, or NULL if none is - * @param conv The PurpleConversation associated with this request, or NULL if none is + * @param conv The PurpleConversation associated with this request, or NULL if none is * @param user_data The data to pass to the callback. * * @return A UI-specific handle. @@ -1435,7 +1435,7 @@ * @param cancel_cb The callback for the @c Cancel button. * @param account The PurpleAccount associated with this request, or NULL if none is * @param who The username of the buddy assocaited with this request, or NULL if none is - * @param conv The PurpleConversation associated with this request, or NULL if none is + * @param conv The PurpleConversation associated with this request, or NULL if none is * @param user_data The data to pass to the callback. * * @return A UI-specific handle.
--- a/libpurple/server.c Fri Aug 17 02:26:42 2007 +0000 +++ b/libpurple/server.c Mon Aug 27 21:59:11 2007 +0000 @@ -242,6 +242,107 @@ } } +PurpleAttentionType *purple_get_attention_type_from_code(PurpleAccount *account, guint type_code) +{ + PurplePlugin *prpl; + PurpleAttentionType* attn; + GList *(*get_attention_types)(PurpleAccount *); + + g_return_val_if_fail(account != NULL, NULL); + + prpl = purple_find_prpl(purple_account_get_protocol_id(account)); + + /* Lookup the attention type in the protocol's attention_types list, if any. */ + get_attention_types = PURPLE_PLUGIN_PROTOCOL_INFO(prpl)->attention_types; + if (get_attention_types) { + GList *attention_types; + + attention_types = get_attention_types(account); + attn = (PurpleAttentionType *)g_list_nth_data(attention_types, type_code); + } else { + attn = NULL; + } + + return attn; +} + +void +serv_send_attention(PurpleConnection *gc, const char *who, guint type_code) +{ + PurpleAttentionType *attn; + PurpleMessageFlags flags; + PurplePlugin *prpl; + gboolean (*send_attention)(PurpleConnection *, const char *, guint); + + gchar *description; + time_t mtime; + + g_return_if_fail(gc != NULL); + g_return_if_fail(who != NULL); + + prpl = purple_find_prpl(purple_account_get_protocol_id(gc->account)); + send_attention = PURPLE_PLUGIN_PROTOCOL_INFO(prpl)->send_attention; + g_return_if_fail(send_attention != NULL); + + mtime = time(NULL); + + attn = purple_get_attention_type_from_code(gc->account, type_code); + + if (attn && attn->outgoing_description) { + description = g_strdup_printf(_("Attention! %s %s."), attn->outgoing_description, who); + } else { + description = g_strdup(_("Attention!")); + } + + flags = PURPLE_MESSAGE_SEND | PURPLE_MESSAGE_NOTIFY | PURPLE_MESSAGE_SYSTEM; + + purple_debug_info("server", "serv_send_attention: sending '%s' to %s\n", + description, who); + + if (!send_attention(gc, who, type_code)) + return; + + /* TODO: icons, sound, shaking... same as serv_got_attention(). */ + serv_got_im(gc, who, description, flags, mtime); + + g_free(description); +} + +void +serv_got_attention(PurpleConnection *gc, const char *who, guint type_code) +{ + PurpleMessageFlags flags; + PurpleAttentionType *attn; + gchar *description; + time_t mtime; + + mtime = time(NULL); + + attn = purple_get_attention_type_from_code(gc->account, type_code); + + /* PURPLE_MESSAGE_NOTIFY is for attention messages. */ + flags = PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NOTIFY | PURPLE_MESSAGE_RECV; + + /* TODO: if (attn->icon_name) is non-null, use it to lookup an emoticon and display + * it next to the attention command. And if it is null, display a generic icon. */ + + if (attn && attn->incoming_description) { + description = g_strdup_printf(_("Attention! You have been %s."), attn->incoming_description); + } else { + description = g_strdup(_("Attention!")); + } + + purple_debug_info("server", "serv_got_attention: got '%s' from %s\n", + description, who); + + serv_got_im(gc, who, description, flags, mtime); + + /* TODO: sounds (depending on PurpleAttentionType), shaking, etc. */ + + g_free(description); +} + + /* * Move a buddy from one group to another on server. *
--- a/libpurple/server.h Fri Aug 17 02:26:42 2007 +0000 +++ b/libpurple/server.h Mon Aug 27 21:59:11 2007 +0000 @@ -53,6 +53,35 @@ void serv_move_buddy(PurpleBuddy *, PurpleGroup *, PurpleGroup *); int serv_send_im(PurpleConnection *, const char *, const char *, PurpleMessageFlags flags); + +/** Get information about an account's attention commands, from the prpl. + * + * @return The attention command numbered 'code' from the prpl's attention_types, or NULL. + */ +PurpleAttentionType *purple_get_attention_type_from_code(PurpleAccount *account, guint type_code); + +/** Send an attention request message. + * + * @param gc The connection to send the message on. + * @param who Whose attention to request. + * @param type An index into the prpl's attention_types list determining the type + * of the attention request command to send. 0 if prpl only defines one + * (for example, Yahoo and MSN), but some protocols define more (MySpaceIM). + * + * Note that you can't send arbitrary PurpleAttentionType's, because there is + * only a fixed set of attention commands. + */ +void serv_send_attention(PurpleConnection *gc, const char *who, guint type_code); + +/** Process an incoming attention message. + * + * @param gc The connection that received the attention message. + * @param who Who requested your attention. + * @param type An index into the prpl's attention_types list determining the type + * of the attention request command to send. + */ +void serv_got_attention(PurpleConnection *gc, const char *who, guint type_code); + void serv_get_info(PurpleConnection *, const char *); void serv_set_info(PurpleConnection *, const char *); @@ -68,6 +97,7 @@ void serv_alias_buddy(PurpleBuddy *); void serv_got_alias(PurpleConnection *gc, const char *who, const char *alias); + /** * Receive a typing message from a remote user. Either PURPLE_TYPING * or PURPLE_TYPED. If the user has stopped typing then use
--- a/libpurple/util.c Fri Aug 17 02:26:42 2007 +0000 +++ b/libpurple/util.c Mon Aug 27 21:59:11 2007 +0000 @@ -1374,7 +1374,7 @@ g_string_free(cdata, TRUE); cdata = NULL; } - + } if(tags == tag) break; @@ -1425,7 +1425,7 @@ ALLOW_TAG("strong"); ALLOW_TAG("ul"); - + /* we skip <HR> because it's not legal in XHTML-IM. However, * we still want to send something sensible, so we put a * linebreak in its place. <BR> also needs special handling @@ -2539,7 +2539,7 @@ * people's settings if there is a problem writing the new values. */ gboolean -purple_util_write_data_to_file(const char *filename, const char *data, size_t size) +purple_util_write_data_to_file(const char *filename, const char *data, gssize size) { const char *user_dir = purple_user_dir(); gchar *filename_temp, *filename_full; @@ -4305,7 +4305,7 @@ } } -gboolean purple_message_meify(char *message, size_t len) +gboolean purple_message_meify(char *message, gssize len) { char *c; gboolean inside_html = FALSE;
--- a/libpurple/util.h Fri Aug 17 02:26:42 2007 +0000 +++ b/libpurple/util.h Mon Aug 27 21:59:11 2007 +0000 @@ -586,7 +586,7 @@ * @return TRUE if the file was written successfully. FALSE otherwise. */ gboolean purple_util_write_data_to_file(const char *filename, const char *data, - size_t size); + gssize size); /** * Read the contents of a given file and parse the results into an @@ -1113,7 +1113,7 @@ * @return TRUE if it starts with "/me ", and it has been removed, otherwise * FALSE */ -gboolean purple_message_meify(char *message, size_t len); +gboolean purple_message_meify(char *message, gssize len); /** * Removes the underscore characters from a string used identify the mnemonic
--- a/libpurple/win32/global.mak Fri Aug 17 02:26:42 2007 +0000 +++ b/libpurple/win32/global.mak Mon Aug 27 21:59:11 2007 +0000 @@ -11,7 +11,7 @@ # Locations of our various dependencies WIN32_DEV_TOP ?= $(PIDGIN_TREE_TOP)/../win32-dev ASPELL_TOP ?= $(WIN32_DEV_TOP)/aspell-dev-0-50-3-3 -GTKSPELL_TOP ?= $(WIN32_DEV_TOP)/gtkspell-2.0.6 +GTKSPELL_TOP ?= $(WIN32_DEV_TOP)/gtkspell-2.0.11 GTK_TOP ?= $(WIN32_DEV_TOP)/gtk_2_0 GTK_BIN ?= $(GTK_TOP)/bin BONJOUR_TOP ?= $(WIN32_DEV_TOP)/Bonjour_SDK
--- a/libpurple/xmlnode.c Fri Aug 17 02:26:42 2007 +0000 +++ b/libpurple/xmlnode.c Mon Aug 27 21:59:11 2007 +0000 @@ -272,6 +272,8 @@ if(NULL != node->parent) { if(node->parent->child == node) { node->parent->child = node->next; + if (node->parent->lastchild == node) + node->parent->lastchild = node->next; } else { xmlnode *prev = node->parent->child; while(prev && prev->next != node) { @@ -279,6 +281,8 @@ } if(prev) { prev->next = node->next; + if (node->parent->lastchild == node) + node->parent->lastchild = prev; } } }
--- a/pidgin/Makefile.am Fri Aug 17 02:26:42 2007 +0000 +++ b/pidgin/Makefile.am Mon Aug 27 21:59:11 2007 +0000 @@ -46,6 +46,7 @@ win32/nsis/translations/kurdish.nsh \ win32/nsis/translations/lithuanian.nsh \ win32/nsis/translations/norwegian.nsh \ + win32/nsis/translations/persian.nsh \ win32/nsis/translations/polish.nsh \ win32/nsis/translations/portuguese.nsh \ win32/nsis/translations/portuguese-br.nsh \
--- a/pidgin/gtkaccount.c Fri Aug 17 02:26:42 2007 +0000 +++ b/pidgin/gtkaccount.c Mon Aug 27 21:59:11 2007 +0000 @@ -272,7 +272,8 @@ add_user_options(dialog, dialog->top_vbox); add_protocol_options(dialog, dialog->bottom_vbox); - if (!dialog->prpl_info || !dialog->prpl_info->register_user) { + if (!dialog->prpl_info || !dialog->prpl_info->register_user || + g_object_get_data(G_OBJECT(item), "fake")) { gtk_widget_hide(dialog->register_button); } else { if (dialog->prpl_info != NULL && @@ -1394,7 +1395,9 @@ purple_signal_emit(pidgin_account_get_handle(), "account-modified", account); /* If this is a new account, then sign on! */ - if (new && !dialog->registering) { + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog->register_button))) { + purple_account_register(account); + } else if (new) { const PurpleSavedStatus *saved_status; saved_status = purple_savedstatus_get_current(); @@ -1410,19 +1413,6 @@ return account; } -static void -register_account_prefs_cb(GtkWidget *w, AccountPrefsDialog *dialog) -{ - PurpleAccount *account; - - dialog->registering = TRUE; - - account = ok_account_prefs_cb(NULL, dialog); - - purple_account_register(account); -} - - static const GtkTargetEntry dnd_targets[] = { {"text/plain", 0, 0}, {"text/uri-list", 0, 1}, @@ -1501,6 +1491,18 @@ add_login_options(dialog, vbox); add_user_options(dialog, vbox); + button = gtk_check_button_new_with_label(_("Create this new account on the server")); + gtk_box_pack_start(GTK_BOX(main_vbox), button, FALSE, FALSE, 0); + gtk_widget_show(button); + dialog->register_button = button; + if (dialog->account == NULL) + gtk_widget_set_sensitive(button, FALSE); + + if (!dialog->prpl_info || !dialog->prpl_info->register_user) + gtk_widget_hide(button); + + + /* Setup the page with 'Advanced'. */ dialog->bottom_vbox = dbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BORDER); gtk_container_set_border_width(GTK_CONTAINER(dbox), PIDGIN_HIG_BORDER); @@ -1519,22 +1521,6 @@ gtk_box_pack_end(GTK_BOX(main_vbox), bbox, FALSE, TRUE, 0); gtk_widget_show(bbox); - /* Register button */ - button = gtk_button_new_with_label(_("Register")); - gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0); - gtk_widget_show(button); - - g_signal_connect(G_OBJECT(button), "clicked", - G_CALLBACK(register_account_prefs_cb), dialog); - - dialog->register_button = button; - - if (dialog->account == NULL) - gtk_widget_set_sensitive(button, FALSE); - - if (!dialog->prpl_info || !dialog->prpl_info->register_user) - gtk_widget_hide(button); - /* Cancel button */ button = gtk_button_new_from_stock(GTK_STOCK_CANCEL); gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0);
--- a/pidgin/gtkblist.c Fri Aug 17 02:26:42 2007 +0000 +++ b/pidgin/gtkblist.c Mon Aug 27 21:59:11 2007 +0000 @@ -2528,7 +2528,8 @@ GValue val; struct _pidgin_blist_node *gtknode; - if (!gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(tv), gtkblist->tip_rect.x, gtkblist->tip_rect.y, &path, NULL, NULL, NULL)) + if (!gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(tv), gtkblist->tip_rect.x, gtkblist->tip_rect.y + (gtkblist->tip_rect.height/2), + &path, NULL, NULL, NULL)) return FALSE; gtk_tree_model_get_iter(GTK_TREE_MODEL(gtkblist->treemodel), &iter, path); val.g_type = 0; @@ -2585,7 +2586,8 @@ PurpleBlistNode *node; GValue val; - if (!gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(tv), gtkblist->tip_rect.x, gtkblist->tip_rect.y, &path, NULL, NULL, NULL)) + if (!gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(tv), gtkblist->tip_rect.x, gtkblist->tip_rect.y + (gtkblist->tip_rect.height/2), + &path, NULL, NULL, NULL)) return FALSE; gtk_tree_model_get_iter(GTK_TREE_MODEL(gtkblist->treemodel), &iter, path); val.g_type = 0;
--- a/pidgin/gtkconv.c Fri Aug 17 02:26:42 2007 +0000 +++ b/pidgin/gtkconv.c Mon Aug 27 21:59:11 2007 +0000 @@ -100,36 +100,6 @@ #define LUMINANCE(c) (float)((0.3*(c.red))+(0.59*(c.green))+(0.11*(c.blue))) -#if 0 -/* These colors come from the default GNOME palette */ -static GdkColor nick_colors[] = { - {0, 47616, 46336, 43776}, /* Basic 3D Medium */ - {0, 32768, 32000, 29696}, /* Basic 3D Dark */ - {0, 22016, 20992, 18432}, /* 3D Shadow */ - {0, 33536, 42496, 32512}, /* Green Medium */ - {0, 23808, 29952, 21760}, /* Green Dark */ - {0, 17408, 22016, 12800}, /* Green Shadow */ - {0, 57344, 46592, 44800}, /* Red Hilight */ - {0, 49408, 26112, 23040}, /* Red Medium */ - {0, 34816, 17920, 12544}, /* Red Dark */ - {0, 49408, 14336, 8704}, /* Red Shadow */ - {0, 34816, 32512, 41728}, /* Purple Medium */ - {0, 25088, 23296, 33024}, /* Purple Dark */ - {0, 18688, 16384, 26112}, /* Purple Shadow */ - {0, 40192, 47104, 53760}, /* Blue Hilight */ - {0, 29952, 36864, 44544}, /* Blue Medium */ - {0, 57344, 49920, 40448}, /* Face Skin Medium */ - {0, 45824, 37120, 26880}, /* Face skin Dark */ - {0, 33280, 26112, 18176}, /* Face Skin Shadow */ - {0, 57088, 16896, 7680}, /* Accent Red */ - {0, 39168, 0, 0}, /* Accent Red Dark */ - {0, 17920, 40960, 17920}, /* Accent Green */ - {0, 9728, 50944, 9728} /* Accent Green Dark */ -}; - -#define NUM_NICK_COLORS (sizeof(nick_colors) / sizeof(*nick_colors)) -#endif - /* From http://www.w3.org/TR/AERT#color-contrast */ #define MIN_BRIGHTNESS_CONTRAST 75 #define MIN_COLOR_CONTRAST 200 @@ -2301,7 +2271,7 @@ const char *name = NULL; GdkPixbuf *status = NULL; PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); - + const char *icon_size = small_icon ? PIDGIN_ICON_SIZE_TANGO_MICROSCOPIC : PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL; g_return_val_if_fail(conv != NULL, NULL); account = purple_conversation_get_account(conv); @@ -2314,22 +2284,41 @@ if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { PurpleBuddy *b = purple_find_buddy(account, name); if (b != NULL) { + PurplePresence *p = purple_buddy_get_presence(b); /* I hate this hack. It fixes a bug where the pending message icon * displays in the conv tab even though it shouldn't. * A better solution would be great. */ if (ops && ops->update) ops->update(NULL, (PurpleBlistNode*)b); - status = pidgin_blist_get_status_icon((PurpleBlistNode*)b, - (small_icon ? PIDGIN_STATUS_ICON_SMALL : PIDGIN_STATUS_ICON_LARGE)); + /* XXX Seanegan: We really need a util function to return a pixbuf for a Presence to avoid all this switching */ + if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_AWAY)) + status = pidgin_create_status_icon(PURPLE_STATUS_AWAY, PIDGIN_CONVERSATION(conv)->icon, icon_size); + else if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_EXTENDED_AWAY)) + status = pidgin_create_status_icon(PURPLE_STATUS_EXTENDED_AWAY, PIDGIN_CONVERSATION(conv)->icon, icon_size); + else if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_OFFLINE)) + status = pidgin_create_status_icon(PURPLE_STATUS_OFFLINE, PIDGIN_CONVERSATION(conv)->icon, icon_size); + else if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_AVAILABLE)) + status = pidgin_create_status_icon(PURPLE_STATUS_AVAILABLE, PIDGIN_CONVERSATION(conv)->icon, icon_size); + else if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_INVISIBLE)) + status = pidgin_create_status_icon(PURPLE_STATUS_INVISIBLE, PIDGIN_CONVERSATION(conv)->icon, icon_size); + else if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_UNAVAILABLE)) + status = pidgin_create_status_icon(PURPLE_STATUS_UNAVAILABLE, PIDGIN_CONVERSATION(conv)->icon, icon_size); } } /* If they don't have a buddy icon, then use the PRPL icon */ - if (status == NULL) - status = pidgin_create_prpl_icon(account, small_icon ? PIDGIN_PRPL_ICON_SMALL : PIDGIN_PRPL_ICON_LARGE); - - return status; + if (status == NULL) { + GtkIconSize size = gtk_icon_size_from_name(icon_size); + if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { + status = gtk_widget_render_icon (PIDGIN_CONVERSATION(conv)->icon, PIDGIN_STOCK_STATUS_PERSON, + size, "GtkWidget"); + } else { + status = gtk_widget_render_icon (PIDGIN_CONVERSATION(conv)->icon, PIDGIN_STOCK_STATUS_CHAT, + size, "GtkWidget"); + } + } + return status; } @@ -2341,6 +2330,7 @@ PurpleBuddy *b; GList *l; GdkPixbuf *status = NULL; + GdkPixbuf *infopane_status = NULL; GdkPixbuf *emblem = NULL; g_return_if_fail(conv != NULL); @@ -2352,6 +2342,8 @@ status = pidgin_conv_get_tab_icon(conv, TRUE); + infopane_status = pidgin_conv_get_tab_icon(conv, FALSE); + b = purple_find_buddy(conv->account, conv->name); if (b) emblem = pidgin_blist_get_emblem((PurpleBlistNode*)b); @@ -2363,7 +2355,7 @@ gtk_list_store_set(GTK_LIST_STORE(gtkconv->infopane_model), &(gtkconv->infopane_iter), - CONV_ICON_COLUMN, status, -1); + CONV_ICON_COLUMN, infopane_status, -1); gtk_list_store_set(GTK_LIST_STORE(gtkconv->infopane_model), &(gtkconv->infopane_iter), @@ -4523,7 +4515,7 @@ path = gtk_tree_path_new_from_string("0"); gtk_cell_view_set_displayed_row(GTK_CELL_VIEW(gtkconv->infopane), path); gtk_tree_path_free(path); - gtk_widget_set_size_request(gtkconv->infopane, -1, 32); + gtk_widget_set_size_request(gtkconv->infopane_hbox, -1, 32); gtk_widget_show(gtkconv->infopane); rend = gtk_cell_renderer_pixbuf_new(); @@ -6279,7 +6271,7 @@ (fields & PIDGIN_CONV_SET_TITLE) || (fields & PIDGIN_CONV_TOPIC)) { - char *title, *truncate = NULL, truncchar = '\0'; + char *title; PurpleConvIm *im = NULL; PurpleAccount *account = purple_conversation_get_account(conv); PurpleBuddy *buddy = NULL; @@ -6287,7 +6279,7 @@ char *markup = NULL; AtkObject *accessibility_obj; /* I think this is a little longer than it needs to be but I'm lazy. */ - char *style, *status_style; + char *style; if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) im = PURPLE_CONV_IM(conv); @@ -6300,12 +6292,6 @@ else title = g_strdup(purple_conversation_get_title(conv)); - if (((truncate = strchr(title, ' ')) && strcmp(title, conv->name)) || - (truncate = strchr(title, '@'))) { - truncchar = *truncate; - *truncate = '\0'; - } - if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { buddy = purple_find_buddy(account, conv->name); if (buddy) { @@ -6357,22 +6343,13 @@ style = ""; } - if (p && purple_presence_is_status_primitive_active(p, PURPLE_STATUS_OFFLINE)) { - status_style = "strikethrough='true'"; - } else if (p && !purple_presence_is_status_primitive_active(p, PURPLE_STATUS_AVAILABLE) && - !purple_presence_is_status_primitive_active(p, PURPLE_STATUS_INVISIBLE)) { - status_style = "style='italic'"; - } else { - status_style = ""; - } - - if (*style != '\0' || *status_style != '\0') + if (*style != '\0') { char *html_title,*label; html_title = g_markup_escape_text(title, -1); - label = g_strdup_printf("<span %s %s>%s</span>", - style, status_style, html_title); + label = g_strdup_printf("<span %s>%s</span>", + style, html_title); g_free(html_title); gtk_label_set_markup(GTK_LABEL(gtkconv->tab_label), label); g_free(label); @@ -6380,9 +6357,6 @@ else gtk_label_set_text(GTK_LABEL(gtkconv->tab_label), title); - if (truncate) - *truncate = truncchar; - if (pidgin_conv_window_is_active_conversation(conv)) update_typing_icon(gtkconv); @@ -7618,13 +7592,14 @@ * has looked at it so we know there are no longer unseen * messages. */ -static gint +static gboolean focus_win_cb(GtkWidget *w, GdkEventFocus *e, gpointer d) { PidginWindow *win = d; PidginConversation *gtkconv = pidgin_conv_window_get_active_gtkconv(win); - gtkconv_set_unseen(gtkconv, PIDGIN_UNSEEN_NONE); + if (gtkconv) + gtkconv_set_unseen(gtkconv, PIDGIN_UNSEEN_NONE); return FALSE; } @@ -7800,25 +7775,20 @@ if (e->button == 3) { /* Right click was pressed. Popup the Send To menu. */ GtkWidget *menu = gtk_menu_new(), *sub; + gboolean populated = populate_menu_with_options(menu, gtkconv, TRUE); sub = gtk_menu_item_get_submenu(GTK_MENU_ITEM(gtkconv->win->menu.send_to)); - if (populate_menu_with_options(menu, gtkconv, TRUE)) - pidgin_separator(menu); - else if (!sub || - !GTK_WIDGET_IS_SENSITIVE(gtkconv->win->menu.send_to)) { - gtk_widget_destroy(menu); - return FALSE; - } else { - menu = sub; - sub = NULL; - } - - if (sub) { + if (sub && GTK_WIDGET_IS_SENSITIVE(gtkconv->win->menu.send_to)) { GtkWidget *item = gtk_menu_item_new_with_mnemonic(_("_Send To")); + if (populated) + pidgin_separator(menu); gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), sub); gtk_widget_show(item); gtk_widget_show_all(sub); + } else if (!populated) { + gtk_widget_destroy(menu); + return FALSE; } gtk_widget_show_all(menu); @@ -8492,7 +8462,7 @@ gtk_notebook_set_scrollable(GTK_NOTEBOOK(win->notebook), TRUE); gtk_notebook_popup_enable(GTK_NOTEBOOK(win->notebook)); gtk_notebook_set_show_tabs(GTK_NOTEBOOK(win->notebook), FALSE); - gtk_notebook_set_show_border(GTK_NOTEBOOK(win->notebook), FALSE); + gtk_notebook_set_show_border(GTK_NOTEBOOK(win->notebook), TRUE); g_signal_connect(G_OBJECT(win->notebook), "button-press-event", G_CALLBACK(right_click_menu_cb), win); @@ -8607,14 +8577,26 @@ static gboolean close_button_left_cb(GtkWidget *widget, GdkEventCrossing *event, GtkLabel *label) { + static GdkCursor *ptr = NULL; + if (ptr == NULL) { + ptr = gdk_cursor_new(GDK_LEFT_PTR); + } + gtk_label_set_markup(label, "×"); + gdk_window_set_cursor(event->window, ptr); return FALSE; } static gboolean close_button_entered_cb(GtkWidget *widget, GdkEventCrossing *event, GtkLabel *label) { - gtk_label_set_markup(label, "<b>×</b>"); + static GdkCursor *hand = NULL; + if (hand == NULL) { + hand = gdk_cursor_new(GDK_HAND2); + } + + gtk_label_set_markup(label, "<u>×</u>"); + gdk_window_set_cursor(event->window, hand); return FALSE; } @@ -8665,6 +8647,7 @@ /* Status icon. */ gtkconv->icon = gtk_image_new(); gtkconv->menu_icon = gtk_image_new(); + gtk_widget_show(gtkconv->icon); update_tab_icon(conv); /* Tab label. */ @@ -8723,9 +8706,9 @@ angle = 270; #if GTK_CHECK_VERSION(2,6,0) - if (!angle && pidgin_conv_window_get_gtkconv_count(win) > 1) { + if (!angle) { g_object_set(G_OBJECT(gtkconv->tab_label), "ellipsize", PANGO_ELLIPSIZE_END, NULL); - gtk_label_set_width_chars(GTK_LABEL(gtkconv->tab_label), 6); + gtk_label_set_width_chars(GTK_LABEL(gtkconv->tab_label), 4); } else { g_object_set(G_OBJECT(gtkconv->tab_label), "ellipsize", PANGO_ELLIPSIZE_NONE, NULL); gtk_label_set_width_chars(GTK_LABEL(gtkconv->tab_label), -1); @@ -8765,8 +8748,6 @@ gtk_event_box_set_visible_window(GTK_EVENT_BOX(ebox), FALSE); #endif gtk_container_add(GTK_CONTAINER(ebox), gtkconv->tabby); - g_signal_connect(G_OBJECT(ebox), "button-press-event", - G_CALLBACK(alias_double_click_cb), gtkconv); if (gtkconv->tab_label->parent == NULL) { /* Pack if it's a new widget */ @@ -8790,14 +8771,15 @@ } gtk_notebook_set_tab_label_packing(GTK_NOTEBOOK(win->notebook), gtkconv->tab_cont, - !tabs_side && !angle && pidgin_conv_window_get_gtkconv_count(win) > 1, + !tabs_side && !angle, TRUE, GTK_PACK_START); if (pidgin_conv_window_get_gtkconv_count(win) == 1) gtk_notebook_set_show_tabs(GTK_NOTEBOOK(win->notebook), - !purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/im/show_buddy_icons") || + purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/tabs") && + (!purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/im/show_buddy_icons") || purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/tab_side") == GTK_POS_LEFT || - purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/tab_side") == GTK_POS_RIGHT); + purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/tab_side") == GTK_POS_RIGHT)); /* show the widgets */ /* gtk_widget_show(gtkconv->icon); */
--- a/pidgin/gtkdialogs.c Fri Aug 17 02:26:42 2007 +0000 +++ b/pidgin/gtkdialogs.c Mon Aug 27 21:59:11 2007 +0000 @@ -86,6 +86,7 @@ {"Luke 'LSchiere' Schierer", N_("support"), "lschiere@users.sf.net"}, {"Megan 'Cae' Schneider", N_("support/QA"), NULL}, {"Evan Schoenberg", N_("developer"), NULL}, + {"Kevin 'SimGuy' Stange", N_("developer & webmaster"), NULL}, {"Stu 'nosnilmot' Tomlinson", N_("developer"), NULL}, {"Nathan 'faceprint' Walp", N_("developer"), NULL}, {NULL, NULL, NULL} @@ -95,7 +96,7 @@ static struct developer patch_writers[] = { {"John 'rekkanoryo' Bailey", NULL, NULL}, {"Peter 'Bleeter' Lawler", NULL, NULL}, - {"Kevin 'SimGuy' Stange", NULL, NULL}, + {"Dennis 'EvilDennisR' Ristuccia", N_("Senior Contributor/QA"), NULL}, {NULL, NULL, NULL} }; @@ -152,6 +153,7 @@ {N_("British English"), "en_GB", "Luke Ross", "lukeross@sys3175.co.uk"}, {N_("Esperanto"), "eo", "Stéphane Fillod", "fillods@users.sourceforge.net"}, {N_("Spanish"), "es", "Javier Fernández-Sanguino Peña", "jfs@debian.org"}, + {N_("Estonian"), "et", "Ivar Smolin", "okul@linux.ee"}, {N_("Euskera(Basque)"), "eu", "Hizkuntza Politikarako Sailburuordetza", "hizkpol@ej-gv.es"}, {N_("Euskera(Basque)"), "eu", "Iñaki Larrañaga Murgoitio", "dooteo@zundan.com"}, {N_("Persian"), "fa", "Elnaz Sarbar", "elnaz@farsiweb.info"}, @@ -160,7 +162,7 @@ {N_("Finnish"), "fi", "Timo Jyrinki", "timo.jyrinki@iki.fi"}, {N_("French"), "fr", "Éric Boumaour", "zongo_fr@users.sourceforge.net"}, {N_("Galician"), "gl", "Mar Castro", "mariamarcp@gmail.com"}, - {N_("Galician"), "gl", "Ignacio Casal Quinteiro", "nacho.resa@gmail.com"}, + {N_("Galician"), "gl", "Frco. Javier Rial", "fjrial@cesga.es"}, {N_("Gujarati"), "gu", "Ankit Patel", "ankit_patel@users.sf.net"}, {N_("Gujarati"), "gu", N_("Gujarati Language Team"), "indianoss-gujarati@lists.sourceforge.net"}, {N_("Hebrew"), "he", "Shalom Craimer", "scraimer@gmail.com"}, @@ -181,7 +183,6 @@ {N_("Bokmål Norwegian"), "nb", "Hallvard Glad", "hallvard.glad@gmail.com"}, {N_("Nepali"), "ne", "Shyam Krishna Bal", "shyamkrishna_bal@yahoo.com"}, {N_("Dutch, Flemish"), "nl", "Vincent van Adrighem", "V.vanAdrighem@dirck.mine.nu"}, - {N_("Norwegian"), "no", "Petter Johan Olsen", "petter.olsen@cc.uit.no"}, {N_("Norwegian Nynorsk"), "nn", "Yngve Spjeld Landro", "nynorsk@strilen.net"}, {N_("Polish"), "pl", "Emil Nowak", "emil5@go2.pl"}, {N_("Polish"), "pl", "Paweł Godlewski", "pawel@bajk.pl"}, @@ -197,7 +198,7 @@ {N_("Albanian"), "sq", "Besnik Bleta", "besnik@programeshqip.org"}, {N_("Serbian"), "sr", "Danilo Šegan", "dsegan@gmx.net"}, {N_("Serbian"), "sr", "Aleksandar Urosevic", "urke@users.sourceforge.net"}, - {N_("Swedish"), "sv", "Tore Lundqvist", "tlt@mima.x.se"}, + {N_("Swedish"), "sv", "Peter Hjalmarsson", "xake@telia.com"}, {N_("Tamil"), "ta", "Viveka Nathan K", "vivekanathan@users.sourceforge.net"}, {N_("Telugu"), "te", "Mr. Subbaramaih", "info.gist@cdac.in"}, {N_("Thai"), "th", "Isriya Paireepairit", "markpeak@gmail.com"}, @@ -230,6 +231,7 @@ {N_("French"), "fr", "Stéphane Pontier", NULL}, {N_("French"), "fr", "Stéphane Wirtel", NULL}, {N_("French"), "fr", "Loïc Jeannin", NULL}, + {N_("Galician"), "gl", "Ignacio Casal Quinteiro", NULL}, {N_("Hebrew"), "he", "Pavel Bibergal", NULL}, {N_("Italian"), "it", "Salvatore di Maggio", NULL}, {N_("Japanese"), "ja", "Ryosuke Kutsuna", NULL}, @@ -237,19 +239,21 @@ {N_("Japanese"), "ja", "Junichi Uekawa", NULL}, {N_("Georgian"), "ka", "Temuri Doghonadze", NULL}, {N_("Korean"), "ko", "Sang-hyun S, A Ho-seok Lee", NULL}, - {N_("Korean"), "ko", "Kyeong-uk Son", "hey@gnome.or.kr"}, + {N_("Korean"), "ko", "Kyeong-uk Son", NULL}, {N_("Lithuanian"), "lt", "Andrius Štikonas", NULL}, {N_("Lithuanian"), "lt", "Gediminas Čičinskas", NULL}, - {N_("Macedonian"), "mk", "Tomislav Markovski", "herrera@users.sf.net"}, + {N_("Macedonian"), "mk", "Tomislav Markovski", NULL}, + {N_("Bokmål Norwegian"), "nb", "Petter Johan Olsen", NULL}, {N_("Polish"), "pl", "Przemysław Sułek", NULL}, {N_("Russian"), "ru", "Alexandre Prokoudine", NULL}, {N_("Russian"), "ru", "Sergey Volozhanin", NULL}, {N_("Slovak"), "sk", "Daniel Režný", NULL}, - {N_("Slovak"), "sk", "helix84", "helix84@centrum.sk"}, - {N_("Slovak"), "sk", "Richard Golier", "golierr@gmail.com"}, + {N_("Slovak"), "sk", "helix84", NULL}, + {N_("Slovak"), "sk", "Richard Golier", NULL}, {N_("Slovenian"), "sl", "Matjaz Horvat", NULL}, + {N_("Swedish"), "sv", "Tore Lundqvist", NULL}, {N_("Swedish"), "sv", "Christian Rose", NULL}, - {N_("Turkish"), "tr", "Ahmet Alp BALKAN", "prf_q@users.sf.net"}, + {N_("Turkish"), "tr", "Ahmet Alp BALKAN", NULL}, {N_("Simplified Chinese"), "zh_CN", "Hashao, Rocky S. Lee", NULL}, {N_("Traditional Chinese"), "zh_TW", "Hashao, Rocky S. Lee", NULL}, {NULL, NULL, NULL, NULL} @@ -298,7 +302,7 @@ context = gtk_widget_get_pango_context(widget); layout = pango_layout_new(context); - markup = g_strdup_printf("<span foreground=\"#5c3566\">%s</span>", VERSION); + markup = g_strdup_printf("<span foreground=\"#FFFFFF\">%s</span>", VERSION); pango_layout_set_font_description(layout, style->font_desc); pango_layout_set_markup(layout, markup, strlen(markup)); g_free(markup); @@ -378,7 +382,7 @@ "libpurple which is capable of connecting to " "AIM, MSN, Yahoo!, XMPP, ICQ, IRC, SILC, SIP/SIMPLE, " "Novell GroupWise, Lotus Sametime, Bonjour, Zephyr, " - "Gadu-Gadu, and QQ all at once. " + "MySpaceIM, Gadu-Gadu, and QQ all at once. " "It is written using GTK+.<BR><BR>" "You may modify and redistribute the program under " "the terms of the GPL (version 2 or later). A copy of the GPL is "
--- a/pidgin/gtkimhtmltoolbar.c Fri Aug 17 02:26:42 2007 +0000 +++ b/pidgin/gtkimhtmltoolbar.c Mon Aug 27 21:59:11 2007 +0000 @@ -70,6 +70,14 @@ } static void +do_strikethrough(GtkWidget *strikethrough, GtkIMHtmlToolbar *toolbar) +{ + g_return_if_fail(toolbar != NULL); + gtk_imhtml_toggle_strike(GTK_IMHTML(toolbar->imhtml)); + gtk_widget_grab_focus(toolbar->imhtml); +} + +static void do_small(GtkWidget *smalltb, GtkIMHtmlToolbar *toolbar) { g_return_if_fail(toolbar != NULL); @@ -433,6 +441,17 @@ gtk_widget_grab_focus(toolbar->imhtml); } +static void insert_hr_cb(GtkWidget *widget, GtkIMHtmlToolbar *toolbar) +{ + GtkTextIter iter; + GtkTextMark *ins; + GtkIMHtmlScalable *hr; + + ins = gtk_text_buffer_get_insert(gtk_text_view_get_buffer(GTK_TEXT_VIEW(toolbar->imhtml))); + gtk_text_buffer_get_iter_at_mark(gtk_text_view_get_buffer(GTK_TEXT_VIEW(toolbar->imhtml)), &iter, ins); + hr = gtk_imhtml_hr_new(); + gtk_imhtml_hr_add_to(hr, GTK_IMHTML(toolbar->imhtml), &iter); +} static void do_insert_image_cb(GtkWidget *widget, int response, GtkIMHtmlToolbar *toolbar) @@ -1027,6 +1046,13 @@ G_CALLBACK(do_underline), toolbar); toolbar->underline = button; + + /* Strikethrough */ + button = pidgin_pixbuf_toolbar_button_from_stock(GTK_STOCK_STRIKETHROUGH); + g_signal_connect(G_OBJECT(button), "clicked", + G_CALLBACK(do_strikethrough), toolbar); + toolbar->strikethrough = button; + /* Increase font size */ button = pidgin_pixbuf_toolbar_button_from_stock(PIDGIN_STOCK_TOOLBAR_TEXT_LARGER); g_signal_connect(G_OBJECT(button), "clicked", @@ -1124,6 +1150,7 @@ {_("<b>_Bold</b>"), &toolbar->bold, TRUE}, {_("<i>_Italic</i>"), &toolbar->italic, TRUE}, {_("<u>_Underline</u>"), &toolbar->underline, TRUE}, + {_("<span strikethrough='true'>Strikethrough</span>"), &toolbar->strikethrough, TRUE}, {_("<span size='larger'>_Larger</span>"), &toolbar->larger_size, TRUE}, #if 0 {_("_Normal"), &toolbar->normal_size, TRUE}, @@ -1230,6 +1257,11 @@ g_signal_connect(G_OBJECT(toolbar->link), "notify::sensitive", G_CALLBACK(button_sensitiveness_changed), menuitem); + menuitem = gtk_menu_item_new_with_mnemonic(_("_Horizontal rule")); + g_signal_connect(G_OBJECT(menuitem), "activate" , G_CALLBACK(insert_hr_cb), toolbar); + gtk_menu_shell_append(GTK_MENU_SHELL(insert_menu), menuitem); + toolbar->insert_hr = menuitem; + g_signal_connect_swapped(G_OBJECT(insert_button), "button-press-event", G_CALLBACK(gtk_widget_activate), insert_button); g_signal_connect(G_OBJECT(insert_button), "activate", G_CALLBACK(pidgin_menu_clicked), insert_menu); g_signal_connect(G_OBJECT(insert_menu), "deactivate", G_CALLBACK(pidgin_menu_deactivate), insert_button);
--- a/pidgin/gtkimhtmltoolbar.h Fri Aug 17 02:26:42 2007 +0000 +++ b/pidgin/gtkimhtmltoolbar.h Mon Aug 27 21:59:11 2007 +0000 @@ -74,6 +74,8 @@ GtkWidget *image_dialog; char *sml; + GtkWidget *strikethrough; + GtkWidget *insert_hr; }; struct _GtkIMHtmlToolbarClass {
--- a/pidgin/gtknotify.c Fri Aug 17 02:26:42 2007 +0000 +++ b/pidgin/gtknotify.c Mon Aug 27 21:59:11 2007 +0000 @@ -151,6 +151,10 @@ mail_dialog = NULL; } +static void email_row_activated_cb(GtkTreeView *tv, GtkTreePath *path, GtkTreeViewColumn *col, gpointer data) { + email_response_cb(GTK_DIALOG(mail_dialog->dialog), GTK_RESPONSE_YES, mail_dialog); +} + static void reset_mail_dialog(GtkDialog *dialog) { @@ -377,6 +381,7 @@ G_CALLBACK(email_response_cb), mail_dialog); g_signal_connect(G_OBJECT(gtk_tree_view_get_selection(GTK_TREE_VIEW(mail_dialog->treeview))), "changed", G_CALLBACK(selection_changed_cb), mail_dialog); + g_signal_connect(G_OBJECT(mail_dialog->treeview), "row-activated", G_CALLBACK(email_row_activated_cb), NULL); gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(mail_dialog->treeview), FALSE); gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(mail_dialog->treeview), TRUE); @@ -584,16 +589,16 @@ char label_text[2048]; char *linked_text, *primary_esc, *secondary_esc; - window = pidgin_create_window(title, PIDGIN_HIG_BORDER, NULL, TRUE); - gtk_window_set_type_hint(GTK_WINDOW(window), GDK_WINDOW_TYPE_HINT_DIALOG); + window = gtk_dialog_new(); + gtk_window_set_title(GTK_WINDOW(window), title); + gtk_container_set_border_width(GTK_CONTAINER(window), PIDGIN_HIG_BORDER); + gtk_window_set_resizable(GTK_WINDOW(window), TRUE); g_signal_connect(G_OBJECT(window), "delete_event", G_CALLBACK(formatted_close_cb), NULL); /* Setup the main vbox */ - vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BORDER); - gtk_container_add(GTK_CONTAINER(window), vbox); - gtk_widget_show(vbox); + vbox = GTK_DIALOG(window)->vbox; /* Setup the descriptive label */ primary_esc = g_markup_escape_text(primary, -1); @@ -625,9 +630,7 @@ gtk_widget_show(frame); /* Add the Close button. */ - button = gtk_button_new_from_stock(GTK_STOCK_CLOSE); - gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 0); - gtk_widget_show(button); + button = gtk_dialog_add_button(GTK_DIALOG(window), GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE); gtk_widget_grab_focus(button); g_signal_connect_swapped(G_OBJECT(button), "clicked", @@ -703,7 +706,6 @@ guint i; GtkWidget *vbox; - GtkWidget *button_area; GtkWidget *label; GtkWidget *sw; PidginNotifySearchResultsData *data; @@ -718,16 +720,16 @@ data->results = results; /* Create the window */ - window = pidgin_create_window(title ? title :_("Search Results"), PIDGIN_HIG_BORDER, NULL, TRUE); - gtk_window_set_type_hint(GTK_WINDOW(window), GDK_WINDOW_TYPE_HINT_DIALOG); + window = gtk_dialog_new(); + gtk_window_set_title(GTK_WINDOW(window), title ? title :_("Search Results")); + gtk_container_set_border_width(GTK_CONTAINER(window), PIDGIN_HIG_BORDER); + gtk_window_set_resizable(GTK_WINDOW(window), TRUE); g_signal_connect_swapped(G_OBJECT(window), "delete_event", G_CALLBACK(searchresults_close_cb), data); /* Setup the main vbox */ - vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BORDER); - gtk_container_add(GTK_CONTAINER(window), vbox); - gtk_widget_show(vbox); + vbox = GTK_DIALOG(window)->vbox; /* Setup the descriptive label */ primary_esc = (primary != NULL) ? g_markup_escape_text(primary, -1) : NULL; @@ -791,13 +793,6 @@ renderer, "text", i, NULL); } - /* Setup the button area */ - button_area = gtk_hbutton_box_new(); - gtk_box_pack_start(GTK_BOX(vbox), button_area, FALSE, FALSE, 0); - gtk_button_box_set_layout(GTK_BUTTON_BOX(button_area), GTK_BUTTONBOX_END); - gtk_box_set_spacing(GTK_BOX(button_area), PIDGIN_HIG_BORDER); - gtk_widget_show(button_area); - for (i = 0; i < g_list_length(results->buttons); i++) { PurpleNotifySearchButton *b = g_list_nth_data(results->buttons, i); GtkWidget *button = NULL; @@ -810,22 +805,22 @@ } break; case PURPLE_NOTIFY_BUTTON_CONTINUE: - button = gtk_button_new_from_stock(GTK_STOCK_GO_FORWARD); + button = gtk_dialog_add_button(GTK_DIALOG(window), GTK_STOCK_GO_FORWARD, GTK_RESPONSE_NONE); break; case PURPLE_NOTIFY_BUTTON_ADD: - button = gtk_button_new_from_stock(GTK_STOCK_ADD); + button = gtk_dialog_add_button(GTK_DIALOG(window), GTK_STOCK_ADD, GTK_RESPONSE_NONE); break; case PURPLE_NOTIFY_BUTTON_INFO: - button = gtk_button_new_from_stock(PIDGIN_STOCK_TOOLBAR_USER_INFO); + button = gtk_dialog_add_button(GTK_DIALOG(window), PIDGIN_STOCK_TOOLBAR_USER_INFO, GTK_RESPONSE_NONE); break; case PURPLE_NOTIFY_BUTTON_IM: - button = gtk_button_new_from_stock(PIDGIN_STOCK_TOOLBAR_MESSAGE_NEW); + button = gtk_dialog_add_button(GTK_DIALOG(window), PIDGIN_STOCK_TOOLBAR_MESSAGE_NEW, GTK_RESPONSE_NONE); break; case PURPLE_NOTIFY_BUTTON_JOIN: - button = gtk_button_new_from_stock(PIDGIN_STOCK_CHAT); + button = gtk_dialog_add_button(GTK_DIALOG(window), PIDGIN_STOCK_CHAT, GTK_RESPONSE_NONE); break; case PURPLE_NOTIFY_BUTTON_INVITE: - button = gtk_button_new_from_stock(PIDGIN_STOCK_INVITE); + button = gtk_dialog_add_button(GTK_DIALOG(window), PIDGIN_STOCK_INVITE, GTK_RESPONSE_NONE); break; default: purple_debug_warning("gtknotify", "Incorrect button type: %d\n", b->type); @@ -833,9 +828,6 @@ if (button != NULL) { PidginNotifySearchResultsButtonData *bd; - gtk_box_pack_start(GTK_BOX(button_area), button, FALSE, FALSE, 0); - gtk_widget_show(button); - bd = g_new0(PidginNotifySearchResultsButtonData, 1); bd->button = b; bd->data = data; @@ -847,9 +839,7 @@ } /* Add the Close button */ - close_button = gtk_button_new_from_stock(GTK_STOCK_CLOSE); - gtk_box_pack_start(GTK_BOX(button_area), close_button, FALSE, FALSE, 0); - gtk_widget_show(close_button); + close_button = gtk_dialog_add_button(GTK_DIALOG(window), GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE); g_signal_connect_swapped(G_OBJECT(close_button), "clicked", G_CALLBACK(searchresults_close_cb), data);
--- a/pidgin/gtkpounce.c Fri Aug 17 02:26:42 2007 +0000 +++ b/pidgin/gtkpounce.c Mon Aug 27 21:59:11 2007 +0000 @@ -467,7 +467,6 @@ PidginPounceDialog *dialog; GtkWidget *window; GtkWidget *label; - GtkWidget *bbox; GtkWidget *vbox1, *vbox2; GtkWidget *hbox; GtkWidget *button; @@ -513,17 +512,16 @@ sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); /* Create the window. */ - dialog->window = window = pidgin_create_window((cur_pounce == NULL ? _("New Buddy Pounce") : _("Edit Buddy Pounce")), - PIDGIN_HIG_BORDER, "buddy_pounce", FALSE) ; - gtk_window_set_type_hint(GTK_WINDOW(window), GDK_WINDOW_TYPE_HINT_DIALOG); + dialog->window = window = gtk_dialog_new(); + gtk_window_set_title(GTK_WINDOW(window), (cur_pounce == NULL ? _("New Buddy Pounce") : _("Edit Buddy Pounce"))); + gtk_window_set_role(GTK_WINDOW(window), "buddy_pounce"); + gtk_container_set_border_width(GTK_CONTAINER(dialog->window), PIDGIN_HIG_BORDER); g_signal_connect(G_OBJECT(window), "delete_event", G_CALLBACK(delete_win_cb), dialog); /* Create the parent vbox for everything. */ - vbox1 = gtk_vbox_new(FALSE, PIDGIN_HIG_BORDER); - gtk_container_add(GTK_CONTAINER(window), vbox1); - gtk_widget_show(vbox1); + vbox1 = GTK_DIALOG(window)->vbox; /* Create the vbox that will contain all the prefs stuff. */ vbox2 = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); @@ -808,26 +806,13 @@ gtk_widget_show(dialog->on_away); gtk_widget_show(dialog->save_pounce); - /* Now the button box! */ - bbox = gtk_hbutton_box_new(); - gtk_box_set_spacing(GTK_BOX(bbox), PIDGIN_HIG_BOX_SPACE); - gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END); - gtk_box_pack_end(GTK_BOX(vbox1), bbox, FALSE, FALSE, 0); - gtk_widget_show(bbox); - /* Cancel button */ - button = gtk_button_new_from_stock(GTK_STOCK_CANCEL); - gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0); - gtk_widget_show(button); - + button = gtk_dialog_add_button(GTK_DIALOG(window), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL); g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(cancel_cb), dialog); /* Save button */ - dialog->save_button = button = gtk_button_new_from_stock(GTK_STOCK_SAVE); - gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0); - gtk_widget_show(button); - + dialog->save_button = button = gtk_dialog_add_button(GTK_DIALOG(window), GTK_STOCK_SAVE, GTK_RESPONSE_OK); g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(save_pounce_cb), dialog);
--- a/pidgin/gtkprefs.c Fri Aug 17 02:26:42 2007 +0000 +++ b/pidgin/gtkprefs.c Mon Aug 27 21:59:11 2007 +0000 @@ -240,7 +240,7 @@ if (label != NULL) { gtk_label_set_mnemonic_widget(GTK_LABEL(label), dropdown); - pidgin_set_accessible_label (dropdown, label); + pidgin_set_accessible_relations (dropdown, label); } if (type == PURPLE_PREF_INT)
--- a/pidgin/gtkrequest.c Fri Aug 17 02:26:42 2007 +0000 +++ b/pidgin/gtkrequest.c Mon Aug 27 21:59:11 2007 +0000 @@ -442,7 +442,7 @@ static void * pidgin_request_choice(const char *title, const char *primary, - const char *secondary, unsigned int default_value, + const char *secondary, int default_value, const char *ok_text, GCallback ok_cb, const char *cancel_text, GCallback cancel_cb, PurpleAccount *account, const char *who, PurpleConversation *conv, @@ -548,7 +548,7 @@ static void * pidgin_request_action(const char *title, const char *primary, - const char *secondary, unsigned int default_action, + const char *secondary, int default_action, PurpleAccount *account, const char *who, PurpleConversation *conv, void *user_data, size_t action_count, va_list actions) { @@ -1083,7 +1083,7 @@ data->cbs[0] = ok_cb; data->cbs[1] = cancel_cb; - + #ifdef _WIN32 data->dialog = win = pidgin_create_window(PIDGIN_ALERT_TITLE, PIDGIN_HIG_BORDER, "multifield", TRUE) ; #else /* !_WIN32 */
--- a/pidgin/gtksavedstatuses.c Fri Aug 17 02:26:42 2007 +0000 +++ b/pidgin/gtksavedstatuses.c Mon Aug 27 21:59:11 2007 +0000 @@ -1450,7 +1450,9 @@ GtkWidget *win; GtkTreeIter iter; GtkCellRenderer *rend; - const char *status_id = NULL; + char *status_id = NULL; + char *message = NULL; + gboolean parent_dialog_has_substatus = FALSE; GList *list; gboolean select = FALSE; @@ -1553,25 +1555,29 @@ G_CALLBACK(substatus_editor_ok_cb), dialog); /* Seed the input widgets with the current values */ - /* TODO: Get the current values from our parent's list store, not the saved_status! */ - if (status_editor->original_title != NULL) - { + + /* Only look at the saved status if we can't find it in the parent status dialog's substatuses model */ + gtk_tree_model_get(GTK_TREE_MODEL(status_editor->model), &iter, + STATUS_EDITOR_COLUMN_ENABLE_SUBSTATUS, &parent_dialog_has_substatus, -1); + if (parent_dialog_has_substatus) { + gtk_tree_model_get(GTK_TREE_MODEL(status_editor->model), &iter, + STATUS_EDITOR_COLUMN_STATUS_ID, &status_id, + STATUS_EDITOR_COLUMN_STATUS_MESSAGE, &message, -1); + } else if (status_editor->original_title != NULL) { PurpleSavedStatus *saved_status = NULL; PurpleSavedStatusSub *substatus = NULL; - saved_status = purple_savedstatus_find(status_editor->original_title); - if (saved_status != NULL) - substatus = purple_savedstatus_get_substatus(saved_status, account); + if ((saved_status = purple_savedstatus_find(status_editor->original_title)) != NULL) { + if ((substatus = purple_savedstatus_get_substatus(saved_status, account)) != NULL) { + message = (char *)purple_savedstatus_substatus_get_message(substatus); + status_id = (char *)purple_status_type_get_id(purple_savedstatus_substatus_get_type(substatus)); + } + } + } + /* TODO: Else get the generic status type from our parent */ - if (substatus != NULL) - { - gtk_imhtml_append_text(dialog->message, - purple_savedstatus_substatus_get_message(substatus), - 0); - status_id = purple_status_type_get_id(purple_savedstatus_substatus_get_type(substatus)); - } - /* TODO: Else get the generic status type from our parent */ - } + if (message) + gtk_imhtml_append_text(dialog->message, message, 0); for (list = purple_account_get_status_types(account); list; list = list->next) { @@ -1607,6 +1613,12 @@ if (!select) gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 0); + if (parent_dialog_has_substatus) { + /* These two were gotten from the parent tree model, so they need to be freed */ + g_free(status_id); + g_free(message); + } + gtk_widget_show_all(win); }
--- a/pidgin/gtksound.c Fri Aug 17 02:26:42 2007 +0000 +++ b/pidgin/gtksound.c Mon Aug 27 21:59:11 2007 +0000 @@ -364,14 +364,14 @@ GError *err = NULL; switch (GST_MESSAGE_TYPE (msg)) { - case GST_MESSAGE_EOS: - gst_element_set_state(play, GST_STATE_NULL); - gst_object_unref(GST_OBJECT(play)); - break; case GST_MESSAGE_ERROR: gst_message_parse_error(msg, &err, NULL); purple_debug_error("gstreamer", "%s\n", err->message); g_error_free(err); + /* fall-through and clean up */ + case GST_MESSAGE_EOS: + gst_element_set_state(play, GST_STATE_NULL); + gst_object_unref(GST_OBJECT(play)); break; case GST_MESSAGE_WARNING: gst_message_parse_warning(msg, &err, NULL);
--- a/pidgin/gtkstatusbox.c Fri Aug 17 02:26:42 2007 +0000 +++ b/pidgin/gtkstatusbox.c Mon Aug 27 21:59:11 2007 +0000 @@ -788,7 +788,8 @@ primitive = purple_savedstatus_get_type(saved_status); if (!status_box->token_status_account && purple_savedstatus_is_transient(saved_status) && ((primitive == PURPLE_STATUS_AVAILABLE) || (primitive == PURPLE_STATUS_AWAY) || - (primitive == PURPLE_STATUS_INVISIBLE) || (primitive == PURPLE_STATUS_OFFLINE)) && + (primitive == PURPLE_STATUS_INVISIBLE) || (primitive == PURPLE_STATUS_OFFLINE) || + (primitive == PURPLE_STATUS_UNAVAILABLE)) && (!purple_savedstatus_has_substatuses(saved_status))) { index = get_statusbox_index(status_box, saved_status); @@ -1414,15 +1415,15 @@ } -static void -toggled_cb(GtkWidget *widget, PidginStatusBox *box) +static +gboolean +toggled_cb(GtkWidget *widget, GdkEventButton *event, PidginStatusBox *box) { - if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) { if (!box->popup_in_progress) pidgin_status_box_popup (box); - } else { - pidgin_status_box_popdown(box); - } + else + pidgin_status_box_popdown(box); +return TRUE; } static void @@ -1772,7 +1773,7 @@ g_signal_connect(G_OBJECT(status_box->toggle_button), "button-release-event", G_CALLBACK(button_released_cb), status_box); #endif - g_signal_connect(G_OBJECT(status_box->toggle_button), "toggled", + g_signal_connect(G_OBJECT(status_box->toggle_button), "button-press-event", G_CALLBACK(toggled_cb), status_box); g_signal_connect(G_OBJECT(buffer), "changed", G_CALLBACK(imhtml_changed_cb), status_box); g_signal_connect(G_OBJECT(status_box->imhtml), "format_function_toggle", @@ -2562,24 +2563,23 @@ static gint get_statusbox_index(PidginStatusBox *box, PurpleSavedStatus *saved_status) { - gint index; + gint index = -1; switch (purple_savedstatus_get_type(saved_status)) { - case PURPLE_STATUS_AVAILABLE: - index = 0; - break; + /* In reverse order */ + case PURPLE_STATUS_OFFLINE: + index++; + case PURPLE_STATUS_INVISIBLE: + index++; + case PURPLE_STATUS_UNAVAILABLE: + index++; case PURPLE_STATUS_AWAY: - index = 1; - break; - case PURPLE_STATUS_INVISIBLE: - index = 2; - break; - case PURPLE_STATUS_OFFLINE: - index = 3; + index++; + case PURPLE_STATUS_AVAILABLE: + index++; break; default: - index = -1; break; }
--- a/pidgin/gtkutils.c Fri Aug 17 02:26:42 2007 +0000 +++ b/pidgin/gtkutils.c Mon Aug 27 21:59:11 2007 +0000 @@ -1147,12 +1147,30 @@ void pidgin_set_accessible_label (GtkWidget *w, GtkWidget *l) { + AtkObject *acc; + const gchar *label_text; + const gchar *existing_name; + + acc = gtk_widget_get_accessible (w); + + /* If this object has no name, set it's name with the label text */ + existing_name = atk_object_get_name (acc); + if (!existing_name) { + label_text = gtk_label_get_text (GTK_LABEL(l)); + if (label_text) + atk_object_set_name (acc, label_text); + } + + pidgin_set_accessible_relations(w, l); +} + +void +pidgin_set_accessible_relations (GtkWidget *w, GtkWidget *l) +{ AtkObject *acc, *label; AtkObject *rel_obj[1]; AtkRelationSet *set; AtkRelation *relation; - const gchar *label_text; - const gchar *existing_name; acc = gtk_widget_get_accessible (w); label = gtk_widget_get_accessible (l); @@ -1160,14 +1178,6 @@ /* Make sure mnemonics work */ gtk_label_set_mnemonic_widget(GTK_LABEL(l), w); - /* If this object has no name, set it's name with the label text */ - existing_name = atk_object_get_name (acc); - if (!existing_name) { - label_text = gtk_label_get_text (GTK_LABEL(l)); - if (label_text) - atk_object_set_name (acc, label_text); - } - /* Create the labeled-by relation */ set = atk_object_ref_relation_set (acc); rel_obj[0] = label;
--- a/pidgin/gtkutils.h Fri Aug 17 02:26:42 2007 +0000 +++ b/pidgin/gtkutils.h Mon Aug 27 21:59:11 2007 +0000 @@ -418,6 +418,14 @@ void pidgin_set_accessible_label(GtkWidget *w, GtkWidget *l); /** + * Sets the labelled-by and label-for ATK relationships. + * + * @param w The widget that we want to label. + * @param l A GtkLabel that we want to use as the label for the widget. + */ +void pidgin_set_accessible_relations(GtkWidget *w, GtkWidget *l); + +/** * A helper function for GtkMenuPositionFuncs. This ensures the menu will * be kept on screen if possible. *
--- a/pidgin/pidginstock.c Fri Aug 17 02:26:42 2007 +0000 +++ b/pidgin/pidginstock.c Mon Aug 27 21:59:11 2007 +0000 @@ -93,6 +93,7 @@ const char *name; const char *dir; const char *filename; + gboolean microscopic; gboolean extra_small; gboolean small; gboolean medium; @@ -101,76 +102,76 @@ gboolean rtl; const char *translucent_name; } const sized_stock_icons [] = { - { PIDGIN_STOCK_STATUS_AVAILABLE, "status", "available.png", TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, PIDGIN_STOCK_STATUS_AVAILABLE_I }, - { PIDGIN_STOCK_STATUS_AWAY, "status", "away.png", TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, PIDGIN_STOCK_STATUS_AWAY_I }, - { PIDGIN_STOCK_STATUS_BUSY, "status", "busy.png", TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, PIDGIN_STOCK_STATUS_BUSY_I }, - { PIDGIN_STOCK_STATUS_CHAT, "status", "chat.png", TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, NULL }, - { PIDGIN_STOCK_STATUS_INVISIBLE,"status", "invisible.png", TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL }, - { PIDGIN_STOCK_STATUS_XA, "status", "extended-away.png", TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, PIDGIN_STOCK_STATUS_XA_I }, - { PIDGIN_STOCK_STATUS_LOGIN, "status", "log-in.png", TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL }, - { PIDGIN_STOCK_STATUS_LOGOUT, "status", "log-out.png", TRUE, TRUE, TRUE, TRUE, FALSE, FALSE , NULL }, - { PIDGIN_STOCK_STATUS_OFFLINE, "status", "offline.png", TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, PIDGIN_STOCK_STATUS_OFFLINE_I }, - { PIDGIN_STOCK_STATUS_PERSON, "status", "person.png", TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL }, - { PIDGIN_STOCK_STATUS_MESSAGE, "toolbar", "message-new.png",TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, + { PIDGIN_STOCK_STATUS_AVAILABLE, "status", "available.png", TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, PIDGIN_STOCK_STATUS_AVAILABLE_I }, + { PIDGIN_STOCK_STATUS_AWAY, "status", "away.png", TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, PIDGIN_STOCK_STATUS_AWAY_I }, + { PIDGIN_STOCK_STATUS_BUSY, "status", "busy.png", TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, PIDGIN_STOCK_STATUS_BUSY_I }, + { PIDGIN_STOCK_STATUS_CHAT, "status", "chat.png", TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL }, + { PIDGIN_STOCK_STATUS_INVISIBLE,"status", "invisible.png", TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL }, + { PIDGIN_STOCK_STATUS_XA, "status", "extended-away.png", TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, PIDGIN_STOCK_STATUS_XA_I }, + { PIDGIN_STOCK_STATUS_LOGIN, "status", "log-in.png", FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, NULL }, + { PIDGIN_STOCK_STATUS_LOGOUT, "status", "log-out.png", FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, NULL }, + { PIDGIN_STOCK_STATUS_OFFLINE, "status", "offline.png", TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, PIDGIN_STOCK_STATUS_OFFLINE_I }, + { PIDGIN_STOCK_STATUS_PERSON, "status", "person.png", TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL }, + { PIDGIN_STOCK_STATUS_MESSAGE, "toolbar", "message-new.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, - { PIDGIN_STOCK_STATUS_IGNORED, "emblems", "blocked.png", TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, - { PIDGIN_STOCK_STATUS_FOUNDER, "emblems", "founder.png", TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, - { PIDGIN_STOCK_STATUS_OPERATOR, "emblems", "operator.png", TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, - { PIDGIN_STOCK_STATUS_HALFOP, "emblems", "half-operator.png", TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, - { PIDGIN_STOCK_STATUS_VOICE, "emblems", "voice.png", TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, + { PIDGIN_STOCK_STATUS_IGNORED, "emblems", "blocked.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, + { PIDGIN_STOCK_STATUS_FOUNDER, "emblems", "founder.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, + { PIDGIN_STOCK_STATUS_OPERATOR, "emblems", "operator.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, + { PIDGIN_STOCK_STATUS_HALFOP, "emblems", "half-operator.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, + { PIDGIN_STOCK_STATUS_VOICE, "emblems", "voice.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, - { PIDGIN_STOCK_DIALOG_AUTH, "dialogs", "auth.png", TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, NULL }, - { PIDGIN_STOCK_DIALOG_COOL, "dialogs", "cool.png", FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, NULL }, - { PIDGIN_STOCK_DIALOG_ERROR, "dialogs", "error.png", TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, NULL }, - { PIDGIN_STOCK_DIALOG_INFO, "dialogs", "info.png", TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, NULL }, - { PIDGIN_STOCK_DIALOG_MAIL, "dialogs", "mail.png", TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, NULL }, - { PIDGIN_STOCK_DIALOG_QUESTION, "dialogs", "question.png", TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, NULL }, - { PIDGIN_STOCK_DIALOG_WARNING, "dialogs", "warning.png", FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, NULL }, + { PIDGIN_STOCK_DIALOG_AUTH, "dialogs", "auth.png", FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, NULL }, + { PIDGIN_STOCK_DIALOG_COOL, "dialogs", "cool.png", FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, NULL }, + { PIDGIN_STOCK_DIALOG_ERROR, "dialogs", "error.png", FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, NULL }, + { PIDGIN_STOCK_DIALOG_INFO, "dialogs", "info.png", FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, NULL }, + { PIDGIN_STOCK_DIALOG_MAIL, "dialogs", "mail.png", FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, NULL }, + { PIDGIN_STOCK_DIALOG_QUESTION, "dialogs", "question.png", FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, NULL }, + { PIDGIN_STOCK_DIALOG_WARNING, "dialogs", "warning.png", FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, NULL }, - { PIDGIN_STOCK_ANIMATION_CONNECT0, "animations", "connect0.png",TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, - { PIDGIN_STOCK_ANIMATION_CONNECT1, "animations", "connect1.png",TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, - { PIDGIN_STOCK_ANIMATION_CONNECT2, "animations", "connect2.png",TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, - { PIDGIN_STOCK_ANIMATION_CONNECT3, "animations", "connect3.png",TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, - { PIDGIN_STOCK_ANIMATION_CONNECT4, "animations", "connect4.png",TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, - { PIDGIN_STOCK_ANIMATION_CONNECT5, "animations", "connect5.png",TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, - { PIDGIN_STOCK_ANIMATION_CONNECT6, "animations", "connect6.png",TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, - { PIDGIN_STOCK_ANIMATION_CONNECT7, "animations", "connect7.png",TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, - { PIDGIN_STOCK_ANIMATION_CONNECT8, "animations", "connect8.png",TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, - { PIDGIN_STOCK_ANIMATION_TYPING0, "animations", "typing0.png",TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, - { PIDGIN_STOCK_ANIMATION_TYPING1, "animations", "typing1.png",TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, - { PIDGIN_STOCK_ANIMATION_TYPING2, "animations", "typing2.png",TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, - { PIDGIN_STOCK_ANIMATION_TYPING3, "animations", "typing3.png",TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, - { PIDGIN_STOCK_ANIMATION_TYPING4, "animations", "typing4.png",TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, - { PIDGIN_STOCK_ANIMATION_TYPING5, "animations", "typing5.png",TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, + { PIDGIN_STOCK_ANIMATION_CONNECT0, "animations", "connect0.png",FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, + { PIDGIN_STOCK_ANIMATION_CONNECT1, "animations", "connect1.png",FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, + { PIDGIN_STOCK_ANIMATION_CONNECT2, "animations", "connect2.png",FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, + { PIDGIN_STOCK_ANIMATION_CONNECT3, "animations", "connect3.png",FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, + { PIDGIN_STOCK_ANIMATION_CONNECT4, "animations", "connect4.png",FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, + { PIDGIN_STOCK_ANIMATION_CONNECT5, "animations", "connect5.png",FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, + { PIDGIN_STOCK_ANIMATION_CONNECT6, "animations", "connect6.png",FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, + { PIDGIN_STOCK_ANIMATION_CONNECT7, "animations", "connect7.png",FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, + { PIDGIN_STOCK_ANIMATION_CONNECT8, "animations", "connect8.png",FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, + { PIDGIN_STOCK_ANIMATION_TYPING0, "animations", "typing0.png",FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, + { PIDGIN_STOCK_ANIMATION_TYPING1, "animations", "typing1.png",FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, + { PIDGIN_STOCK_ANIMATION_TYPING2, "animations", "typing2.png",FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, + { PIDGIN_STOCK_ANIMATION_TYPING3, "animations", "typing3.png",FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, + { PIDGIN_STOCK_ANIMATION_TYPING4, "animations", "typing4.png",FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, + { PIDGIN_STOCK_ANIMATION_TYPING5, "animations", "typing5.png",FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, - { PIDGIN_STOCK_TOOLBAR_ACCOUNTS, "toolbar", "accounts.png", TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, - { PIDGIN_STOCK_TOOLBAR_BGCOLOR, "toolbar", "change-bgcolor.png", TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, - { PIDGIN_STOCK_TOOLBAR_BLOCK, "emblems", "blocked.png", TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, - { PIDGIN_STOCK_TOOLBAR_FGCOLOR, "toolbar", "change-fgcolor.png", TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, - { PIDGIN_STOCK_TOOLBAR_SMILEY, "toolbar", "emote-select.png", TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, - { PIDGIN_STOCK_TOOLBAR_FONT_FACE, "toolbar", "font-face.png", TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, - { PIDGIN_STOCK_TOOLBAR_TEXT_SMALLER, "toolbar", "font-size-down.png", TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, - { PIDGIN_STOCK_TOOLBAR_TEXT_LARGER, "toolbar", "font-size-up.png", TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, - { PIDGIN_STOCK_TOOLBAR_INSERT, "toolbar", "insert.png", TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, - { PIDGIN_STOCK_TOOLBAR_INSERT_IMAGE, "toolbar", "insert-image.png", TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, - { PIDGIN_STOCK_TOOLBAR_INSERT_LINK, "toolbar", "insert-link.png", TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, - { PIDGIN_STOCK_TOOLBAR_MESSAGE_NEW, "toolbar", "message-new.png", TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, - { PIDGIN_STOCK_TOOLBAR_PENDING, "toolbar", "message-new.png", TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, - { PIDGIN_STOCK_TOOLBAR_PLUGINS, "toolbar", "plugins.png", TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, - { PIDGIN_STOCK_TOOLBAR_TYPING, "toolbar", "typing.png", TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, - { PIDGIN_STOCK_TOOLBAR_UNBLOCK, "toolbar", "unblock.png", TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, - { PIDGIN_STOCK_TOOLBAR_SELECT_AVATAR, "toolbar", "select-avatar.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, NULL }, - { PIDGIN_STOCK_TOOLBAR_SEND_FILE, "toolbar", "send-file.png", TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, + { PIDGIN_STOCK_TOOLBAR_ACCOUNTS, "toolbar", "accounts.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, + { PIDGIN_STOCK_TOOLBAR_BGCOLOR, "toolbar", "change-bgcolor.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, + { PIDGIN_STOCK_TOOLBAR_BLOCK, "emblems", "blocked.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, + { PIDGIN_STOCK_TOOLBAR_FGCOLOR, "toolbar", "change-fgcolor.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, + { PIDGIN_STOCK_TOOLBAR_SMILEY, "toolbar", "emote-select.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, + { PIDGIN_STOCK_TOOLBAR_FONT_FACE, "toolbar", "font-face.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, + { PIDGIN_STOCK_TOOLBAR_TEXT_SMALLER, "toolbar", "font-size-down.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, + { PIDGIN_STOCK_TOOLBAR_TEXT_LARGER, "toolbar", "font-size-up.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, + { PIDGIN_STOCK_TOOLBAR_INSERT, "toolbar", "insert.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, + { PIDGIN_STOCK_TOOLBAR_INSERT_IMAGE, "toolbar", "insert-image.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, + { PIDGIN_STOCK_TOOLBAR_INSERT_LINK, "toolbar", "insert-link.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, + { PIDGIN_STOCK_TOOLBAR_MESSAGE_NEW, "toolbar", "message-new.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, + { PIDGIN_STOCK_TOOLBAR_PENDING, "toolbar", "message-new.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, + { PIDGIN_STOCK_TOOLBAR_PLUGINS, "toolbar", "plugins.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, + { PIDGIN_STOCK_TOOLBAR_TYPING, "toolbar", "typing.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, + { PIDGIN_STOCK_TOOLBAR_UNBLOCK, "toolbar", "unblock.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, + { PIDGIN_STOCK_TOOLBAR_SELECT_AVATAR, "toolbar", "select-avatar.png", FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, NULL }, + { PIDGIN_STOCK_TOOLBAR_SEND_FILE, "toolbar", "send-file.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, - { PIDGIN_STOCK_TRAY_AVAILABLE, "tray", "tray-online.png", TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL }, - { PIDGIN_STOCK_TRAY_INVISIBLE, "tray", "tray-invisible.png", TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL }, - { PIDGIN_STOCK_TRAY_AWAY, "tray", "tray-away.png", TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL }, - { PIDGIN_STOCK_TRAY_BUSY, "tray", "tray-busy.png", TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL }, - { PIDGIN_STOCK_TRAY_XA, "tray", "tray-extended-away.png", TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL }, - { PIDGIN_STOCK_TRAY_OFFLINE, "tray", "tray-offline.png", TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL }, - { PIDGIN_STOCK_TRAY_CONNECT, "tray", "tray-connecting.png", TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL }, - { PIDGIN_STOCK_TRAY_PENDING, "tray", "tray-new-im.png", TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL }, - { PIDGIN_STOCK_TRAY_EMAIL, "tray", "tray-message.png", TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL } + { PIDGIN_STOCK_TRAY_AVAILABLE, "tray", "tray-online.png", FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL }, + { PIDGIN_STOCK_TRAY_INVISIBLE, "tray", "tray-invisible.png", FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL }, + { PIDGIN_STOCK_TRAY_AWAY, "tray", "tray-away.png", FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL }, + { PIDGIN_STOCK_TRAY_BUSY, "tray", "tray-busy.png", FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL }, + { PIDGIN_STOCK_TRAY_XA, "tray", "tray-extended-away.png", FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL }, + { PIDGIN_STOCK_TRAY_OFFLINE, "tray", "tray-offline.png", FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL }, + { PIDGIN_STOCK_TRAY_CONNECT, "tray", "tray-connecting.png", FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL }, + { PIDGIN_STOCK_TRAY_PENDING, "tray", "tray-new-im.png", FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL }, + { PIDGIN_STOCK_TRAY_EMAIL, "tray", "tray-message.png", FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL } }; static gchar * @@ -339,7 +340,7 @@ GtkIconFactory *icon_factory; size_t i; GtkWidget *win; - GtkIconSize extra_small, small, medium, large, huge; + GtkIconSize microscopic, extra_small, small, medium, large, huge; if (stock_initted) return; @@ -394,6 +395,8 @@ } /* register custom icon sizes */ + + microscopic = gtk_icon_size_register(PIDGIN_ICON_SIZE_TANGO_MICROSCOPIC, 11, 11); extra_small = gtk_icon_size_register(PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL, 16, 16); small = gtk_icon_size_register(PIDGIN_ICON_SIZE_TANGO_SMALL, 22, 22); medium = gtk_icon_size_register(PIDGIN_ICON_SIZE_TANGO_MEDIUM, 32, 32); @@ -405,6 +408,10 @@ GtkIconSet *iconset; iconset = gtk_icon_set_new(); + if (sized_stock_icons[i].microscopic) + add_sized_icon(iconset, microscopic, + sized_stock_icons[i].dir, sized_stock_icons[i].rtl, + "11", sized_stock_icons[i].filename); if (sized_stock_icons[i].extra_small) add_sized_icon(iconset, extra_small, sized_stock_icons[i].dir, sized_stock_icons[i].rtl, @@ -431,6 +438,10 @@ if (sized_stock_icons[i].translucent_name) { iconset = gtk_icon_set_new(); + if (sized_stock_icons[i].microscopic) + add_translucent_sized_icon(iconset, microscopic, + sized_stock_icons[i].dir, sized_stock_icons[i].rtl, + "11", sized_stock_icons[i].filename); if (sized_stock_icons[i].extra_small) add_translucent_sized_icon(iconset, extra_small, sized_stock_icons[i].dir, sized_stock_icons[i].rtl,
--- a/pidgin/pidginstock.h Fri Aug 17 02:26:42 2007 +0000 +++ b/pidgin/pidginstock.h Mon Aug 27 21:59:11 2007 +0000 @@ -145,6 +145,7 @@ /** * For using icons that aren't one of the default GTK_ICON_SIZEs */ +#define PIDGIN_ICON_SIZE_TANGO_MICROSCOPIC "pidgin-icon-size-tango-microscopic" #define PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL "pidgin-icon-size-tango-extra-small" #define PIDGIN_ICON_SIZE_TANGO_SMALL "pidgin-icon-size-tango-small" #define PIDGIN_ICON_SIZE_TANGO_MEDIUM "pidgin-icon-size-tango-medium"
--- a/pidgin/pixmaps/emotes/default/24/Makefile.am Fri Aug 17 02:26:42 2007 +0000 +++ b/pidgin/pixmaps/emotes/default/24/Makefile.am Mon Aug 27 21:59:11 2007 +0000 @@ -42,6 +42,7 @@ curl-lip.png \ curse.png \ cute.png \ + cyclops.png \ dance.png \ dazed.png \ desire.png \ @@ -94,7 +95,7 @@ love-over.png \ love.png \ lying.png \ - madtongue.png \ + mad-tongue.png \ mail.png \ male-fighter1.png \ male-fighter2.png \
--- a/pidgin/pixmaps/emotes/default/24/default.theme.in Fri Aug 17 02:26:42 2007 +0000 +++ b/pidgin/pixmaps/emotes/default/24/default.theme.in Mon Aug 27 21:59:11 2007 +0000 @@ -1,5 +1,5 @@ -Name=Default -Description=Pidgin smileys +_Name=Default +_Description=Pidgin smileys Icon=wink.png Author=Hylke Bons @@ -24,7 +24,7 @@ shout.png >:o >:O ! skywalker.png C:-) c:-) C:) c:) ! monkey.png :-(|) :(|) - +! cyclops.png O-) o-) # Following AIM 6.1 [AIM]
--- a/pidgin/pixmaps/emotes/default/24/scalable/Makefile.am Fri Aug 17 02:26:42 2007 +0000 +++ b/pidgin/pixmaps/emotes/default/24/scalable/Makefile.am Mon Aug 27 21:59:11 2007 +0000 @@ -40,6 +40,7 @@ curl-lip.svg \ curse.svg \ cute.svg \ + cyclops.svg \ dance.svg \ dazed.svg \ desire.svg \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pidgin/pixmaps/emotes/default/24/scalable/cyclops.svg Mon Aug 27 21:59:11 2007 +0000 @@ -0,0 +1,440 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://web.resource.org/cc/" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="24" + height="24" + id="svg2" + sodipodi:version="0.32" + inkscape:version="0.45.1" + version="1.0" + sodipodi:docbase="/home/hbons/Desktop" + sodipodi:docname="cyclops.svg" + inkscape:export-filename="/home/hbons/Desktop/cyclops.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" + inkscape:output_extension="org.inkscape.output.svg.inkscape"> + <defs + id="defs4"> + <linearGradient + inkscape:collect="always" + id="linearGradient3183"> + <stop + style="stop-color:#ef2929;stop-opacity:1;" + offset="0" + id="stop3185" /> + <stop + style="stop-color:#ef2929;stop-opacity:0;" + offset="1" + id="stop3187" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + id="linearGradient3104"> + <stop + style="stop-color:#eeeeec;stop-opacity:1;" + offset="0" + id="stop3106" /> + <stop + style="stop-color:#eeeeec;stop-opacity:0;" + offset="1" + id="stop3108" /> + </linearGradient> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3104" + id="radialGradient3114" + cx="8.3343515" + cy="14.186539" + fx="8.3343515" + fy="14.186539" + r="9.975256" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-0.9327,0.932656,-0.947494,-0.947449,33.02126,11.96667)" /> + <filter + inkscape:collect="always" + x="-0.27879594" + width="1.5575919" + y="-0.78248726" + height="2.5649745" + id="filter3405"> + <feGaussianBlur + inkscape:collect="always" + stdDeviation="1.5438116" + id="feGaussianBlur3407" /> + </filter> + <radialGradient + r="9.975256" + fy="18.005522" + fx="8.7359829" + cy="18.005522" + cx="8.7359829" + gradientTransform="matrix(-1.3308754,1.3308124,-1.4391023,-1.4390341,45.391773,16.51952)" + gradientUnits="userSpaceOnUse" + id="radialGradient2247" + xlink:href="#linearGradient3104" + inkscape:collect="always" /> + <linearGradient + inkscape:collect="always" + id="linearGradient3263"> + <stop + style="stop-color:#555753;stop-opacity:1;" + offset="0" + id="stop3265" /> + <stop + style="stop-color:#555753;stop-opacity:0;" + offset="1" + id="stop3267" /> + </linearGradient> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3104" + id="radialGradient2216" + cx="8.3343515" + cy="14.186539" + fx="8.3343515" + fy="14.186539" + r="9.975256" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-0.9327,0.932656,-0.947494,-0.947449,33.02126,11.96667)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3263" + id="linearGradient3269" + x1="12.845698" + y1="16.037401" + x2="10.698112" + y2="15.449714" + gradientUnits="userSpaceOnUse" /> + <radialGradient + r="9.975256" + fy="18.005522" + fx="8.7359829" + cy="18.005522" + cx="8.7359829" + gradientTransform="matrix(-1.3308754,1.3308124,-1.4391023,-1.4390341,45.391773,16.51952)" + gradientUnits="userSpaceOnUse" + id="radialGradient3191" + xlink:href="#linearGradient3104" + inkscape:collect="always" /> + <linearGradient + inkscape:collect="always" + id="linearGradient3150"> + <stop + style="stop-color:#2e3436;stop-opacity:1;" + offset="0" + id="stop3152" /> + <stop + style="stop-color:#2e3436;stop-opacity:0;" + offset="1" + id="stop3154" /> + </linearGradient> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3104" + id="radialGradient3175" + cx="8.3343515" + cy="14.186539" + fx="8.3343515" + fy="14.186539" + r="9.975256" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-0.9327,0.932656,-0.947494,-0.947449,33.02126,11.96667)" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3150" + id="radialGradient3156" + cx="10.748654" + cy="10.457643" + fx="10.748654" + fy="10.457643" + r="6.6449099" + gradientTransform="matrix(-0.842757,0,0,-0.35721,19.80716,14.19321)" + gradientUnits="userSpaceOnUse" /> + <radialGradient + gradientTransform="matrix(-1.3308754,1.3308124,-1.4391023,-1.4390341,45.391773,16.51952)" + gradientUnits="userSpaceOnUse" + r="9.975256" + fy="18.005522" + fx="8.7359829" + cy="18.005522" + cx="8.7359829" + id="radialGradient2214" + xlink:href="#linearGradient3104" + inkscape:collect="always" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3104" + id="radialGradient2255" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-0.9327,0.932656,-0.947494,-0.947449,33.02126,11.96667)" + cx="8.3343515" + cy="14.186539" + fx="8.3343515" + fy="14.186539" + r="9.975256" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3104" + id="radialGradient3313" + cx="8.3343515" + cy="14.186539" + fx="8.3343515" + fy="14.186539" + r="9.975256" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-0.9327,0.932656,-0.947494,-0.947449,33.02126,11.96667)" /> + <radialGradient + r="2.5781252" + fy="11.083743" + fx="17.911736" + cy="11.083743" + cx="17.911736" + gradientTransform="matrix(-1.591138,1.574803,-1.783257,-1.76495,68.854751,-2.8442229)" + gradientUnits="userSpaceOnUse" + id="radialGradient2259" + xlink:href="#linearGradient2382" + inkscape:collect="always" /> + <linearGradient + inkscape:collect="always" + id="linearGradient2867"> + <stop + style="stop-color:#d3d7cf;stop-opacity:1;" + offset="0" + id="stop2869" /> + <stop + style="stop-color:#d3d7cf;stop-opacity:0;" + offset="1" + id="stop2871" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + id="linearGradient2847"> + <stop + style="stop-color:#888a85;stop-opacity:1;" + offset="0" + id="stop2849" /> + <stop + style="stop-color:#888a85;stop-opacity:0;" + offset="1" + id="stop2851" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + id="linearGradient2382"> + <stop + style="stop-color:#d3d7cf;stop-opacity:1;" + offset="0" + id="stop2384" /> + <stop + style="stop-color:#d3d7cf;stop-opacity:0;" + offset="1" + id="stop2386" /> + </linearGradient> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3104" + id="radialGradient2230" + cx="8.3343515" + cy="14.186539" + fx="8.3343515" + fy="14.186539" + r="9.975256" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-0.9327,0.932656,-0.947494,-0.947449,33.02126,11.96667)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2847" + id="linearGradient2853" + x1="12.5" + y1="18.202251" + x2="12.746171" + y2="20.761486" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2867" + id="linearGradient2873" + x1="12.720216" + y1="20.952612" + x2="12.720216" + y2="17.682426" + gradientUnits="userSpaceOnUse" /> + <radialGradient + gradientTransform="matrix(-0.9327,0.932656,-0.947494,-0.947449,33.02126,11.96667)" + gradientUnits="userSpaceOnUse" + r="9.975256" + fy="14.186539" + fx="8.3343515" + cy="14.186539" + cx="8.3343515" + id="radialGradient2303" + xlink:href="#linearGradient3104" + inkscape:collect="always" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3104" + id="radialGradient2349" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-0.9327,0.932656,-0.947494,-0.947449,33.02126,11.96667)" + cx="8.3343515" + cy="14.186539" + fx="8.3343515" + fy="14.186539" + r="9.975256" /> + <radialGradient + gradientTransform="matrix(-0.9327,0.932656,-0.947494,-0.947449,33.02126,11.96667)" + gradientUnits="userSpaceOnUse" + r="9.975256" + fy="14.186539" + fx="8.3343515" + cy="14.186539" + cx="8.3343515" + id="radialGradient2233" + xlink:href="#linearGradient3104" + inkscape:collect="always" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3104" + id="radialGradient2264" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-0.9327,0.932656,-0.947494,-0.947449,33.02126,11.96667)" + cx="8.3343515" + cy="14.186539" + fx="8.3343515" + fy="14.186539" + r="9.975256" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3183" + id="linearGradient3189" + x1="12" + y1="18.630589" + x2="12" + y2="16.200893" + gradientUnits="userSpaceOnUse" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="22.4" + inkscape:cx="26.058673" + inkscape:cy="12.633455" + inkscape:document-units="px" + inkscape:current-layer="layer1" + showgrid="true" + fill="#fce94f" + inkscape:window-width="1440" + inkscape:window-height="847" + inkscape:window-x="0" + inkscape:window-y="0" /> + <metadata + id="metadata7"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1"> + <path + sodipodi:type="arc" + style="opacity:0.64044944;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter3405)" + id="path3140" + sodipodi:cx="10.748654" + sodipodi:cy="10.457643" + sodipodi:rx="6.6449099" + sodipodi:ry="2.3675451" + d="M 17.393564 10.457643 A 6.6449099 2.3675451 0 1 1 4.1037445,10.457643 A 6.6449099 2.3675451 0 1 1 17.393564 10.457643 z" + transform="matrix(1.2039291,0,0,1.055946,-0.9406174,8.4572942)" /> + <path + sodipodi:type="arc" + style="opacity:1;fill:#edd400;fill-opacity:1;stroke:#cc6400;stroke-width:1.05276573;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="path1307" + sodipodi:cx="11.806158" + sodipodi:cy="10.983024" + sodipodi:rx="9.975256" + sodipodi:ry="9.975256" + d="M 21.781414 10.983024 A 9.975256 9.975256 0 1 1 1.8309021,10.983024 A 9.975256 9.975256 0 1 1 21.781414 10.983024 z" + transform="matrix(0.952236,0,0,0.952236,0.757713,1.541608)" /> + <path + sodipodi:type="arc" + style="opacity:0.79545455;fill:url(#radialGradient3114);fill-opacity:1.0;stroke:none;stroke-width:1.05274069;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="path3102" + sodipodi:cx="11.806158" + sodipodi:cy="10.983024" + sodipodi:rx="9.975256" + sodipodi:ry="9.975256" + d="M 21.781414 10.983024 A 9.975256 9.975256 0 1 1 1.8309021,10.983024 A 9.975256 9.975256 0 1 1 21.781414 10.983024 z" + transform="matrix(0.8019,0,0,0.801938,2.532654,3.191833)" /> + <path + sodipodi:type="arc" + style="opacity:0.64044944;fill:none;fill-opacity:1.0;stroke:#ffffff;stroke-width:1.17343897;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="path2184" + sodipodi:cx="11.806158" + sodipodi:cy="10.983024" + sodipodi:rx="9.975256" + sodipodi:ry="9.975256" + d="M 21.781414 10.983024 A 9.975256 9.975256 0 1 1 1.8309021,10.983024 A 9.975256 9.975256 0 1 1 21.781414 10.983024 z" + transform="matrix(0.852176,0,0,0.852216,1.93909,2.639626)" /> + <path + style="fill:#eeeeec;fill-opacity:1;stroke:#fea523;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1" + d="M 16.500001,10.000001 C 16.500001,11.932 14.484003,13.5 12,13.5 C 9.5160001,13.5 7.5000004,11.932 7.5000004,10.000001 C 7.5000004,8.0680005 9.5160001,6.5000003 12,6.5000003 C 14.484003,6.5000003 16.500001,8.0680005 16.500001,10.000001 z " + id="path3154" /> + <path + sodipodi:type="arc" + style="opacity:1;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:0.98640186;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="path2172" + sodipodi:cx="9.7069349" + sodipodi:cy="9.6526775" + sodipodi:rx="1.0259361" + sodipodi:ry="1.9413869" + d="M 10.732871 9.6526775 A 1.0259361 1.9413869 0 1 1 8.6809988,9.6526775 A 1.0259361 1.9413869 0 1 1 10.732871 9.6526775 z" + transform="matrix(1.9494392,0,0,1.0301914,-6.9230792,5.5894428e-2)" /> + <path + style="opacity:1;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 17,14 C 16.413519,16.283765 14.403819,19.026786 12,19.026786 C 9.5961819,19.026786 7.5864809,16.283765 6.9999999,14 C 8.0537469,15.478811 9.9044429,17.044402 12,17.044402 C 14.095556,17.044403 15.946253,15.478811 17,14 z " + id="path2186" + sodipodi:nodetypes="cscsc" /> + <path + sodipodi:type="arc" + style="opacity:0.64044949;fill:none;fill-opacity:1;stroke:#f57900;stroke-width:0.49971181;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="path2261" + sodipodi:cx="8.3258924" + sodipodi:cy="9.2232141" + sodipodi:rx="1.2276785" + sodipodi:ry="1.7410715" + d="M 7.2133909,8.4869402 A 1.2276785,1.7410715 0 0 1 9.288462,8.1425499" + transform="matrix(-3.3001466,0.1859839,0.4412458,1.1885988,35.56042,-5.9291419)" + sodipodi:start="3.5782199" + sodipodi:end="5.6135639" + sodipodi:open="true" /> + <path + sodipodi:type="arc" + style="opacity:1;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:0.98640186;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="path2206" + sodipodi:cx="9.7069349" + sodipodi:cy="9.6526775" + sodipodi:rx="1.0259361" + sodipodi:ry="1.9413869" + d="M 10.732871 9.6526775 A 1.0259361 1.9413869 0 1 1 8.6809988,9.6526775 A 1.0259361 1.9413869 0 1 1 10.732871 9.6526775 z" + transform="matrix(0.9747193,0,0,0.5150956,1.5384634,5.0279481)" /> + </g> +</svg>
--- a/pidgin/pixmaps/protocols/16/Makefile.am Fri Aug 17 02:26:42 2007 +0000 +++ b/pidgin/pixmaps/protocols/16/Makefile.am Mon Aug 27 21:59:11 2007 +0000 @@ -10,6 +10,7 @@ jabber.png \ meanwhile.png \ msn.png \ + myspace.png \ qq.png \ silc.png \ simple.png \
--- a/pidgin/pixmaps/protocols/22/Makefile.am Fri Aug 17 02:26:42 2007 +0000 +++ b/pidgin/pixmaps/protocols/22/Makefile.am Mon Aug 27 21:59:11 2007 +0000 @@ -10,6 +10,7 @@ jabber.png \ meanwhile.png \ msn.png \ + myspace.png \ qq.png \ silc.png \ simple.png \
--- a/pidgin/pixmaps/protocols/48/Makefile.am Fri Aug 17 02:26:42 2007 +0000 +++ b/pidgin/pixmaps/protocols/48/Makefile.am Mon Aug 27 21:59:11 2007 +0000 @@ -9,6 +9,7 @@ jabber.png \ meanwhile.png \ msn.png \ + myspace.png \ qq.png \ silc.png \ simple.png \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pidgin/pixmaps/status/11/Makefile.am Mon Aug 27 21:59:11 2007 +0000 @@ -0,0 +1,15 @@ +SUBDIRS = scalable rtl + +EXTRA_DIST = available.png \ + away.png \ + busy.png \ + chat.png \ + extended-away.png \ + invisible.png \ + offline.png \ + person.png + +pidginstatuspixdir = $(datadir)/pixmaps/pidgin/status/11 + +pidginstatuspix_DATA = $(EXTRA_DIST) +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pidgin/pixmaps/status/11/Makefile.mingw Mon Aug 27 21:59:11 2007 +0000 @@ -0,0 +1,20 @@ +# +# Makefile.mingw +# +# Description: Makefile for win32 (mingw) version of Pidgin pixmaps +# + +PIDGIN_TREE_TOP := ../../../.. +include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak + +datadir = $(PIDGIN_INSTALL_DIR) +include ./Makefile.am + +.PHONY: install + +install: + if test '$(pidginstatuspix_DATA)'; then \ + mkdir -p $(pidginstatuspixdir); \ + cp $(pidginstatuspix_DATA) $(pidginstatuspixdir); \ + fi; +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pidgin/pixmaps/status/11/rtl/Makefile.am Mon Aug 27 21:59:11 2007 +0000 @@ -0,0 +1,6 @@ +EXTRA_DIST = extended-away.png + +pidginstatuspixdir = $(datadir)/pixmaps/pidgin/status/11/rtl + +pidginstatuspix_DATA = $(EXTRA_DIST) +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pidgin/pixmaps/status/11/rtl/Makefile.mingw Mon Aug 27 21:59:11 2007 +0000 @@ -0,0 +1,20 @@ +# +# Makefile.mingw +# +# Description: Makefile for win32 (mingw) version of Pidgin pixmaps +# + +PIDGIN_TREE_TOP := ../../../../.. +include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak + +datadir = $(PIDGIN_INSTALL_DIR) +include ./Makefile.am + +.PHONY: install + +install: + if test '$(pidginstatuspix_DATA)'; then \ + mkdir -p $(pidginstatuspixdir); \ + cp $(pidginstatuspix_DATA) $(pidginstatuspixdir); \ + fi; +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pidgin/pixmaps/status/11/scalable/Makefile.am Mon Aug 27 21:59:11 2007 +0000 @@ -0,0 +1,8 @@ +EXTRA_DIST = available.svg \ + away.svg \ + busy.svg \ + chat.svg \ + extended-away.svg \ + invisible.svg \ + offline.svg \ + person.svg
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pidgin/pixmaps/status/11/scalable/available.svg Mon Aug 27 21:59:11 2007 +0000 @@ -0,0 +1,949 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://web.resource.org/cc/" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="11" + height="11" + id="svg1872" + sodipodi:version="0.32" + inkscape:version="0.45.1" + sodipodi:docbase="/home/hbons/Desktop/tabs" + sodipodi:docname="available.svg" + inkscape:output_extension="org.inkscape.output.svg.inkscape" + version="1.0" + inkscape:export-filename="/home/hbons/Desktop/tabs/available.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90"> + <defs + id="defs1874"> + <radialGradient + r="5" + fy="44" + fx="1" + cy="44" + cx="1" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + gradientUnits="userSpaceOnUse" + id="radialGradient7751" + xlink:href="#linearGradient2781" + inkscape:collect="always" /> + <linearGradient + id="linearGradient2781" + inkscape:collect="always"> + <stop + id="stop2783" + offset="0" + style="stop-color:black;stop-opacity:1;" /> + <stop + id="stop2785" + offset="1" + style="stop-color:black;stop-opacity:0;" /> + </linearGradient> + <radialGradient + r="5" + fy="44" + fx="1" + cy="44" + cx="1" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + gradientUnits="userSpaceOnUse" + id="radialGradient7753" + xlink:href="#linearGradient2781" + inkscape:collect="always" /> + <linearGradient + y2="40" + x2="21.875" + y1="48.000977" + x1="21.875" + gradientUnits="userSpaceOnUse" + id="linearGradient7755" + xlink:href="#linearGradient2804" + inkscape:collect="always" /> + <linearGradient + id="linearGradient2804"> + <stop + id="stop2806" + offset="0" + style="stop-color:black;stop-opacity:0;" /> + <stop + style="stop-color:black;stop-opacity:1;" + offset="0.5" + id="stop2812" /> + <stop + id="stop2808" + offset="1" + style="stop-color:black;stop-opacity:0;" /> + </linearGradient> + <linearGradient + id="linearGradient2851"> + <stop + id="stop2853" + offset="0" + style="stop-color:#73d216;stop-opacity:1;" /> + <stop + id="stop2855" + offset="1" + style="stop-color:#5ca911;stop-opacity:1;" /> + </linearGradient> + <linearGradient + id="linearGradient3149" + inkscape:collect="always"> + <stop + id="stop3151" + offset="0" + style="stop-color:#eeeeec;stop-opacity:1;" /> + <stop + id="stop3153" + offset="1" + style="stop-color:#eeeeec;stop-opacity:0;" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3149" + id="linearGradient1956" + gradientUnits="userSpaceOnUse" + x1="17.890068" + y1="2.2464287" + x2="17.890068" + y2="34.458977" + gradientTransform="matrix(0.287092,0,0,0.287092,5.363906,5.455062)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2851" + id="linearGradient1959" + gradientUnits="userSpaceOnUse" + x1="6.878005" + y1="11.789385" + x2="12.233074" + y2="27.77807" + gradientTransform="matrix(0.36035,0,0,0.358865,4.074001,4.193834)" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient1970" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient1972" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient1974" + gradientUnits="userSpaceOnUse" + x1="21.875" + y1="48.000977" + x2="21.875" + y2="40" /> + <linearGradient + inkscape:collect="always" + id="linearGradient2898"> + <stop + style="stop-color:white;stop-opacity:1;" + offset="0" + id="stop2900" /> + <stop + style="stop-color:white;stop-opacity:0;" + offset="1" + id="stop2902" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2851" + id="linearGradient4738" + gradientUnits="userSpaceOnUse" + x1="6.878005" + y1="11.789385" + x2="12.233074" + y2="27.77807" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3149" + id="linearGradient4740" + gradientUnits="userSpaceOnUse" + x1="15.498499" + y1="9.4211226" + x2="24.240097" + y2="36.603138" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3149" + id="linearGradient3044" + gradientUnits="userSpaceOnUse" + x1="17.890068" + y1="8.0617304" + x2="17.890068" + y2="40.032413" /> + <linearGradient + id="linearGradient3046"> + <stop + style="stop-color:#73d216;stop-opacity:1;" + offset="0" + id="stop3048" /> + <stop + style="stop-color:#5ca911;stop-opacity:1;" + offset="1" + id="stop3050" /> + </linearGradient> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3816" + id="radialGradient3064" + cx="31.112698" + cy="19.008621" + fx="31.112698" + fy="19.008621" + r="8.6620579" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.914124,0,0,1.631747,2.671799,-12.00863)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2851" + id="linearGradient3066" + x1="6.878005" + y1="11.789385" + x2="12.233074" + y2="27.77807" + gradientUnits="userSpaceOnUse" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2898" + id="radialGradient2904" + cx="4.8470273" + cy="6.9473476" + fx="4.8470273" + fy="6.9473476" + r="0.8078171" + gradientTransform="matrix(3.018423,0.664359,-1.388844,4.257661,-0.134567,-26.02469)" + gradientUnits="userSpaceOnUse" /> + <radialGradient + gradientUnits="userSpaceOnUse" + r="8.6620579" + fy="19.008621" + fx="31.112698" + cy="19.008621" + cx="31.112698" + id="radialGradient2818" + xlink:href="#linearGradient2812" + inkscape:collect="always" /> + <linearGradient + gradientUnits="userSpaceOnUse" + y2="11.024895" + x2="10.623409" + y1="2.7991772" + x1="4.5264969" + id="linearGradient2810" + xlink:href="#linearGradient2804" + inkscape:collect="always" /> + <linearGradient + gradientUnits="userSpaceOnUse" + y2="27.77807" + x2="12.233074" + y1="11.789385" + x1="6.878005" + id="linearGradient2963" + xlink:href="#linearGradient2851" + inkscape:collect="always" /> + <linearGradient + id="linearGradient2951"> + <stop + id="stop2953" + offset="0" + style="stop-color:#73d216;stop-opacity:1;" /> + <stop + id="stop2955" + offset="1" + style="stop-color:#5ca911;stop-opacity:1;" /> + </linearGradient> + <linearGradient + y2="40.032413" + x2="17.890068" + y1="8.0617304" + x1="17.890068" + gradientUnits="userSpaceOnUse" + id="linearGradient2949" + xlink:href="#linearGradient3149" + inkscape:collect="always" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2812" + id="radialGradient3005" + gradientUnits="userSpaceOnUse" + cx="31.112698" + cy="19.008621" + fx="31.112698" + fy="19.008621" + r="8.6620579" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient3007" + gradientUnits="userSpaceOnUse" + x1="4.5264969" + y1="2.7991772" + x2="10.623409" + y2="11.024895" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2812" + id="radialGradient3025" + gradientUnits="userSpaceOnUse" + cx="31.112698" + cy="19.008621" + fx="31.112698" + fy="19.008621" + r="8.6620579" /> + <linearGradient + gradientUnits="userSpaceOnUse" + y2="10.018044" + x2="10.043059" + y1="1.3319674" + x1="1.5769236" + id="linearGradient2995" + xlink:href="#linearGradient2989" + inkscape:collect="always" /> + <radialGradient + r="8.6620579" + fy="19.008621" + fx="31.112698" + cy="19.008621" + cx="31.112698" + gradientUnits="userSpaceOnUse" + id="radialGradient2084" + xlink:href="#linearGradient2812" + inkscape:collect="always" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3149" + id="linearGradient2046" + gradientUnits="userSpaceOnUse" + x1="17.890068" + y1="8.0617304" + x2="17.890068" + y2="40.032413" /> + <linearGradient + id="linearGradient2048"> + <stop + style="stop-color:#73d216;stop-opacity:1;" + offset="0" + id="stop2050" /> + <stop + style="stop-color:#5ca911;stop-opacity:1;" + offset="1" + id="stop2052" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2851" + id="linearGradient2060" + x1="6.878005" + y1="11.789385" + x2="12.233074" + y2="27.77807" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient2062" + x1="4.5264969" + y1="2.7991772" + x2="10.623409" + y2="11.024895" + gradientUnits="userSpaceOnUse" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2812" + id="radialGradient2064" + cx="31.112698" + cy="19.008621" + fx="31.112698" + fy="19.008621" + r="8.6620579" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + id="linearGradient2812"> + <stop + style="stop-color:#2e3436;stop-opacity:1;" + offset="0" + id="stop2814" /> + <stop + style="stop-color:#2e3436;stop-opacity:0;" + offset="1" + id="stop2816" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3149" + id="linearGradient2269" + gradientUnits="userSpaceOnUse" + x1="17.890068" + y1="8.0617304" + x2="17.890068" + y2="40.032413" /> + <linearGradient + id="linearGradient2055"> + <stop + style="stop-color:#73d216;stop-opacity:1;" + offset="0" + id="stop2057" /> + <stop + style="stop-color:#5ca911;stop-opacity:1;" + offset="1" + id="stop2059" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2851" + id="linearGradient2857" + x1="6.878005" + y1="11.789385" + x2="12.233074" + y2="27.77807" + gradientUnits="userSpaceOnUse" /> + <linearGradient + y2="14.895812" + x2="11.802028" + y1="1.9986149" + x1="11.802028" + gradientUnits="userSpaceOnUse" + id="linearGradient6606" + xlink:href="#linearGradient2225" + inkscape:collect="always" /> + <linearGradient + y2="48.674999" + x2="15.535398" + y1="1.8014067" + x1="15.535398" + gradientTransform="matrix(0.37378,0,0,0.375227,17.64779,15.86312)" + gradientUnits="userSpaceOnUse" + id="linearGradient2339" + xlink:href="#linearGradient2239" + inkscape:collect="always" /> + <linearGradient + y2="17.697369" + x2="11.226587" + y1="-5.4832759" + x1="11.226587" + gradientTransform="matrix(0.529942,0,0,0.53199,17.26643,15.48536)" + gradientUnits="userSpaceOnUse" + id="linearGradient2337" + xlink:href="#linearGradient2186" + inkscape:collect="always" /> + <linearGradient + y2="33.483475" + x2="15.522223" + y1="1.5657365" + x1="15.602553" + gradientTransform="matrix(0.371983,0,0,0.372254,2.539836,8.539528)" + gradientUnits="userSpaceOnUse" + id="linearGradient1357" + xlink:href="#linearGradient2239" + inkscape:collect="always" /> + <linearGradient + inkscape:collect="always" + id="linearGradient2239"> + <stop + style="stop-color:#ffffff;stop-opacity:1;" + offset="0" + id="stop2241" /> + <stop + style="stop-color:#ffffff;stop-opacity:0;" + offset="1" + id="stop2243" /> + </linearGradient> + <radialGradient + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1,0,0,0.626667,0,6.566431)" + r="6.3436799" + fy="17.588654" + fx="11.756953" + cy="17.588654" + cx="11.756953" + id="radialGradient2266" + xlink:href="#linearGradient2260" + inkscape:collect="always" /> + <radialGradient + r="7.003407" + fy="8.963316" + fx="9.9988937" + cy="8.963316" + cx="9.9988937" + gradientTransform="matrix(-2.522332,0,0,2.521765,40.1904,-21.80154)" + gradientUnits="userSpaceOnUse" + id="radialGradient2225" + xlink:href="#linearGradient2200" + inkscape:collect="always" /> + <radialGradient + r="7.003407" + fy="8.963316" + fx="9.9988937" + cy="8.963316" + cx="9.9988937" + gradientTransform="matrix(-2.522332,0,0,2.521765,40.1904,-21.83521)" + gradientUnits="userSpaceOnUse" + id="radialGradient2216" + xlink:href="#linearGradient2200" + inkscape:collect="always" /> + <linearGradient + id="linearGradient2200" + inkscape:collect="always"> + <stop + id="stop2202" + offset="0" + style="stop-color:#d3d7cf;stop-opacity:1;" /> + <stop + id="stop2204" + offset="1" + style="stop-color:#d3d7cf;stop-opacity:0;" /> + </linearGradient> + <radialGradient + gradientUnits="userSpaceOnUse" + r="8.6620579" + fy="19.008621" + fx="31.112698" + cy="19.008621" + cx="31.112698" + id="radialGradient3822" + xlink:href="#linearGradient3816" + inkscape:collect="always" /> + <linearGradient + id="linearGradient3816" + inkscape:collect="always"> + <stop + id="stop3818" + offset="0" + style="stop-color:#000000;stop-opacity:1;" /> + <stop + id="stop3820" + offset="1" + style="stop-color:#000000;stop-opacity:0;" /> + </linearGradient> + <linearGradient + id="linearGradient2260" + inkscape:collect="always"> + <stop + id="stop2262" + offset="0" + style="stop-color:#555753;stop-opacity:1;" /> + <stop + id="stop2264" + offset="1" + style="stop-color:#555753;stop-opacity:0;" /> + </linearGradient> + <linearGradient + gradientTransform="matrix(0.529942,0,0,0.53199,17.26643,15.48536)" + gradientUnits="userSpaceOnUse" + y2="17.697369" + x2="11.226587" + y1="-5.4832759" + x1="11.226587" + id="linearGradient2194" + xlink:href="#linearGradient2186" + inkscape:collect="always" /> + <linearGradient + id="linearGradient2186" + inkscape:collect="always"> + <stop + id="stop2188" + offset="0" + style="stop-color:#ffffff;stop-opacity:1;" /> + <stop + id="stop2190" + offset="1" + style="stop-color:#ffffff;stop-opacity:0;" /> + </linearGradient> + <linearGradient + gradientTransform="matrix(0.37378,0,0,0.375227,17.64779,15.86312)" + gradientUnits="userSpaceOnUse" + y2="48.674999" + x2="15.535398" + y1="1.8014067" + x1="15.535398" + id="linearGradient2245" + xlink:href="#linearGradient2239" + inkscape:collect="always" /> + <radialGradient + r="5" + fy="44" + fx="1" + cy="44" + cx="1" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + gradientUnits="userSpaceOnUse" + id="radialGradient2827" + xlink:href="#linearGradient2781" + inkscape:collect="always" /> + <radialGradient + r="5" + fy="44" + fx="1" + cy="44" + cx="1" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + gradientUnits="userSpaceOnUse" + id="radialGradient2829" + xlink:href="#linearGradient2781" + inkscape:collect="always" /> + <linearGradient + y2="40" + x2="21.875" + y1="48.000977" + x1="21.875" + gradientUnits="userSpaceOnUse" + id="linearGradient2831" + xlink:href="#linearGradient2804" + inkscape:collect="always" /> + <linearGradient + id="linearGradient2006"> + <stop + id="stop2008" + offset="0" + style="stop-color:black;stop-opacity:0;" /> + <stop + style="stop-color:black;stop-opacity:1;" + offset="0.5" + id="stop2010" /> + <stop + id="stop2012" + offset="1" + style="stop-color:black;stop-opacity:0;" /> + </linearGradient> + <linearGradient + y2="24.143761" + x2="27.2733" + y1="10.957423" + x1="35.003674" + gradientTransform="matrix(-0.977228,0,0,0.995878,50.60272,9.115637)" + gradientUnits="userSpaceOnUse" + id="linearGradient29443" + xlink:href="#linearGradient29418" + inkscape:collect="always" /> + <linearGradient + id="linearGradient29418"> + <stop + id="stop29420" + offset="0.0000000" + style="stop-color:#f5f5f5;stop-opacity:1.0000000;" /> + <stop + id="stop29422" + offset="1.0000000" + style="stop-color:#e9e9e9;stop-opacity:1.0000000;" /> + </linearGradient> + <linearGradient + id="linearGradient2225" + inkscape:collect="always"> + <stop + id="stop2227" + offset="0" + style="stop-color:#eeeeec;stop-opacity:1;" /> + <stop + id="stop2229" + offset="1" + style="stop-color:#eeeeec;stop-opacity:0;" /> + </linearGradient> + <linearGradient + id="linearGradient2989" + inkscape:collect="always"> + <stop + id="stop2991" + offset="0" + style="stop-color:#eeeeec;stop-opacity:1;" /> + <stop + id="stop2993" + offset="1" + style="stop-color:#eeeeec;stop-opacity:0;" /> + </linearGradient> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2812" + id="radialGradient2112" + gradientUnits="userSpaceOnUse" + cx="31.112698" + cy="19.008621" + fx="31.112698" + fy="19.008621" + r="8.6620579" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2851" + id="linearGradient2114" + gradientUnits="userSpaceOnUse" + x1="6.878005" + y1="11.789385" + x2="12.233074" + y2="27.77807" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3149" + id="linearGradient2116" + gradientUnits="userSpaceOnUse" + x1="15.498499" + y1="9.4211226" + x2="24.240097" + y2="36.603138" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3149" + id="linearGradient2119" + gradientUnits="userSpaceOnUse" + x1="15.498499" + y1="9.4211226" + x2="24.240097" + y2="36.603138" + gradientTransform="matrix(0.2512053,0,0,0.2512055,0.505914,0.5856851)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2851" + id="linearGradient2122" + gradientUnits="userSpaceOnUse" + x1="6.878005" + y1="11.789385" + x2="12.233074" + y2="27.77807" + gradientTransform="matrix(0.3229785,0,0,0.3229785,-0.7781054,-0.675548)" /> + <linearGradient + y2="40" + x2="21.875" + y1="48.000977" + x1="21.875" + gradientUnits="userSpaceOnUse" + id="linearGradient2567" + xlink:href="#linearGradient2804" + inkscape:collect="always" /> + <radialGradient + r="5" + fy="44" + fx="1" + cy="44" + cx="1" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + gradientUnits="userSpaceOnUse" + id="radialGradient2565" + xlink:href="#linearGradient2781" + inkscape:collect="always" /> + <radialGradient + r="5" + fy="44" + fx="1" + cy="44" + cx="1" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + gradientUnits="userSpaceOnUse" + id="radialGradient2563" + xlink:href="#linearGradient2781" + inkscape:collect="always" /> + <linearGradient + gradientTransform="matrix(0.36035,0,0,0.358865,4.074001,4.193834)" + y2="27.77807" + x2="12.233074" + y1="11.789385" + x1="6.878005" + gradientUnits="userSpaceOnUse" + id="linearGradient2561" + xlink:href="#linearGradient2851" + inkscape:collect="always" /> + <linearGradient + gradientTransform="matrix(0.287092,0,0,0.287092,5.363906,5.455062)" + y2="34.458977" + x2="17.890068" + y1="2.2464287" + x1="17.890068" + gradientUnits="userSpaceOnUse" + id="linearGradient2559" + xlink:href="#linearGradient3149" + inkscape:collect="always" /> + <linearGradient + id="linearGradient2547"> + <stop + style="stop-color:#73d216;stop-opacity:1;" + offset="0" + id="stop2549" /> + <stop + style="stop-color:#5ca911;stop-opacity:1;" + offset="1" + id="stop2551" /> + </linearGradient> + <linearGradient + id="linearGradient2539"> + <stop + style="stop-color:black;stop-opacity:0;" + offset="0" + id="stop2541" /> + <stop + id="stop2543" + offset="0.5" + style="stop-color:black;stop-opacity:1;" /> + <stop + style="stop-color:black;stop-opacity:0;" + offset="1" + id="stop2545" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient2537" + gradientUnits="userSpaceOnUse" + x1="21.875" + y1="48.000977" + x2="21.875" + y2="40" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient2535" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient2527" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <linearGradient + y2="17.697369" + x2="11.226587" + y1="-5.4832759" + x1="11.226587" + gradientTransform="matrix(-0.420408,0,0,0.420404,15.54691,5.457116)" + gradientUnits="userSpaceOnUse" + id="linearGradient2343" + xlink:href="#linearGradient2186" + inkscape:collect="always" /> + <linearGradient + y2="48.674999" + x2="15.535398" + y1="1.8014067" + x1="15.535398" + gradientTransform="matrix(-0.296523,0,0,0.296522,15.24437,5.75564)" + gradientUnits="userSpaceOnUse" + id="linearGradient2345" + xlink:href="#linearGradient2239" + inkscape:collect="always" /> + <radialGradient + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1,0,0,0.626667,0,6.566431)" + r="6.3436799" + fy="17.588654" + fx="11.756953" + cy="17.588654" + cx="11.756953" + id="radialGradient2511" + xlink:href="#linearGradient2260" + inkscape:collect="always" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2186" + id="linearGradient2583" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-0.420408,0,0,0.420404,23.273502,-1.8126311)" + x1="11.226587" + y1="-5.4832759" + x2="11.226587" + y2="17.697369" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient2585" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-0.296523,0,0,0.296522,22.970962,-1.5141071)" + x1="15.535398" + y1="1.8014067" + x2="15.535398" + y2="48.674999" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2851" + id="linearGradient2597" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.358865,0,0,0.358865,-0.920117,-0.8061648)" + x1="6.878005" + y1="11.789385" + x2="12.233074" + y2="27.77807" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3149" + id="linearGradient2599" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.2870918,0,0,0.287092,0.3639019,0.4550689)" + x1="15.498499" + y1="9.4211226" + x2="24.240097" + y2="36.603138" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="31.392433" + inkscape:cx="16.517697" + inkscape:cy="7.0793428" + inkscape:current-layer="layer1" + showgrid="true" + inkscape:grid-bbox="true" + inkscape:document-units="px" + inkscape:window-width="1440" + inkscape:window-height="847" + inkscape:window-x="0" + inkscape:window-y="0" + width="11px" + height="11px" /> + <metadata + id="metadata1877"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + id="layer1" + inkscape:label="Layer 1" + inkscape:groupmode="layer"> + <path + style="fill:url(#linearGradient2597);fill-opacity:1;fill-rule:evenodd;stroke:#306300;stroke-width:0.99999893;stroke-miterlimit:4;stroke-opacity:1" + d="M 10.500001,5.5000001 C 10.500001,8.2600001 8.2599999,10.500001 5.5000003,10.500001 C 2.7400002,10.500001 0.49999946,8.2600001 0.49999946,5.5000001 C 0.49999946,2.7399991 2.7400002,0.49999904 5.5000003,0.49999904 C 8.2599999,0.49999904 10.500001,2.7399991 10.500001,5.5000001 z " + id="path4331" /> + <path + style="opacity:0.6;fill:url(#linearGradient2599);fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:0.99999857;stroke-miterlimit:4;stroke-opacity:1" + d="M 9.5000009,5.5000008 C 9.5000009,7.7080002 7.7080009,9.5000009 5.5000004,9.5000009 C 3.2920001,9.5000009 1.4999993,7.7080002 1.4999993,5.5000008 C 1.4999993,3.2919993 3.2920001,1.4999992 5.5000004,1.4999992 C 7.7080009,1.4999992 9.5000009,3.2919993 9.5000009,5.5000008 z " + id="path4333" /> + </g> +</svg>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pidgin/pixmaps/status/11/scalable/away.svg Mon Aug 27 21:59:11 2007 +0000 @@ -0,0 +1,2123 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://web.resource.org/cc/" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="11" + height="11" + id="svg1872" + sodipodi:version="0.32" + inkscape:version="0.45.1" + sodipodi:docbase="/home/hbons/Desktop/tabs" + sodipodi:docname="away.svg" + inkscape:output_extension="org.inkscape.output.svg.inkscape" + version="1.0" + inkscape:export-filename="/home/hbons/Desktop/tabs/busy.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90"> + <defs + id="defs1874"> + <radialGradient + r="5" + fy="44" + fx="1" + cy="44" + cx="1" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + gradientUnits="userSpaceOnUse" + id="radialGradient7751" + xlink:href="#linearGradient2781" + inkscape:collect="always" /> + <linearGradient + id="linearGradient2781" + inkscape:collect="always"> + <stop + id="stop2783" + offset="0" + style="stop-color:black;stop-opacity:1;" /> + <stop + id="stop2785" + offset="1" + style="stop-color:black;stop-opacity:0;" /> + </linearGradient> + <radialGradient + r="5" + fy="44" + fx="1" + cy="44" + cx="1" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + gradientUnits="userSpaceOnUse" + id="radialGradient7753" + xlink:href="#linearGradient2781" + inkscape:collect="always" /> + <linearGradient + y2="40" + x2="21.875" + y1="48.000977" + x1="21.875" + gradientUnits="userSpaceOnUse" + id="linearGradient7755" + xlink:href="#linearGradient2804" + inkscape:collect="always" /> + <linearGradient + id="linearGradient2804"> + <stop + id="stop2806" + offset="0" + style="stop-color:black;stop-opacity:0;" /> + <stop + style="stop-color:black;stop-opacity:1;" + offset="0.5" + id="stop2812" /> + <stop + id="stop2808" + offset="1" + style="stop-color:black;stop-opacity:0;" /> + </linearGradient> + <linearGradient + id="linearGradient2851"> + <stop + id="stop2853" + offset="0" + style="stop-color:#73d216;stop-opacity:1;" /> + <stop + id="stop2855" + offset="1" + style="stop-color:#5ca911;stop-opacity:1;" /> + </linearGradient> + <linearGradient + id="linearGradient3149" + inkscape:collect="always"> + <stop + id="stop3151" + offset="0" + style="stop-color:#eeeeec;stop-opacity:1;" /> + <stop + id="stop3153" + offset="1" + style="stop-color:#eeeeec;stop-opacity:0;" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3149" + id="linearGradient1956" + gradientUnits="userSpaceOnUse" + x1="17.890068" + y1="2.2464287" + x2="17.890068" + y2="34.458977" + gradientTransform="matrix(0.287092,0,0,0.287092,5.363906,5.455062)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2851" + id="linearGradient1959" + gradientUnits="userSpaceOnUse" + x1="6.878005" + y1="11.789385" + x2="12.233074" + y2="27.77807" + gradientTransform="matrix(0.36035,0,0,0.358865,4.074001,4.193834)" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient1970" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient1972" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient1974" + gradientUnits="userSpaceOnUse" + x1="21.875" + y1="48.000977" + x2="21.875" + y2="40" /> + <linearGradient + inkscape:collect="always" + id="linearGradient2898"> + <stop + style="stop-color:white;stop-opacity:1;" + offset="0" + id="stop2900" /> + <stop + style="stop-color:white;stop-opacity:0;" + offset="1" + id="stop2902" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2851" + id="linearGradient4738" + gradientUnits="userSpaceOnUse" + x1="6.878005" + y1="11.789385" + x2="12.233074" + y2="27.77807" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3149" + id="linearGradient4740" + gradientUnits="userSpaceOnUse" + x1="15.498499" + y1="9.4211226" + x2="24.240097" + y2="36.603138" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3149" + id="linearGradient3044" + gradientUnits="userSpaceOnUse" + x1="17.890068" + y1="8.0617304" + x2="17.890068" + y2="40.032413" /> + <linearGradient + id="linearGradient3046"> + <stop + style="stop-color:#73d216;stop-opacity:1;" + offset="0" + id="stop3048" /> + <stop + style="stop-color:#5ca911;stop-opacity:1;" + offset="1" + id="stop3050" /> + </linearGradient> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3816" + id="radialGradient3064" + cx="31.112698" + cy="19.008621" + fx="31.112698" + fy="19.008621" + r="8.6620579" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.914124,0,0,1.631747,2.671799,-12.00863)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2851" + id="linearGradient3066" + x1="6.878005" + y1="11.789385" + x2="12.233074" + y2="27.77807" + gradientUnits="userSpaceOnUse" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2898" + id="radialGradient2904" + cx="4.8470273" + cy="6.9473476" + fx="4.8470273" + fy="6.9473476" + r="0.8078171" + gradientTransform="matrix(3.018423,0.664359,-1.388844,4.257661,-0.134567,-26.02469)" + gradientUnits="userSpaceOnUse" /> + <radialGradient + gradientUnits="userSpaceOnUse" + r="8.6620579" + fy="19.008621" + fx="31.112698" + cy="19.008621" + cx="31.112698" + id="radialGradient2818" + xlink:href="#linearGradient2812" + inkscape:collect="always" /> + <linearGradient + gradientUnits="userSpaceOnUse" + y2="11.024895" + x2="10.623409" + y1="2.7991772" + x1="4.5264969" + id="linearGradient2810" + xlink:href="#linearGradient2804" + inkscape:collect="always" /> + <linearGradient + gradientUnits="userSpaceOnUse" + y2="27.77807" + x2="12.233074" + y1="11.789385" + x1="6.878005" + id="linearGradient2963" + xlink:href="#linearGradient2851" + inkscape:collect="always" /> + <linearGradient + id="linearGradient2951"> + <stop + id="stop2953" + offset="0" + style="stop-color:#73d216;stop-opacity:1;" /> + <stop + id="stop2955" + offset="1" + style="stop-color:#5ca911;stop-opacity:1;" /> + </linearGradient> + <linearGradient + y2="40.032413" + x2="17.890068" + y1="8.0617304" + x1="17.890068" + gradientUnits="userSpaceOnUse" + id="linearGradient2949" + xlink:href="#linearGradient3149" + inkscape:collect="always" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2812" + id="radialGradient3005" + gradientUnits="userSpaceOnUse" + cx="31.112698" + cy="19.008621" + fx="31.112698" + fy="19.008621" + r="8.6620579" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient3007" + gradientUnits="userSpaceOnUse" + x1="4.5264969" + y1="2.7991772" + x2="10.623409" + y2="11.024895" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2812" + id="radialGradient3025" + gradientUnits="userSpaceOnUse" + cx="31.112698" + cy="19.008621" + fx="31.112698" + fy="19.008621" + r="8.6620579" /> + <linearGradient + gradientUnits="userSpaceOnUse" + y2="10.018044" + x2="10.043059" + y1="1.3319674" + x1="1.5769236" + id="linearGradient2995" + xlink:href="#linearGradient2989" + inkscape:collect="always" /> + <radialGradient + r="8.6620579" + fy="19.008621" + fx="31.112698" + cy="19.008621" + cx="31.112698" + gradientUnits="userSpaceOnUse" + id="radialGradient2084" + xlink:href="#linearGradient2812" + inkscape:collect="always" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3149" + id="linearGradient2046" + gradientUnits="userSpaceOnUse" + x1="17.890068" + y1="8.0617304" + x2="17.890068" + y2="40.032413" /> + <linearGradient + id="linearGradient2048"> + <stop + style="stop-color:#73d216;stop-opacity:1;" + offset="0" + id="stop2050" /> + <stop + style="stop-color:#5ca911;stop-opacity:1;" + offset="1" + id="stop2052" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2851" + id="linearGradient2060" + x1="6.878005" + y1="11.789385" + x2="12.233074" + y2="27.77807" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient2062" + x1="4.5264969" + y1="2.7991772" + x2="10.623409" + y2="11.024895" + gradientUnits="userSpaceOnUse" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2812" + id="radialGradient2064" + cx="31.112698" + cy="19.008621" + fx="31.112698" + fy="19.008621" + r="8.6620579" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + id="linearGradient2812"> + <stop + style="stop-color:#2e3436;stop-opacity:1;" + offset="0" + id="stop2814" /> + <stop + style="stop-color:#2e3436;stop-opacity:0;" + offset="1" + id="stop2816" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3149" + id="linearGradient2269" + gradientUnits="userSpaceOnUse" + x1="17.890068" + y1="8.0617304" + x2="17.890068" + y2="40.032413" /> + <linearGradient + id="linearGradient2055"> + <stop + style="stop-color:#73d216;stop-opacity:1;" + offset="0" + id="stop2057" /> + <stop + style="stop-color:#5ca911;stop-opacity:1;" + offset="1" + id="stop2059" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2851" + id="linearGradient2857" + x1="6.878005" + y1="11.789385" + x2="12.233074" + y2="27.77807" + gradientUnits="userSpaceOnUse" /> + <linearGradient + y2="14.895812" + x2="11.802028" + y1="1.9986149" + x1="11.802028" + gradientUnits="userSpaceOnUse" + id="linearGradient6606" + xlink:href="#linearGradient2225" + inkscape:collect="always" /> + <linearGradient + y2="48.674999" + x2="15.535398" + y1="1.8014067" + x1="15.535398" + gradientTransform="matrix(0.37378,0,0,0.375227,17.64779,15.86312)" + gradientUnits="userSpaceOnUse" + id="linearGradient2339" + xlink:href="#linearGradient2239" + inkscape:collect="always" /> + <linearGradient + y2="17.697369" + x2="11.226587" + y1="-5.4832759" + x1="11.226587" + gradientTransform="matrix(0.529942,0,0,0.53199,17.26643,15.48536)" + gradientUnits="userSpaceOnUse" + id="linearGradient2337" + xlink:href="#linearGradient2186" + inkscape:collect="always" /> + <linearGradient + y2="33.483475" + x2="15.522223" + y1="1.5657365" + x1="15.602553" + gradientTransform="matrix(0.371983,0,0,0.372254,2.539836,8.539528)" + gradientUnits="userSpaceOnUse" + id="linearGradient1357" + xlink:href="#linearGradient2239" + inkscape:collect="always" /> + <linearGradient + inkscape:collect="always" + id="linearGradient2239"> + <stop + style="stop-color:#ffffff;stop-opacity:1;" + offset="0" + id="stop2241" /> + <stop + style="stop-color:#ffffff;stop-opacity:0;" + offset="1" + id="stop2243" /> + </linearGradient> + <radialGradient + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1,0,0,0.626667,0,6.566431)" + r="6.3436799" + fy="17.588654" + fx="11.756953" + cy="17.588654" + cx="11.756953" + id="radialGradient2266" + xlink:href="#linearGradient2260" + inkscape:collect="always" /> + <radialGradient + r="7.003407" + fy="8.963316" + fx="9.9988937" + cy="8.963316" + cx="9.9988937" + gradientTransform="matrix(-2.522332,0,0,2.521765,40.1904,-21.80154)" + gradientUnits="userSpaceOnUse" + id="radialGradient2225" + xlink:href="#linearGradient2200" + inkscape:collect="always" /> + <radialGradient + r="7.003407" + fy="8.963316" + fx="9.9988937" + cy="8.963316" + cx="9.9988937" + gradientTransform="matrix(-2.522332,0,0,2.521765,40.1904,-21.83521)" + gradientUnits="userSpaceOnUse" + id="radialGradient2216" + xlink:href="#linearGradient2200" + inkscape:collect="always" /> + <linearGradient + id="linearGradient2200" + inkscape:collect="always"> + <stop + id="stop2202" + offset="0" + style="stop-color:#d3d7cf;stop-opacity:1;" /> + <stop + id="stop2204" + offset="1" + style="stop-color:#d3d7cf;stop-opacity:0;" /> + </linearGradient> + <radialGradient + gradientUnits="userSpaceOnUse" + r="8.6620579" + fy="19.008621" + fx="31.112698" + cy="19.008621" + cx="31.112698" + id="radialGradient3822" + xlink:href="#linearGradient3816" + inkscape:collect="always" /> + <linearGradient + id="linearGradient3816" + inkscape:collect="always"> + <stop + id="stop3818" + offset="0" + style="stop-color:#000000;stop-opacity:1;" /> + <stop + id="stop3820" + offset="1" + style="stop-color:#000000;stop-opacity:0;" /> + </linearGradient> + <linearGradient + id="linearGradient2260" + inkscape:collect="always"> + <stop + id="stop2262" + offset="0" + style="stop-color:#555753;stop-opacity:1;" /> + <stop + id="stop2264" + offset="1" + style="stop-color:#555753;stop-opacity:0;" /> + </linearGradient> + <linearGradient + gradientTransform="matrix(0.529942,0,0,0.53199,17.26643,15.48536)" + gradientUnits="userSpaceOnUse" + y2="17.697369" + x2="11.226587" + y1="-5.4832759" + x1="11.226587" + id="linearGradient2194" + xlink:href="#linearGradient2186" + inkscape:collect="always" /> + <linearGradient + id="linearGradient2186" + inkscape:collect="always"> + <stop + id="stop2188" + offset="0" + style="stop-color:#ffffff;stop-opacity:1;" /> + <stop + id="stop2190" + offset="1" + style="stop-color:#ffffff;stop-opacity:0;" /> + </linearGradient> + <linearGradient + gradientTransform="matrix(0.37378,0,0,0.375227,17.64779,15.86312)" + gradientUnits="userSpaceOnUse" + y2="48.674999" + x2="15.535398" + y1="1.8014067" + x1="15.535398" + id="linearGradient2245" + xlink:href="#linearGradient2239" + inkscape:collect="always" /> + <radialGradient + r="5" + fy="44" + fx="1" + cy="44" + cx="1" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + gradientUnits="userSpaceOnUse" + id="radialGradient2827" + xlink:href="#linearGradient2781" + inkscape:collect="always" /> + <radialGradient + r="5" + fy="44" + fx="1" + cy="44" + cx="1" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + gradientUnits="userSpaceOnUse" + id="radialGradient2829" + xlink:href="#linearGradient2781" + inkscape:collect="always" /> + <linearGradient + y2="40" + x2="21.875" + y1="48.000977" + x1="21.875" + gradientUnits="userSpaceOnUse" + id="linearGradient2831" + xlink:href="#linearGradient2804" + inkscape:collect="always" /> + <linearGradient + id="linearGradient2006"> + <stop + id="stop2008" + offset="0" + style="stop-color:black;stop-opacity:0;" /> + <stop + style="stop-color:black;stop-opacity:1;" + offset="0.5" + id="stop2010" /> + <stop + id="stop2012" + offset="1" + style="stop-color:black;stop-opacity:0;" /> + </linearGradient> + <linearGradient + y2="24.143761" + x2="27.2733" + y1="10.957423" + x1="35.003674" + gradientTransform="matrix(-0.977228,0,0,0.995878,50.60272,9.115637)" + gradientUnits="userSpaceOnUse" + id="linearGradient29443" + xlink:href="#linearGradient29418" + inkscape:collect="always" /> + <linearGradient + id="linearGradient29418"> + <stop + id="stop29420" + offset="0.0000000" + style="stop-color:#f5f5f5;stop-opacity:1.0000000;" /> + <stop + id="stop29422" + offset="1.0000000" + style="stop-color:#e9e9e9;stop-opacity:1.0000000;" /> + </linearGradient> + <linearGradient + id="linearGradient2225" + inkscape:collect="always"> + <stop + id="stop2227" + offset="0" + style="stop-color:#eeeeec;stop-opacity:1;" /> + <stop + id="stop2229" + offset="1" + style="stop-color:#eeeeec;stop-opacity:0;" /> + </linearGradient> + <linearGradient + id="linearGradient2989" + inkscape:collect="always"> + <stop + id="stop2991" + offset="0" + style="stop-color:#eeeeec;stop-opacity:1;" /> + <stop + id="stop2993" + offset="1" + style="stop-color:#eeeeec;stop-opacity:0;" /> + </linearGradient> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2812" + id="radialGradient2112" + gradientUnits="userSpaceOnUse" + cx="31.112698" + cy="19.008621" + fx="31.112698" + fy="19.008621" + r="8.6620579" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2851" + id="linearGradient2114" + gradientUnits="userSpaceOnUse" + x1="6.878005" + y1="11.789385" + x2="12.233074" + y2="27.77807" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3149" + id="linearGradient2116" + gradientUnits="userSpaceOnUse" + x1="15.498499" + y1="9.4211226" + x2="24.240097" + y2="36.603138" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3149" + id="linearGradient2119" + gradientUnits="userSpaceOnUse" + x1="15.498499" + y1="9.4211226" + x2="24.240097" + y2="36.603138" + gradientTransform="matrix(0.2512053,0,0,0.2512055,0.505914,0.5856851)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2851" + id="linearGradient2122" + gradientUnits="userSpaceOnUse" + x1="6.878005" + y1="11.789385" + x2="12.233074" + y2="27.77807" + gradientTransform="matrix(0.3229785,0,0,0.3229785,-0.7781054,-0.675548)" /> + <linearGradient + y2="40" + x2="21.875" + y1="48.000977" + x1="21.875" + gradientUnits="userSpaceOnUse" + id="linearGradient2567" + xlink:href="#linearGradient2804" + inkscape:collect="always" /> + <radialGradient + r="5" + fy="44" + fx="1" + cy="44" + cx="1" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + gradientUnits="userSpaceOnUse" + id="radialGradient2565" + xlink:href="#linearGradient2781" + inkscape:collect="always" /> + <radialGradient + r="5" + fy="44" + fx="1" + cy="44" + cx="1" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + gradientUnits="userSpaceOnUse" + id="radialGradient2563" + xlink:href="#linearGradient2781" + inkscape:collect="always" /> + <linearGradient + gradientTransform="matrix(0.36035,0,0,0.358865,4.074001,4.193834)" + y2="27.77807" + x2="12.233074" + y1="11.789385" + x1="6.878005" + gradientUnits="userSpaceOnUse" + id="linearGradient2561" + xlink:href="#linearGradient2851" + inkscape:collect="always" /> + <linearGradient + gradientTransform="matrix(0.287092,0,0,0.287092,5.363906,5.455062)" + y2="34.458977" + x2="17.890068" + y1="2.2464287" + x1="17.890068" + gradientUnits="userSpaceOnUse" + id="linearGradient2559" + xlink:href="#linearGradient3149" + inkscape:collect="always" /> + <linearGradient + id="linearGradient2547"> + <stop + style="stop-color:#73d216;stop-opacity:1;" + offset="0" + id="stop2549" /> + <stop + style="stop-color:#5ca911;stop-opacity:1;" + offset="1" + id="stop2551" /> + </linearGradient> + <linearGradient + id="linearGradient2539"> + <stop + style="stop-color:black;stop-opacity:0;" + offset="0" + id="stop2541" /> + <stop + id="stop2543" + offset="0.5" + style="stop-color:black;stop-opacity:1;" /> + <stop + style="stop-color:black;stop-opacity:0;" + offset="1" + id="stop2545" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient2537" + gradientUnits="userSpaceOnUse" + x1="21.875" + y1="48.000977" + x2="21.875" + y2="40" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient2535" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient2527" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <linearGradient + y2="17.697369" + x2="11.226587" + y1="-5.4832759" + x1="11.226587" + gradientTransform="matrix(-0.420408,0,0,0.420404,15.54691,5.457116)" + gradientUnits="userSpaceOnUse" + id="linearGradient2343" + xlink:href="#linearGradient2186" + inkscape:collect="always" /> + <linearGradient + y2="48.674999" + x2="15.535398" + y1="1.8014067" + x1="15.535398" + gradientTransform="matrix(-0.296523,0,0,0.296522,15.24437,5.75564)" + gradientUnits="userSpaceOnUse" + id="linearGradient2345" + xlink:href="#linearGradient2239" + inkscape:collect="always" /> + <radialGradient + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1,0,0,0.626667,0,6.566431)" + r="6.3436799" + fy="17.588654" + fx="11.756953" + cy="17.588654" + cx="11.756953" + id="radialGradient2511" + xlink:href="#linearGradient2260" + inkscape:collect="always" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2186" + id="linearGradient2583" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-0.420408,0,0,0.420404,23.273502,-1.8126311)" + x1="11.226587" + y1="-5.4832759" + x2="11.226587" + y2="17.697369" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient2585" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-0.296523,0,0,0.296522,22.970962,-1.5141071)" + x1="15.535398" + y1="1.8014067" + x2="15.535398" + y2="48.674999" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2851" + id="linearGradient2597" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.358865,0,0,0.358865,-0.920117,-0.8061648)" + x1="6.878005" + y1="11.789385" + x2="12.233074" + y2="27.77807" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3149" + id="linearGradient2599" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.2870918,0,0,0.287092,0.3639019,0.4550689)" + x1="15.498499" + y1="9.4211226" + x2="24.240097" + y2="36.603138" /> + <linearGradient + y2="40" + x2="21.875" + y1="48.000977" + x1="21.875" + gradientUnits="userSpaceOnUse" + id="linearGradient2713" + xlink:href="#linearGradient2804" + inkscape:collect="always" /> + <radialGradient + r="5" + fy="44" + fx="1" + cy="44" + cx="1" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + gradientUnits="userSpaceOnUse" + id="radialGradient2711" + xlink:href="#linearGradient2781" + inkscape:collect="always" /> + <radialGradient + r="5" + fy="44" + fx="1" + cy="44" + cx="1" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + gradientUnits="userSpaceOnUse" + id="radialGradient2709" + xlink:href="#linearGradient2781" + inkscape:collect="always" /> + <linearGradient + gradientTransform="matrix(0.36035,0,0,0.358865,4.074001,4.193834)" + y2="27.77807" + x2="12.233074" + y1="11.789385" + x1="6.878005" + gradientUnits="userSpaceOnUse" + id="linearGradient2707" + xlink:href="#linearGradient2851" + inkscape:collect="always" /> + <linearGradient + gradientTransform="matrix(0.287092,0,0,0.287092,5.363906,5.455062)" + y2="34.458977" + x2="17.890068" + y1="2.2464287" + x1="17.890068" + gradientUnits="userSpaceOnUse" + id="linearGradient2705" + xlink:href="#linearGradient3149" + inkscape:collect="always" /> + <linearGradient + id="linearGradient2693"> + <stop + style="stop-color:#73d216;stop-opacity:1;" + offset="0" + id="stop2695" /> + <stop + style="stop-color:#5ca911;stop-opacity:1;" + offset="1" + id="stop2697" /> + </linearGradient> + <linearGradient + id="linearGradient2685"> + <stop + style="stop-color:black;stop-opacity:0;" + offset="0" + id="stop2687" /> + <stop + id="stop2689" + offset="0.5" + style="stop-color:black;stop-opacity:1;" /> + <stop + style="stop-color:black;stop-opacity:0;" + offset="1" + id="stop2691" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient2683" + gradientUnits="userSpaceOnUse" + x1="21.875" + y1="48.000977" + x2="21.875" + y2="40" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient2681" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient2673" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <linearGradient + y2="17.697369" + x2="11.226587" + y1="-5.4832759" + x1="11.226587" + gradientTransform="matrix(-0.420408,0,0,0.420404,15.54691,5.457116)" + gradientUnits="userSpaceOnUse" + id="linearGradient2671" + xlink:href="#linearGradient2186" + inkscape:collect="always" /> + <linearGradient + y2="48.674999" + x2="15.535398" + y1="1.8014067" + x1="15.535398" + gradientTransform="matrix(-0.296523,0,0,0.296522,15.24437,5.75564)" + gradientUnits="userSpaceOnUse" + id="linearGradient2663" + xlink:href="#linearGradient2239" + inkscape:collect="always" /> + <radialGradient + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1,0,0,0.626667,0,6.566431)" + r="6.3436799" + fy="17.588654" + fx="11.756953" + cy="17.588654" + cx="11.756953" + id="radialGradient2655" + xlink:href="#linearGradient2260" + inkscape:collect="always" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient2727" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient2729" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient2731" + gradientUnits="userSpaceOnUse" + x1="21.875" + y1="48.000977" + x2="21.875" + y2="40" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2186" + id="linearGradient2733" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-0.420408,0,0,0.420404,15.54691,5.457116)" + x1="11.226587" + y1="-5.4832759" + x2="11.226587" + y2="17.697369" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient2735" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-0.296523,0,0,0.296522,15.24437,5.75564)" + x1="15.535398" + y1="1.8014067" + x2="15.535398" + y2="48.674999" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2186" + id="linearGradient2739" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-0.420408,0,0,0.420404,10.546911,0.4571158)" + x1="11.226587" + y1="-5.4832759" + x2="11.226587" + y2="17.697369" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient2741" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-0.296523,0,0,0.296522,10.244371,0.7556398)" + x1="15.535398" + y1="1.8014067" + x2="15.535398" + y2="48.674999" /> + <linearGradient + y2="10.018044" + x2="10.043059" + y1="1.3319674" + x1="1.5769236" + gradientUnits="userSpaceOnUse" + id="linearGradient2232" + xlink:href="#linearGradient2989" + inkscape:collect="always" /> + <linearGradient + id="linearGradient2098"> + <stop + style="stop-color:#f5f5f5;stop-opacity:1.0000000;" + offset="0.0000000" + id="stop2100" /> + <stop + style="stop-color:#e9e9e9;stop-opacity:1.0000000;" + offset="1.0000000" + id="stop2102" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient29418" + id="linearGradient2104" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-0.977228,0,0,0.995878,50.60272,9.115637)" + x1="35.003674" + y1="10.957423" + x2="27.273300" + y2="24.143761" /> + <linearGradient + id="linearGradient2106"> + <stop + style="stop-color:black;stop-opacity:0;" + offset="0" + id="stop2108" /> + <stop + id="stop2110" + offset="0.5" + style="stop-color:black;stop-opacity:1;" /> + <stop + style="stop-color:black;stop-opacity:0;" + offset="1" + id="stop2112" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient4258" + gradientUnits="userSpaceOnUse" + x1="21.875" + y1="48.000977" + x2="21.875" + y2="40" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient2116" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient2124" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient2126" + x1="15.535398" + y1="1.8014067" + x2="15.535398" + y2="48.674999" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.37378,0,0,0.375227,17.64779,15.86312)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2186" + id="linearGradient2134" + x1="11.226587" + y1="-5.4832759" + x2="11.226587" + y2="17.697369" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.529942,0,0,0.53199,17.26643,15.48536)" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3816" + id="radialGradient2148" + cx="31.112698" + cy="19.008621" + fx="31.112698" + fy="19.008621" + r="8.6620579" + gradientUnits="userSpaceOnUse" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2200" + id="radialGradient2156" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-2.522332,-1.518129e-16,-1.517788e-16,2.521765,40.1904,-21.83521)" + cx="9.9988937" + cy="8.963316" + fx="9.9988937" + fy="8.963316" + r="7.0034069" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2200" + id="radialGradient2158" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-2.522332,-1.518129e-16,-1.517788e-16,2.521765,40.1904,-21.80154)" + cx="9.9988937" + cy="8.963316" + fx="9.9988937" + fy="8.963316" + r="7.0034069" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2260" + id="radialGradient4249" + cx="11.756953" + cy="17.588654" + fx="11.756953" + fy="17.588654" + r="6.3436799" + gradientTransform="matrix(1,0,0,0.626667,0,6.566431)" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient4247" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.371983,0,0,0.372254,2.539836,8.539528)" + x1="15.602553" + y1="1.5657365" + x2="15.522223" + y2="33.483475" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2186" + id="linearGradient2168" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.529942,0,0,0.53199,17.26643,15.48536)" + x1="11.226587" + y1="-5.4832759" + x2="11.226587" + y2="17.697369" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient2170" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.37378,0,0,0.375227,17.64779,15.86312)" + x1="15.535398" + y1="1.8014067" + x2="15.535398" + y2="48.674999" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2225" + id="linearGradient4243" + gradientUnits="userSpaceOnUse" + x1="11.802028" + y1="1.9986149" + x2="11.802028" + y2="14.895812" /> + <linearGradient + gradientUnits="userSpaceOnUse" + y2="27.77807" + x2="12.233074" + y1="11.789385" + x1="6.878005" + id="linearGradient4241" + xlink:href="#linearGradient2851" + inkscape:collect="always" /> + <linearGradient + id="linearGradient2177"> + <stop + id="stop2179" + offset="0" + style="stop-color:#73d216;stop-opacity:1;" /> + <stop + id="stop2181" + offset="1" + style="stop-color:#5ca911;stop-opacity:1;" /> + </linearGradient> + <linearGradient + y2="40.032413" + x2="17.890068" + y1="8.0617304" + x1="17.890068" + gradientUnits="userSpaceOnUse" + id="linearGradient4230" + xlink:href="#linearGradient3149" + inkscape:collect="always" /> + <radialGradient + gradientUnits="userSpaceOnUse" + r="8.6620579" + fy="19.008621" + fx="31.112698" + cy="19.008621" + cx="31.112698" + id="radialGradient4222" + xlink:href="#linearGradient2812" + inkscape:collect="always" /> + <linearGradient + gradientUnits="userSpaceOnUse" + y2="11.024895" + x2="10.623409" + y1="2.7991772" + x1="4.5264969" + id="linearGradient4220" + xlink:href="#linearGradient2804" + inkscape:collect="always" /> + <linearGradient + gradientUnits="userSpaceOnUse" + y2="27.77807" + x2="12.233074" + y1="11.789385" + x1="6.878005" + id="linearGradient4218" + xlink:href="#linearGradient2851" + inkscape:collect="always" /> + <linearGradient + id="linearGradient4212"> + <stop + id="stop4214" + offset="0" + style="stop-color:#73d216;stop-opacity:1;" /> + <stop + id="stop4216" + offset="1" + style="stop-color:#5ca911;stop-opacity:1;" /> + </linearGradient> + <linearGradient + y2="40.032413" + x2="17.890068" + y1="8.0617304" + x1="17.890068" + gradientUnits="userSpaceOnUse" + id="linearGradient4210" + xlink:href="#linearGradient3149" + inkscape:collect="always" /> + <linearGradient + id="linearGradient3292"> + <stop + style="stop-color:#f5f5f5;stop-opacity:1.0000000;" + offset="0.0000000" + id="stop3294" /> + <stop + style="stop-color:#e9e9e9;stop-opacity:1.0000000;" + offset="1.0000000" + id="stop3296" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient29418" + id="linearGradient3298" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-0.977228,0,0,0.995878,50.60272,9.115637)" + x1="35.003674" + y1="10.957423" + x2="27.273300" + y2="24.143761" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient3300" + gradientUnits="userSpaceOnUse" + x1="21.875" + y1="48.000977" + x2="21.875" + y2="40" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient3302" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient3304" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <linearGradient + id="linearGradient3306"> + <stop + style="stop-color:black;stop-opacity:0;" + offset="0" + id="stop3308" /> + <stop + id="stop3310" + offset="0.5" + style="stop-color:black;stop-opacity:1;" /> + <stop + style="stop-color:black;stop-opacity:0;" + offset="1" + id="stop3312" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient3314" + gradientUnits="userSpaceOnUse" + x1="21.875" + y1="48.000977" + x2="21.875" + y2="40" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient3316" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient3324" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient3326" + x1="15.535398" + y1="1.8014067" + x2="15.535398" + y2="48.674999" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.37378,0,0,0.375227,17.64779,15.86312)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2186" + id="linearGradient3334" + x1="11.226587" + y1="-5.4832759" + x2="11.226587" + y2="17.697369" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.529942,0,0,0.53199,17.26643,15.48536)" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3816" + id="radialGradient3348" + cx="31.112698" + cy="19.008621" + fx="31.112698" + fy="19.008621" + r="8.6620579" + gradientUnits="userSpaceOnUse" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2200" + id="radialGradient3356" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-2.522332,-1.518129e-16,-1.517788e-16,2.521765,40.1904,-21.83521)" + cx="9.9988937" + cy="8.963316" + fx="9.9988937" + fy="8.963316" + r="7.0034069" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2200" + id="radialGradient3358" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-2.522332,-1.518129e-16,-1.517788e-16,2.521765,40.1904,-21.80154)" + cx="9.9988937" + cy="8.963316" + fx="9.9988937" + fy="8.963316" + r="7.0034069" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2260" + id="radialGradient3360" + cx="11.756953" + cy="17.588654" + fx="11.756953" + fy="17.588654" + r="6.3436799" + gradientTransform="matrix(1,0,0,0.626667,0,6.566431)" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient3368" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.371983,0,0,0.372254,2.539836,8.539528)" + x1="15.602553" + y1="1.5657365" + x2="15.522223" + y2="33.483475" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2186" + id="linearGradient3370" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.529942,0,0,0.53199,17.26643,15.48536)" + x1="11.226587" + y1="-5.4832759" + x2="11.226587" + y2="17.697369" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient3372" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.37378,0,0,0.375227,17.64779,15.86312)" + x1="15.535398" + y1="1.8014067" + x2="15.535398" + y2="48.674999" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2225" + id="linearGradient3374" + gradientUnits="userSpaceOnUse" + x1="11.802028" + y1="1.9986149" + x2="11.802028" + y2="14.895812" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2225" + id="linearGradient2231" + x1="11.802028" + y1="1.9986149" + x2="11.802028" + y2="14.895812" + gradientUnits="userSpaceOnUse" /> + <linearGradient + id="linearGradient3093"> + <stop + style="stop-color:#f5f5f5;stop-opacity:1.0000000;" + offset="0.0000000" + id="stop3095" /> + <stop + style="stop-color:#e9e9e9;stop-opacity:1.0000000;" + offset="1.0000000" + id="stop3097" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient29418" + id="linearGradient3099" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-0.977228,0,0,0.995878,50.60272,9.115637)" + x1="35.003674" + y1="10.957423" + x2="27.273300" + y2="24.143761" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient3101" + gradientUnits="userSpaceOnUse" + x1="21.875" + y1="48.000977" + x2="21.875" + y2="40" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient3103" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient3105" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <linearGradient + id="linearGradient3107"> + <stop + style="stop-color:black;stop-opacity:0;" + offset="0" + id="stop3109" /> + <stop + id="stop3111" + offset="0.5" + style="stop-color:black;stop-opacity:1;" /> + <stop + style="stop-color:black;stop-opacity:0;" + offset="1" + id="stop3113" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient3115" + gradientUnits="userSpaceOnUse" + x1="21.875" + y1="48.000977" + x2="21.875" + y2="40" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient3117" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient3125" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient3127" + x1="15.535398" + y1="1.8014067" + x2="15.535398" + y2="48.674999" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.37378,0,0,0.375227,17.64779,15.86312)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2186" + id="linearGradient3135" + x1="11.226587" + y1="-5.4832759" + x2="11.226587" + y2="17.697369" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.529942,0,0,0.53199,17.26643,15.48536)" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3816" + id="radialGradient3149" + cx="31.112698" + cy="19.008621" + fx="31.112698" + fy="19.008621" + r="8.6620579" + gradientUnits="userSpaceOnUse" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2200" + id="radialGradient3158" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-2.522332,-1.518129e-16,-1.517788e-16,2.521765,40.1904,-21.83521)" + cx="9.9988937" + cy="8.963316" + fx="9.9988937" + fy="8.963316" + r="7.0034069" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2200" + id="radialGradient3160" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-2.522332,-1.518129e-16,-1.517788e-16,2.521765,40.1904,-21.80154)" + cx="9.9988937" + cy="8.963316" + fx="9.9988937" + fy="8.963316" + r="7.0034069" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2260" + id="radialGradient3162" + cx="11.756953" + cy="17.588654" + fx="11.756953" + fy="17.588654" + r="6.3436799" + gradientTransform="matrix(1,0,0,0.626667,0,6.566431)" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient3170" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.371983,0,0,0.372254,2.539836,8.539528)" + x1="15.602553" + y1="1.5657365" + x2="15.522223" + y2="33.483475" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2186" + id="linearGradient3172" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.529942,0,0,0.53199,17.26643,15.48536)" + x1="11.226587" + y1="-5.4832759" + x2="11.226587" + y2="17.697369" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient3174" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.37378,0,0,0.375227,17.64779,15.86312)" + x1="15.535398" + y1="1.8014067" + x2="15.535398" + y2="48.674999" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2186" + id="linearGradient3176" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.525701,0,0,0.525844,2.191252,8.189764)" + x1="11.226587" + y1="-5.4832759" + x2="11.226587" + y2="17.697369" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient3178" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.370788,0,0,0.370892,2.569561,8.563159)" + x1="15.535398" + y1="1.8014067" + x2="15.535398" + y2="48.674999" /> + <linearGradient + id="linearGradient4148"> + <stop + style="stop-color:#f5f5f5;stop-opacity:1.0000000;" + offset="0.0000000" + id="stop4150" /> + <stop + style="stop-color:#e9e9e9;stop-opacity:1.0000000;" + offset="1.0000000" + id="stop4152" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient29418" + id="linearGradient4146" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-0.977228,0,0,0.995878,50.60272,9.115637)" + x1="35.003674" + y1="10.957423" + x2="27.273300" + y2="24.143761" /> + <linearGradient + id="linearGradient2947"> + <stop + style="stop-color:black;stop-opacity:0;" + offset="0" + id="stop2949" /> + <stop + id="stop2951" + offset="0.5" + style="stop-color:black;stop-opacity:1;" /> + <stop + style="stop-color:black;stop-opacity:0;" + offset="1" + id="stop4144" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient4139" + gradientUnits="userSpaceOnUse" + x1="21.875" + y1="48.000977" + x2="21.875" + y2="40" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient4137" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient4135" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient4133" + x1="15.535398" + y1="1.8014067" + x2="15.535398" + y2="48.674999" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.37378,0,0,0.375227,17.64779,15.86312)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2186" + id="linearGradient4125" + x1="11.226587" + y1="-5.4832759" + x2="11.226587" + y2="17.697369" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.529942,0,0,0.53199,17.26643,15.48536)" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3816" + id="radialGradient4111" + cx="31.112698" + cy="19.008621" + fx="31.112698" + fy="19.008621" + r="8.6620579" + gradientUnits="userSpaceOnUse" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2200" + id="radialGradient4103" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-2.522332,-1.518129e-16,-1.517788e-16,2.521765,40.1904,-21.83521)" + cx="9.9988937" + cy="8.963316" + fx="9.9988937" + fy="8.963316" + r="7.0034069" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2200" + id="radialGradient4101" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-2.522332,-1.518129e-16,-1.517788e-16,2.521765,40.1904,-21.80154)" + cx="9.9988937" + cy="8.963316" + fx="9.9988937" + fy="8.963316" + r="7.0034069" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2186" + id="linearGradient4093" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.529942,0,0,0.53199,17.26643,15.48536)" + x1="11.226587" + y1="-5.4832759" + x2="11.226587" + y2="17.697369" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient4091" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.37378,0,0,0.375227,17.64779,15.86312)" + x1="15.535398" + y1="1.8014067" + x2="15.535398" + y2="48.674999" /> + <linearGradient + y2="40" + x2="21.875" + y1="48.000977" + x1="21.875" + gradientUnits="userSpaceOnUse" + id="linearGradient4089" + xlink:href="#linearGradient2804" + inkscape:collect="always" /> + <radialGradient + r="5" + fy="44" + fx="1" + cy="44" + cx="1" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + gradientUnits="userSpaceOnUse" + id="radialGradient4087" + xlink:href="#linearGradient2781" + inkscape:collect="always" /> + <radialGradient + r="5" + fy="44" + fx="1" + cy="44" + cx="1" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + gradientUnits="userSpaceOnUse" + id="radialGradient4085" + xlink:href="#linearGradient2781" + inkscape:collect="always" /> + <linearGradient + id="linearGradient4079"> + <stop + style="stop-color:#73d216;stop-opacity:1;" + offset="0" + id="stop4081" /> + <stop + style="stop-color:#5ca911;stop-opacity:1;" + offset="1" + id="stop4083" /> + </linearGradient> + <linearGradient + id="linearGradient4071"> + <stop + style="stop-color:black;stop-opacity:0;" + offset="0" + id="stop4073" /> + <stop + id="stop4075" + offset="0.5" + style="stop-color:black;stop-opacity:1;" /> + <stop + style="stop-color:black;stop-opacity:0;" + offset="1" + id="stop4077" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient4069" + gradientUnits="userSpaceOnUse" + x1="21.875" + y1="48.000977" + x2="21.875" + y2="40" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient4067" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient4059" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="31.392433" + inkscape:cx="14.001166" + inkscape:cy="6.793253" + inkscape:current-layer="layer1" + showgrid="true" + inkscape:grid-bbox="true" + inkscape:document-units="px" + inkscape:window-width="1440" + inkscape:window-height="847" + inkscape:window-x="0" + inkscape:window-y="0" + width="11px" + height="11px" /> + <metadata + id="metadata1877"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + id="layer1" + inkscape:label="Layer 1" + inkscape:groupmode="layer"> + <path + sodipodi:type="arc" + style="color:#000000;fill:#729fcf;fill-opacity:1;fill-rule:evenodd;stroke:#173867;stroke-width:2.86902547px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" + id="path2069" + sodipodi:cx="15.590227" + sodipodi:cy="16.57217" + sodipodi:rx="14.345175" + sodipodi:ry="14.345175" + d="M 29.935402 16.57217 A 14.345175 14.345175 0 1 1 1.2450523,16.57217 A 14.345175 14.345175 0 1 1 29.935402 16.57217 z" + transform="matrix(0.348549,0,0,0.348549,6.6036232e-2,-0.2762077)" /> + <path + sodipodi:type="arc" + style="fill:#8ab0d7;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="path2788" + sodipodi:cx="-3.8088531" + sodipodi:cy="3.303823" + sodipodi:rx="3.1932809" + sodipodi:ry="3.3471739" + d="M -0.61557221 3.303823 A 3.1932809 3.3471739 0 1 1 -7.0021341,3.303823 A 3.1932809 3.3471739 0 1 1 -0.61557221 3.303823 z" + transform="matrix(1.409209,0,0,1.344418,10.867469,1.0582933)" /> + <path + sodipodi:type="arc" + style="fill:#dcdcd8;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="path2796" + sodipodi:cx="6.0403023" + sodipodi:cy="7.5551186" + sodipodi:rx="1.615877" + sodipodi:ry="1.3273276" + d="M 7.6561793 7.5551186 A 1.615877 1.3273276 0 1 1 4.4244252,7.5551186 A 1.615877 1.3273276 0 1 1 7.6561793 7.5551186 z" + transform="matrix(2.784865,0,0,3.390272,-11.321424,-20.113899)" /> + <rect + style="fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect2832" + width="1" + height="1" + x="5.00001" + y="-5.999999" + transform="matrix(0,1,-1,0,0,0)" /> + <rect + style="fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect2236" + width="1" + height="1" + x="4.00001" + y="-6.999999" + transform="matrix(0,1,-1,0,0,0)" /> + <rect + style="fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect2240" + width="1" + height="1" + x="6.00001" + y="-6.999999" + transform="matrix(0,1,-1,0,0,0)" /> + <rect + style="fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect3133" + width="1" + height="1" + x="3.00001" + y="-7.9999981" + transform="matrix(0,1,-1,0,0,0)" /> + <rect + style="fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect3135" + width="1" + height="1" + x="7.00001" + y="-7.9999981" + transform="matrix(0,1,-1,0,0,0)" /> + </g> +</svg>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pidgin/pixmaps/status/11/scalable/busy.svg Mon Aug 27 21:59:11 2007 +0000 @@ -0,0 +1,1182 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://web.resource.org/cc/" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="11" + height="11" + id="svg1872" + sodipodi:version="0.32" + inkscape:version="0.45.1" + sodipodi:docbase="/home/hbons/Desktop/tabs" + sodipodi:docname="busy.svg" + inkscape:output_extension="org.inkscape.output.svg.inkscape" + version="1.0" + inkscape:export-filename="/home/hbons/Desktop/tabs/busy.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90"> + <defs + id="defs1874"> + <radialGradient + r="5" + fy="44" + fx="1" + cy="44" + cx="1" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + gradientUnits="userSpaceOnUse" + id="radialGradient7751" + xlink:href="#linearGradient2781" + inkscape:collect="always" /> + <linearGradient + id="linearGradient2781" + inkscape:collect="always"> + <stop + id="stop2783" + offset="0" + style="stop-color:black;stop-opacity:1;" /> + <stop + id="stop2785" + offset="1" + style="stop-color:black;stop-opacity:0;" /> + </linearGradient> + <radialGradient + r="5" + fy="44" + fx="1" + cy="44" + cx="1" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + gradientUnits="userSpaceOnUse" + id="radialGradient7753" + xlink:href="#linearGradient2781" + inkscape:collect="always" /> + <linearGradient + y2="40" + x2="21.875" + y1="48.000977" + x1="21.875" + gradientUnits="userSpaceOnUse" + id="linearGradient7755" + xlink:href="#linearGradient2804" + inkscape:collect="always" /> + <linearGradient + id="linearGradient2804"> + <stop + id="stop2806" + offset="0" + style="stop-color:black;stop-opacity:0;" /> + <stop + style="stop-color:black;stop-opacity:1;" + offset="0.5" + id="stop2812" /> + <stop + id="stop2808" + offset="1" + style="stop-color:black;stop-opacity:0;" /> + </linearGradient> + <linearGradient + id="linearGradient2851"> + <stop + id="stop2853" + offset="0" + style="stop-color:#73d216;stop-opacity:1;" /> + <stop + id="stop2855" + offset="1" + style="stop-color:#5ca911;stop-opacity:1;" /> + </linearGradient> + <linearGradient + id="linearGradient3149" + inkscape:collect="always"> + <stop + id="stop3151" + offset="0" + style="stop-color:#eeeeec;stop-opacity:1;" /> + <stop + id="stop3153" + offset="1" + style="stop-color:#eeeeec;stop-opacity:0;" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3149" + id="linearGradient1956" + gradientUnits="userSpaceOnUse" + x1="17.890068" + y1="2.2464287" + x2="17.890068" + y2="34.458977" + gradientTransform="matrix(0.287092,0,0,0.287092,5.363906,5.455062)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2851" + id="linearGradient1959" + gradientUnits="userSpaceOnUse" + x1="6.878005" + y1="11.789385" + x2="12.233074" + y2="27.77807" + gradientTransform="matrix(0.36035,0,0,0.358865,4.074001,4.193834)" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient1970" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient1972" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient1974" + gradientUnits="userSpaceOnUse" + x1="21.875" + y1="48.000977" + x2="21.875" + y2="40" /> + <linearGradient + inkscape:collect="always" + id="linearGradient2898"> + <stop + style="stop-color:white;stop-opacity:1;" + offset="0" + id="stop2900" /> + <stop + style="stop-color:white;stop-opacity:0;" + offset="1" + id="stop2902" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2851" + id="linearGradient4738" + gradientUnits="userSpaceOnUse" + x1="6.878005" + y1="11.789385" + x2="12.233074" + y2="27.77807" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3149" + id="linearGradient4740" + gradientUnits="userSpaceOnUse" + x1="15.498499" + y1="9.4211226" + x2="24.240097" + y2="36.603138" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3149" + id="linearGradient3044" + gradientUnits="userSpaceOnUse" + x1="17.890068" + y1="8.0617304" + x2="17.890068" + y2="40.032413" /> + <linearGradient + id="linearGradient3046"> + <stop + style="stop-color:#73d216;stop-opacity:1;" + offset="0" + id="stop3048" /> + <stop + style="stop-color:#5ca911;stop-opacity:1;" + offset="1" + id="stop3050" /> + </linearGradient> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3816" + id="radialGradient3064" + cx="31.112698" + cy="19.008621" + fx="31.112698" + fy="19.008621" + r="8.6620579" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.914124,0,0,1.631747,2.671799,-12.00863)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2851" + id="linearGradient3066" + x1="6.878005" + y1="11.789385" + x2="12.233074" + y2="27.77807" + gradientUnits="userSpaceOnUse" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2898" + id="radialGradient2904" + cx="4.8470273" + cy="6.9473476" + fx="4.8470273" + fy="6.9473476" + r="0.8078171" + gradientTransform="matrix(3.018423,0.664359,-1.388844,4.257661,-0.134567,-26.02469)" + gradientUnits="userSpaceOnUse" /> + <radialGradient + gradientUnits="userSpaceOnUse" + r="8.6620579" + fy="19.008621" + fx="31.112698" + cy="19.008621" + cx="31.112698" + id="radialGradient2818" + xlink:href="#linearGradient2812" + inkscape:collect="always" /> + <linearGradient + gradientUnits="userSpaceOnUse" + y2="11.024895" + x2="10.623409" + y1="2.7991772" + x1="4.5264969" + id="linearGradient2810" + xlink:href="#linearGradient2804" + inkscape:collect="always" /> + <linearGradient + gradientUnits="userSpaceOnUse" + y2="27.77807" + x2="12.233074" + y1="11.789385" + x1="6.878005" + id="linearGradient2963" + xlink:href="#linearGradient2851" + inkscape:collect="always" /> + <linearGradient + id="linearGradient2951"> + <stop + id="stop2953" + offset="0" + style="stop-color:#73d216;stop-opacity:1;" /> + <stop + id="stop2955" + offset="1" + style="stop-color:#5ca911;stop-opacity:1;" /> + </linearGradient> + <linearGradient + y2="40.032413" + x2="17.890068" + y1="8.0617304" + x1="17.890068" + gradientUnits="userSpaceOnUse" + id="linearGradient2949" + xlink:href="#linearGradient3149" + inkscape:collect="always" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2812" + id="radialGradient3005" + gradientUnits="userSpaceOnUse" + cx="31.112698" + cy="19.008621" + fx="31.112698" + fy="19.008621" + r="8.6620579" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient3007" + gradientUnits="userSpaceOnUse" + x1="4.5264969" + y1="2.7991772" + x2="10.623409" + y2="11.024895" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2812" + id="radialGradient3025" + gradientUnits="userSpaceOnUse" + cx="31.112698" + cy="19.008621" + fx="31.112698" + fy="19.008621" + r="8.6620579" /> + <linearGradient + gradientUnits="userSpaceOnUse" + y2="10.018044" + x2="10.043059" + y1="1.3319674" + x1="1.5769236" + id="linearGradient2995" + xlink:href="#linearGradient2989" + inkscape:collect="always" /> + <radialGradient + r="8.6620579" + fy="19.008621" + fx="31.112698" + cy="19.008621" + cx="31.112698" + gradientUnits="userSpaceOnUse" + id="radialGradient2084" + xlink:href="#linearGradient2812" + inkscape:collect="always" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3149" + id="linearGradient2046" + gradientUnits="userSpaceOnUse" + x1="17.890068" + y1="8.0617304" + x2="17.890068" + y2="40.032413" /> + <linearGradient + id="linearGradient2048"> + <stop + style="stop-color:#73d216;stop-opacity:1;" + offset="0" + id="stop2050" /> + <stop + style="stop-color:#5ca911;stop-opacity:1;" + offset="1" + id="stop2052" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2851" + id="linearGradient2060" + x1="6.878005" + y1="11.789385" + x2="12.233074" + y2="27.77807" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient2062" + x1="4.5264969" + y1="2.7991772" + x2="10.623409" + y2="11.024895" + gradientUnits="userSpaceOnUse" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2812" + id="radialGradient2064" + cx="31.112698" + cy="19.008621" + fx="31.112698" + fy="19.008621" + r="8.6620579" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + id="linearGradient2812"> + <stop + style="stop-color:#2e3436;stop-opacity:1;" + offset="0" + id="stop2814" /> + <stop + style="stop-color:#2e3436;stop-opacity:0;" + offset="1" + id="stop2816" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3149" + id="linearGradient2269" + gradientUnits="userSpaceOnUse" + x1="17.890068" + y1="8.0617304" + x2="17.890068" + y2="40.032413" /> + <linearGradient + id="linearGradient2055"> + <stop + style="stop-color:#73d216;stop-opacity:1;" + offset="0" + id="stop2057" /> + <stop + style="stop-color:#5ca911;stop-opacity:1;" + offset="1" + id="stop2059" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2851" + id="linearGradient2857" + x1="6.878005" + y1="11.789385" + x2="12.233074" + y2="27.77807" + gradientUnits="userSpaceOnUse" /> + <linearGradient + y2="14.895812" + x2="11.802028" + y1="1.9986149" + x1="11.802028" + gradientUnits="userSpaceOnUse" + id="linearGradient6606" + xlink:href="#linearGradient2225" + inkscape:collect="always" /> + <linearGradient + y2="48.674999" + x2="15.535398" + y1="1.8014067" + x1="15.535398" + gradientTransform="matrix(0.37378,0,0,0.375227,17.64779,15.86312)" + gradientUnits="userSpaceOnUse" + id="linearGradient2339" + xlink:href="#linearGradient2239" + inkscape:collect="always" /> + <linearGradient + y2="17.697369" + x2="11.226587" + y1="-5.4832759" + x1="11.226587" + gradientTransform="matrix(0.529942,0,0,0.53199,17.26643,15.48536)" + gradientUnits="userSpaceOnUse" + id="linearGradient2337" + xlink:href="#linearGradient2186" + inkscape:collect="always" /> + <linearGradient + y2="33.483475" + x2="15.522223" + y1="1.5657365" + x1="15.602553" + gradientTransform="matrix(0.371983,0,0,0.372254,2.539836,8.539528)" + gradientUnits="userSpaceOnUse" + id="linearGradient1357" + xlink:href="#linearGradient2239" + inkscape:collect="always" /> + <linearGradient + inkscape:collect="always" + id="linearGradient2239"> + <stop + style="stop-color:#ffffff;stop-opacity:1;" + offset="0" + id="stop2241" /> + <stop + style="stop-color:#ffffff;stop-opacity:0;" + offset="1" + id="stop2243" /> + </linearGradient> + <radialGradient + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1,0,0,0.626667,0,6.566431)" + r="6.3436799" + fy="17.588654" + fx="11.756953" + cy="17.588654" + cx="11.756953" + id="radialGradient2266" + xlink:href="#linearGradient2260" + inkscape:collect="always" /> + <radialGradient + r="7.003407" + fy="8.963316" + fx="9.9988937" + cy="8.963316" + cx="9.9988937" + gradientTransform="matrix(-2.522332,0,0,2.521765,40.1904,-21.80154)" + gradientUnits="userSpaceOnUse" + id="radialGradient2225" + xlink:href="#linearGradient2200" + inkscape:collect="always" /> + <radialGradient + r="7.003407" + fy="8.963316" + fx="9.9988937" + cy="8.963316" + cx="9.9988937" + gradientTransform="matrix(-2.522332,0,0,2.521765,40.1904,-21.83521)" + gradientUnits="userSpaceOnUse" + id="radialGradient2216" + xlink:href="#linearGradient2200" + inkscape:collect="always" /> + <linearGradient + id="linearGradient2200" + inkscape:collect="always"> + <stop + id="stop2202" + offset="0" + style="stop-color:#d3d7cf;stop-opacity:1;" /> + <stop + id="stop2204" + offset="1" + style="stop-color:#d3d7cf;stop-opacity:0;" /> + </linearGradient> + <radialGradient + gradientUnits="userSpaceOnUse" + r="8.6620579" + fy="19.008621" + fx="31.112698" + cy="19.008621" + cx="31.112698" + id="radialGradient3822" + xlink:href="#linearGradient3816" + inkscape:collect="always" /> + <linearGradient + id="linearGradient3816" + inkscape:collect="always"> + <stop + id="stop3818" + offset="0" + style="stop-color:#000000;stop-opacity:1;" /> + <stop + id="stop3820" + offset="1" + style="stop-color:#000000;stop-opacity:0;" /> + </linearGradient> + <linearGradient + id="linearGradient2260" + inkscape:collect="always"> + <stop + id="stop2262" + offset="0" + style="stop-color:#555753;stop-opacity:1;" /> + <stop + id="stop2264" + offset="1" + style="stop-color:#555753;stop-opacity:0;" /> + </linearGradient> + <linearGradient + gradientTransform="matrix(0.529942,0,0,0.53199,17.26643,15.48536)" + gradientUnits="userSpaceOnUse" + y2="17.697369" + x2="11.226587" + y1="-5.4832759" + x1="11.226587" + id="linearGradient2194" + xlink:href="#linearGradient2186" + inkscape:collect="always" /> + <linearGradient + id="linearGradient2186" + inkscape:collect="always"> + <stop + id="stop2188" + offset="0" + style="stop-color:#ffffff;stop-opacity:1;" /> + <stop + id="stop2190" + offset="1" + style="stop-color:#ffffff;stop-opacity:0;" /> + </linearGradient> + <linearGradient + gradientTransform="matrix(0.37378,0,0,0.375227,17.64779,15.86312)" + gradientUnits="userSpaceOnUse" + y2="48.674999" + x2="15.535398" + y1="1.8014067" + x1="15.535398" + id="linearGradient2245" + xlink:href="#linearGradient2239" + inkscape:collect="always" /> + <radialGradient + r="5" + fy="44" + fx="1" + cy="44" + cx="1" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + gradientUnits="userSpaceOnUse" + id="radialGradient2827" + xlink:href="#linearGradient2781" + inkscape:collect="always" /> + <radialGradient + r="5" + fy="44" + fx="1" + cy="44" + cx="1" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + gradientUnits="userSpaceOnUse" + id="radialGradient2829" + xlink:href="#linearGradient2781" + inkscape:collect="always" /> + <linearGradient + y2="40" + x2="21.875" + y1="48.000977" + x1="21.875" + gradientUnits="userSpaceOnUse" + id="linearGradient2831" + xlink:href="#linearGradient2804" + inkscape:collect="always" /> + <linearGradient + id="linearGradient2006"> + <stop + id="stop2008" + offset="0" + style="stop-color:black;stop-opacity:0;" /> + <stop + style="stop-color:black;stop-opacity:1;" + offset="0.5" + id="stop2010" /> + <stop + id="stop2012" + offset="1" + style="stop-color:black;stop-opacity:0;" /> + </linearGradient> + <linearGradient + y2="24.143761" + x2="27.2733" + y1="10.957423" + x1="35.003674" + gradientTransform="matrix(-0.977228,0,0,0.995878,50.60272,9.115637)" + gradientUnits="userSpaceOnUse" + id="linearGradient29443" + xlink:href="#linearGradient29418" + inkscape:collect="always" /> + <linearGradient + id="linearGradient29418"> + <stop + id="stop29420" + offset="0.0000000" + style="stop-color:#f5f5f5;stop-opacity:1.0000000;" /> + <stop + id="stop29422" + offset="1.0000000" + style="stop-color:#e9e9e9;stop-opacity:1.0000000;" /> + </linearGradient> + <linearGradient + id="linearGradient2225" + inkscape:collect="always"> + <stop + id="stop2227" + offset="0" + style="stop-color:#eeeeec;stop-opacity:1;" /> + <stop + id="stop2229" + offset="1" + style="stop-color:#eeeeec;stop-opacity:0;" /> + </linearGradient> + <linearGradient + id="linearGradient2989" + inkscape:collect="always"> + <stop + id="stop2991" + offset="0" + style="stop-color:#eeeeec;stop-opacity:1;" /> + <stop + id="stop2993" + offset="1" + style="stop-color:#eeeeec;stop-opacity:0;" /> + </linearGradient> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2812" + id="radialGradient2112" + gradientUnits="userSpaceOnUse" + cx="31.112698" + cy="19.008621" + fx="31.112698" + fy="19.008621" + r="8.6620579" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2851" + id="linearGradient2114" + gradientUnits="userSpaceOnUse" + x1="6.878005" + y1="11.789385" + x2="12.233074" + y2="27.77807" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3149" + id="linearGradient2116" + gradientUnits="userSpaceOnUse" + x1="15.498499" + y1="9.4211226" + x2="24.240097" + y2="36.603138" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3149" + id="linearGradient2119" + gradientUnits="userSpaceOnUse" + x1="15.498499" + y1="9.4211226" + x2="24.240097" + y2="36.603138" + gradientTransform="matrix(0.2512053,0,0,0.2512055,0.505914,0.5856851)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2851" + id="linearGradient2122" + gradientUnits="userSpaceOnUse" + x1="6.878005" + y1="11.789385" + x2="12.233074" + y2="27.77807" + gradientTransform="matrix(0.3229785,0,0,0.3229785,-0.7781054,-0.675548)" /> + <linearGradient + y2="40" + x2="21.875" + y1="48.000977" + x1="21.875" + gradientUnits="userSpaceOnUse" + id="linearGradient2567" + xlink:href="#linearGradient2804" + inkscape:collect="always" /> + <radialGradient + r="5" + fy="44" + fx="1" + cy="44" + cx="1" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + gradientUnits="userSpaceOnUse" + id="radialGradient2565" + xlink:href="#linearGradient2781" + inkscape:collect="always" /> + <radialGradient + r="5" + fy="44" + fx="1" + cy="44" + cx="1" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + gradientUnits="userSpaceOnUse" + id="radialGradient2563" + xlink:href="#linearGradient2781" + inkscape:collect="always" /> + <linearGradient + gradientTransform="matrix(0.36035,0,0,0.358865,4.074001,4.193834)" + y2="27.77807" + x2="12.233074" + y1="11.789385" + x1="6.878005" + gradientUnits="userSpaceOnUse" + id="linearGradient2561" + xlink:href="#linearGradient2851" + inkscape:collect="always" /> + <linearGradient + gradientTransform="matrix(0.287092,0,0,0.287092,5.363906,5.455062)" + y2="34.458977" + x2="17.890068" + y1="2.2464287" + x1="17.890068" + gradientUnits="userSpaceOnUse" + id="linearGradient2559" + xlink:href="#linearGradient3149" + inkscape:collect="always" /> + <linearGradient + id="linearGradient2547"> + <stop + style="stop-color:#73d216;stop-opacity:1;" + offset="0" + id="stop2549" /> + <stop + style="stop-color:#5ca911;stop-opacity:1;" + offset="1" + id="stop2551" /> + </linearGradient> + <linearGradient + id="linearGradient2539"> + <stop + style="stop-color:black;stop-opacity:0;" + offset="0" + id="stop2541" /> + <stop + id="stop2543" + offset="0.5" + style="stop-color:black;stop-opacity:1;" /> + <stop + style="stop-color:black;stop-opacity:0;" + offset="1" + id="stop2545" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient2537" + gradientUnits="userSpaceOnUse" + x1="21.875" + y1="48.000977" + x2="21.875" + y2="40" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient2535" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient2527" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <linearGradient + y2="17.697369" + x2="11.226587" + y1="-5.4832759" + x1="11.226587" + gradientTransform="matrix(-0.420408,0,0,0.420404,15.54691,5.457116)" + gradientUnits="userSpaceOnUse" + id="linearGradient2343" + xlink:href="#linearGradient2186" + inkscape:collect="always" /> + <linearGradient + y2="48.674999" + x2="15.535398" + y1="1.8014067" + x1="15.535398" + gradientTransform="matrix(-0.296523,0,0,0.296522,15.24437,5.75564)" + gradientUnits="userSpaceOnUse" + id="linearGradient2345" + xlink:href="#linearGradient2239" + inkscape:collect="always" /> + <radialGradient + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1,0,0,0.626667,0,6.566431)" + r="6.3436799" + fy="17.588654" + fx="11.756953" + cy="17.588654" + cx="11.756953" + id="radialGradient2511" + xlink:href="#linearGradient2260" + inkscape:collect="always" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2186" + id="linearGradient2583" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-0.420408,0,0,0.420404,23.273502,-1.8126311)" + x1="11.226587" + y1="-5.4832759" + x2="11.226587" + y2="17.697369" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient2585" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-0.296523,0,0,0.296522,22.970962,-1.5141071)" + x1="15.535398" + y1="1.8014067" + x2="15.535398" + y2="48.674999" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2851" + id="linearGradient2597" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.358865,0,0,0.358865,-0.920117,-0.8061648)" + x1="6.878005" + y1="11.789385" + x2="12.233074" + y2="27.77807" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3149" + id="linearGradient2599" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.2870918,0,0,0.287092,0.3639019,0.4550689)" + x1="15.498499" + y1="9.4211226" + x2="24.240097" + y2="36.603138" /> + <linearGradient + y2="40" + x2="21.875" + y1="48.000977" + x1="21.875" + gradientUnits="userSpaceOnUse" + id="linearGradient2713" + xlink:href="#linearGradient2804" + inkscape:collect="always" /> + <radialGradient + r="5" + fy="44" + fx="1" + cy="44" + cx="1" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + gradientUnits="userSpaceOnUse" + id="radialGradient2711" + xlink:href="#linearGradient2781" + inkscape:collect="always" /> + <radialGradient + r="5" + fy="44" + fx="1" + cy="44" + cx="1" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + gradientUnits="userSpaceOnUse" + id="radialGradient2709" + xlink:href="#linearGradient2781" + inkscape:collect="always" /> + <linearGradient + gradientTransform="matrix(0.36035,0,0,0.358865,4.074001,4.193834)" + y2="27.77807" + x2="12.233074" + y1="11.789385" + x1="6.878005" + gradientUnits="userSpaceOnUse" + id="linearGradient2707" + xlink:href="#linearGradient2851" + inkscape:collect="always" /> + <linearGradient + gradientTransform="matrix(0.287092,0,0,0.287092,5.363906,5.455062)" + y2="34.458977" + x2="17.890068" + y1="2.2464287" + x1="17.890068" + gradientUnits="userSpaceOnUse" + id="linearGradient2705" + xlink:href="#linearGradient3149" + inkscape:collect="always" /> + <linearGradient + id="linearGradient2693"> + <stop + style="stop-color:#73d216;stop-opacity:1;" + offset="0" + id="stop2695" /> + <stop + style="stop-color:#5ca911;stop-opacity:1;" + offset="1" + id="stop2697" /> + </linearGradient> + <linearGradient + id="linearGradient2685"> + <stop + style="stop-color:black;stop-opacity:0;" + offset="0" + id="stop2687" /> + <stop + id="stop2689" + offset="0.5" + style="stop-color:black;stop-opacity:1;" /> + <stop + style="stop-color:black;stop-opacity:0;" + offset="1" + id="stop2691" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient2683" + gradientUnits="userSpaceOnUse" + x1="21.875" + y1="48.000977" + x2="21.875" + y2="40" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient2681" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient2673" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <linearGradient + y2="17.697369" + x2="11.226587" + y1="-5.4832759" + x1="11.226587" + gradientTransform="matrix(-0.420408,0,0,0.420404,15.54691,5.457116)" + gradientUnits="userSpaceOnUse" + id="linearGradient2671" + xlink:href="#linearGradient2186" + inkscape:collect="always" /> + <linearGradient + y2="48.674999" + x2="15.535398" + y1="1.8014067" + x1="15.535398" + gradientTransform="matrix(-0.296523,0,0,0.296522,15.24437,5.75564)" + gradientUnits="userSpaceOnUse" + id="linearGradient2663" + xlink:href="#linearGradient2239" + inkscape:collect="always" /> + <radialGradient + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1,0,0,0.626667,0,6.566431)" + r="6.3436799" + fy="17.588654" + fx="11.756953" + cy="17.588654" + cx="11.756953" + id="radialGradient2655" + xlink:href="#linearGradient2260" + inkscape:collect="always" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient2727" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient2729" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient2731" + gradientUnits="userSpaceOnUse" + x1="21.875" + y1="48.000977" + x2="21.875" + y2="40" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2186" + id="linearGradient2733" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-0.420408,0,0,0.420404,15.54691,5.457116)" + x1="11.226587" + y1="-5.4832759" + x2="11.226587" + y2="17.697369" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient2735" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-0.296523,0,0,0.296522,15.24437,5.75564)" + x1="15.535398" + y1="1.8014067" + x2="15.535398" + y2="48.674999" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2186" + id="linearGradient2739" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-0.420408,0,0,0.420404,10.546911,0.4571158)" + x1="11.226587" + y1="-5.4832759" + x2="11.226587" + y2="17.697369" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient2741" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-0.296523,0,0,0.296522,10.244371,0.7556398)" + x1="15.535398" + y1="1.8014067" + x2="15.535398" + y2="48.674999" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="31.392433" + inkscape:cx="16.517697" + inkscape:cy="5.0346503" + inkscape:current-layer="layer1" + showgrid="true" + inkscape:grid-bbox="true" + inkscape:document-units="px" + inkscape:window-width="1440" + inkscape:window-height="847" + inkscape:window-x="0" + inkscape:window-y="0" + width="11px" + height="11px" /> + <metadata + id="metadata1877"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + id="layer1" + inkscape:label="Layer 1" + inkscape:groupmode="layer"> + <path + sodipodi:type="arc" + style="color:#000000;fill:#ef2929;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.36561811px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" + id="path1311" + sodipodi:cx="15.590227" + sodipodi:cy="16.57217" + sodipodi:rx="14.345175" + sodipodi:ry="14.345175" + d="M 29.935402 16.57217 A 14.345175 14.345175 0 1 1 1.2450523,16.57217 A 14.345175 14.345175 0 1 1 29.935402 16.57217 z" + transform="matrix(-0.359512,0,0,0.359513,11.065161,-0.4895062)" /> + <path + sodipodi:type="arc" + style="color:#000000;fill:#ef2929;fill-opacity:1;fill-rule:evenodd;stroke:#a40000;stroke-width:2.86904168px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" + id="path2325" + sodipodi:cx="15.590227" + sodipodi:cy="16.57217" + sodipodi:rx="14.345175" + sodipodi:ry="14.345175" + d="M 29.935402 16.57217 A 14.345175 14.345175 0 1 1 1.2450523,16.57217 A 14.345175 14.345175 0 1 1 29.935402 16.57217 z" + transform="matrix(-0.348549,0,0,0.348549,10.933961,-0.2762162)" /> + <path + style="opacity:0.6;color:#000000;fill:url(#linearGradient2739);fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient2741);stroke-width:0.99999988px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" + d="M 1.5000029,5.5000048 C 1.5000029,7.7080048 3.2920029,9.5000073 5.5000039,9.5000073 C 7.7080029,9.5000073 9.5000039,7.7080048 9.5000039,5.5000048 C 9.5000039,3.2920029 7.7080029,1.5000022 5.5000039,1.5000022 C 3.2920029,1.5000022 1.5000029,3.2920029 1.5000029,5.5000048 z " + id="path2327" /> + <rect + style="opacity:1;fill:#eeeeec;fill-opacity:1;stroke:#a40000;stroke-width:0.99999994;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect2921" + width="6.0000005" + height="1.9999999" + x="2.5" + y="4.5" /> + </g> +</svg>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pidgin/pixmaps/status/11/scalable/chat.svg Mon Aug 27 21:59:11 2007 +0000 @@ -0,0 +1,272 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://web.resource.org/cc/" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="11" + height="11" + id="svg7380" + sodipodi:version="0.32" + inkscape:version="0.45.1" + sodipodi:docbase="/home/hbons/Desktop" + sodipodi:docname="chat.svg" + inkscape:export-filename="/home/hbons/Desktop/chat.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" + inkscape:output_extension="org.inkscape.output.svg.inkscape" + version="1.0"> + <defs + id="defs7382"> + <linearGradient + id="linearGradient3800"> + <stop + style="stop-color:#f4d9b1;stop-opacity:1.0000000;" + offset="0.0000000" + id="stop3802" /> + <stop + style="stop-color:#df9725;stop-opacity:1.0000000;" + offset="1.0000000" + id="stop3804" /> + </linearGradient> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3800" + id="radialGradient4171" + gradientUnits="userSpaceOnUse" + cx="27.702486" + cy="14.540437" + fx="27.702486" + fy="14.540437" + r="9.1620579" + gradientTransform="matrix(1.191087,0,0,1.124022,-5.086983,-1.361697)" /> + <linearGradient + inkscape:collect="always" + id="linearGradient7300"> + <stop + style="stop-color:#eeeeec;stop-opacity:1;" + offset="0" + id="stop7302" /> + <stop + style="stop-color:#eeeeec;stop-opacity:0;" + offset="1" + id="stop7304" /> + </linearGradient> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient7300" + id="radialGradient7306" + cx="24.248138" + cy="27.184834" + fx="24.248138" + fy="27.184834" + r="12.499089" + gradientTransform="matrix(0.964825,0,0,0.631898,0.954495,11.94073)" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + id="linearGradient3816"> + <stop + style="stop-color:#000000;stop-opacity:1;" + offset="0" + id="stop3818" /> + <stop + style="stop-color:#000000;stop-opacity:0;" + offset="1" + id="stop3820" /> + </linearGradient> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3816" + id="radialGradient4179" + gradientUnits="userSpaceOnUse" + cx="31.112698" + cy="19.008621" + fx="31.112698" + fy="19.008621" + r="8.6620579" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient7300" + id="radialGradient4244" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.964825,0,0,0.631898,0.954495,11.94073)" + cx="24.248138" + cy="27.184834" + fx="24.248138" + fy="27.184834" + r="12.499089" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3800" + id="radialGradient4246" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.191087,0,0,1.124022,-5.086983,-1.361697)" + cx="27.702486" + cy="14.540437" + fx="27.702486" + fy="14.540437" + r="9.1620579" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient7300" + id="radialGradient2631" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.964825,0,0,0.631898,0.954495,11.94073)" + cx="24.248138" + cy="27.184834" + fx="24.248138" + fy="27.184834" + r="12.499089" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3800" + id="radialGradient2633" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.191087,0,0,1.124022,-5.086983,-1.361697)" + cx="27.702486" + cy="14.540437" + fx="27.702486" + fy="14.540437" + r="9.1620579" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient7300" + id="radialGradient2188" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.964825,0,0,0.631898,0.954495,11.94073)" + cx="24.248138" + cy="27.184834" + fx="24.248138" + fy="27.184834" + r="12.499089" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3800" + id="radialGradient2190" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.191087,0,0,1.124022,-5.086983,-1.361697)" + cx="27.702486" + cy="14.540437" + fx="27.702486" + fy="14.540437" + r="9.1620579" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="36.060436" + inkscape:cx="12.098289" + inkscape:cy="6.1866582" + inkscape:current-layer="layer1" + showgrid="true" + inkscape:grid-bbox="true" + inkscape:document-units="px" + inkscape:window-width="1440" + inkscape:window-height="843" + inkscape:window-x="0" + inkscape:window-y="0" + width="11px" + height="11px" /> + <metadata + id="metadata7385"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + id="layer1" + inkscape:label="Layer 1" + inkscape:groupmode="layer"> + <path + style="opacity:1;color:#000000;fill:#729fcf;fill-opacity:1;fill-rule:evenodd;stroke:#3465a4;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" + d="M 5.6663217,10.5 L 8.5076604,10.5 C 9.3127059,10.5 10.109736,10.185178 10.401886,9.2878789 C 10.679316,8.4357864 10.449241,6.8131316 8.6497271,5.5000004 L 5.2874764,5.5000004 C 3.4879623,6.7121213 3.26308,8.3698055 3.677385,9.3383838 C 4.0994615,10.32513 4.8139201,10.5 5.6663217,10.5 z " + id="path2178" + sodipodi:nodetypes="cczcczc" /> + <path + sodipodi:type="inkscape:offset" + inkscape:radius="-1.1784238" + inkscape:original="M 24.5625 24.125 C 17.844986 28.367641 17.015916 34.172303 18.5625 37.5625 C 20.138096 41.016289 22.818019 41.625 26 41.625 L 36.59375 41.625 C 39.598953 41.624999 42.565667 40.546959 43.65625 37.40625 C 44.691891 34.423774 43.842514 28.721194 37.125 24.125 L 24.5625 24.125 z " + style="opacity:0.45454544;color:#000000;fill:url(#radialGradient2188);fill-opacity:1;fill-rule:evenodd;stroke:#eeeeec;stroke-width:4.89376259px;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" + id="path2180" + d="M 24.96875,25.3125 C 18.887883,29.293056 18.373983,34.320202 19.625,37.0625 C 20.318936,38.583645 21.166625,39.341162 22.1875,39.8125 C 23.208375,40.283838 24.484153,40.4375 26,40.4375 L 36.59375,40.4375 C 37.955442,40.4375 39.252462,40.19959 40.28125,39.65625 C 41.310038,39.11291 42.08087,38.328274 42.53125,37.03125 C 43.335253,34.715853 42.805994,29.63256 36.71875,25.3125 L 24.96875,25.3125 z " + transform="matrix(0.2105175,0,0,0.1983472,0.4849292,1.4793376)" /> + <path + style="opacity:0.78977272;fill:#eeeeec;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1" + d="M 8.9999998,7.5000004 C 8.9999998,8.3280004 7.9468851,8.5707392 7.0000001,9.0000002 C 5.6603268,8.5959901 4.9999998,8.3280004 4.9999998,7.5000004 C 4.9999998,6.6720007 5.8959997,6.0000002 7.0000001,6.0000002 C 8.1039998,6.0000002 8.9999998,6.6720007 8.9999998,7.5000004 z " + id="path2182" + sodipodi:nodetypes="ccssc" /> + <path + sodipodi:type="arc" + style="opacity:1;color:#000000;fill:url(#radialGradient2190);fill-opacity:1;fill-rule:evenodd;stroke:#b2730d;stroke-width:2.47487783px;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" + id="path2184" + sodipodi:cx="31.112698" + sodipodi:cy="19.008621" + sodipodi:rx="8.6620579" + sodipodi:ry="8.6620579" + d="M 39.774755 19.008621 A 8.6620579 8.6620579 0 1 1 22.45064,19.008621 A 8.6620579 8.6620579 0 1 1 39.774755 19.008621 z" + transform="matrix(0.4040609,0,0,0.4040609,-5.571426,-3.680641)" /> + <path + d="M 39.774755 19.008621 A 8.6620579 8.6620579 0 1 1 22.45064,19.008621 A 8.6620579 8.6620579 0 1 1 39.774755 19.008621 z" + sodipodi:ry="8.6620579" + sodipodi:rx="8.6620579" + sodipodi:cy="19.008621" + sodipodi:cx="31.112698" + id="path2186" + style="opacity:0.25;color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:3.46482706px;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" + sodipodi:type="arc" + transform="matrix(0.288615,0,0,0.288615,-1.9795919,-1.4861727)" /> + <path + style="opacity:1;color:#000000;fill:#ad7fa8;fill-opacity:1;fill-rule:evenodd;stroke:#5c3566;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" + d="M 2.6663227,10.5 L 5.5076614,10.5 C 6.3127069,10.5 7.1097368,10.185178 7.4018867,9.2878787 C 7.6793171,8.4357862 7.4492418,6.8131314 5.6497281,5.5000002 L 2.2874774,5.5000002 C 0.48796329,6.7121211 0.26308099,8.3698053 0.67738599,9.3383836 C 1.0994625,10.32513 1.8139211,10.5 2.6663227,10.5 z " + id="path4308" + sodipodi:nodetypes="cczcczc" /> + <path + sodipodi:type="inkscape:offset" + inkscape:radius="-1.1784238" + inkscape:original="M 24.5625 24.125 C 17.844986 28.367641 17.015916 34.172303 18.5625 37.5625 C 20.138096 41.016289 22.818019 41.625 26 41.625 L 36.59375 41.625 C 39.598953 41.624999 42.565667 40.546959 43.65625 37.40625 C 44.691891 34.423774 43.842514 28.721194 37.125 24.125 L 24.5625 24.125 z " + style="opacity:0.45454544;color:#000000;fill:url(#radialGradient2631);fill-opacity:1;fill-rule:evenodd;stroke:#eeeeec;stroke-width:4.89376259px;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" + id="path7281" + d="M 24.96875,25.3125 C 18.887883,29.293056 18.373983,34.320202 19.625,37.0625 C 20.318936,38.583645 21.166625,39.341162 22.1875,39.8125 C 23.208375,40.283838 24.484153,40.4375 26,40.4375 L 36.59375,40.4375 C 37.955442,40.4375 39.252462,40.19959 40.28125,39.65625 C 41.310038,39.11291 42.08087,38.328274 42.53125,37.03125 C 43.335253,34.715853 42.805994,29.63256 36.71875,25.3125 L 24.96875,25.3125 z " + transform="matrix(0.2105175,0,0,0.1983472,-2.5150698,1.4793374)" /> + <path + style="opacity:0.78977272;fill:#eeeeec;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1" + d="M 6.0000008,7.5000002 C 6.0000008,8.3280002 4.9468861,8.570739 4.0000011,9 C 2.6603278,8.5959899 2.0000008,8.3280002 2.0000008,7.5000002 C 2.0000008,6.6720005 2.8960007,6 4.0000011,6 C 5.1040008,6 6.0000008,6.6720005 6.0000008,7.5000002 z " + id="path7285" + sodipodi:nodetypes="ccssc" /> + <path + sodipodi:type="arc" + style="opacity:1;color:#000000;fill:url(#radialGradient2633);fill-opacity:1;fill-rule:evenodd;stroke:#b2730d;stroke-width:2.47487783px;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" + id="path4320" + sodipodi:cx="31.112698" + sodipodi:cy="19.008621" + sodipodi:rx="8.6620579" + sodipodi:ry="8.6620579" + d="M 39.774755 19.008621 A 8.6620579 8.6620579 0 1 1 22.45064,19.008621 A 8.6620579 8.6620579 0 1 1 39.774755 19.008621 z" + transform="matrix(0.4040609,0,0,0.4040609,-8.571425,-3.6806412)" /> + <path + d="M 39.774755 19.008621 A 8.6620579 8.6620579 0 1 1 22.45064,19.008621 A 8.6620579 8.6620579 0 1 1 39.774755 19.008621 z" + sodipodi:ry="8.6620579" + sodipodi:rx="8.6620579" + sodipodi:cy="19.008621" + sodipodi:cx="31.112698" + id="path4322" + style="opacity:0.25;color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:3.46482706px;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" + sodipodi:type="arc" + transform="matrix(0.288615,0,0,0.288615,-4.9795909,-1.4861729)" /> + </g> +</svg>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pidgin/pixmaps/status/11/scalable/extended-away.svg Mon Aug 27 21:59:11 2007 +0000 @@ -0,0 +1,2809 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://web.resource.org/cc/" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="11" + height="11" + id="svg1872" + sodipodi:version="0.32" + inkscape:version="0.45.1" + sodipodi:docbase="/home/hbons/Desktop/tabs" + sodipodi:docname="extended-away.svg" + inkscape:output_extension="org.inkscape.output.svg.inkscape" + version="1.0" + inkscape:export-filename="/home/hbons/Desktop/tabs/extended-away.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90"> + <defs + id="defs1874"> + <radialGradient + r="5" + fy="44" + fx="1" + cy="44" + cx="1" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + gradientUnits="userSpaceOnUse" + id="radialGradient7751" + xlink:href="#linearGradient2781" + inkscape:collect="always" /> + <linearGradient + id="linearGradient2781" + inkscape:collect="always"> + <stop + id="stop2783" + offset="0" + style="stop-color:black;stop-opacity:1;" /> + <stop + id="stop2785" + offset="1" + style="stop-color:black;stop-opacity:0;" /> + </linearGradient> + <radialGradient + r="5" + fy="44" + fx="1" + cy="44" + cx="1" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + gradientUnits="userSpaceOnUse" + id="radialGradient7753" + xlink:href="#linearGradient2781" + inkscape:collect="always" /> + <linearGradient + y2="40" + x2="21.875" + y1="48.000977" + x1="21.875" + gradientUnits="userSpaceOnUse" + id="linearGradient7755" + xlink:href="#linearGradient2804" + inkscape:collect="always" /> + <linearGradient + id="linearGradient2804"> + <stop + id="stop2806" + offset="0" + style="stop-color:black;stop-opacity:0;" /> + <stop + style="stop-color:black;stop-opacity:1;" + offset="0.5" + id="stop2812" /> + <stop + id="stop2808" + offset="1" + style="stop-color:black;stop-opacity:0;" /> + </linearGradient> + <linearGradient + id="linearGradient2851"> + <stop + id="stop2853" + offset="0" + style="stop-color:#73d216;stop-opacity:1;" /> + <stop + id="stop2855" + offset="1" + style="stop-color:#5ca911;stop-opacity:1;" /> + </linearGradient> + <linearGradient + id="linearGradient3149" + inkscape:collect="always"> + <stop + id="stop3151" + offset="0" + style="stop-color:#eeeeec;stop-opacity:1;" /> + <stop + id="stop3153" + offset="1" + style="stop-color:#eeeeec;stop-opacity:0;" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3149" + id="linearGradient1956" + gradientUnits="userSpaceOnUse" + x1="17.890068" + y1="2.2464287" + x2="17.890068" + y2="34.458977" + gradientTransform="matrix(0.287092,0,0,0.287092,5.363906,5.455062)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2851" + id="linearGradient1959" + gradientUnits="userSpaceOnUse" + x1="6.878005" + y1="11.789385" + x2="12.233074" + y2="27.77807" + gradientTransform="matrix(0.36035,0,0,0.358865,4.074001,4.193834)" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient1970" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient1972" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient1974" + gradientUnits="userSpaceOnUse" + x1="21.875" + y1="48.000977" + x2="21.875" + y2="40" /> + <linearGradient + inkscape:collect="always" + id="linearGradient2898"> + <stop + style="stop-color:white;stop-opacity:1;" + offset="0" + id="stop2900" /> + <stop + style="stop-color:white;stop-opacity:0;" + offset="1" + id="stop2902" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2851" + id="linearGradient4738" + gradientUnits="userSpaceOnUse" + x1="6.878005" + y1="11.789385" + x2="12.233074" + y2="27.77807" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3149" + id="linearGradient4740" + gradientUnits="userSpaceOnUse" + x1="15.498499" + y1="9.4211226" + x2="24.240097" + y2="36.603138" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3149" + id="linearGradient3044" + gradientUnits="userSpaceOnUse" + x1="17.890068" + y1="8.0617304" + x2="17.890068" + y2="40.032413" /> + <linearGradient + id="linearGradient3046"> + <stop + style="stop-color:#73d216;stop-opacity:1;" + offset="0" + id="stop3048" /> + <stop + style="stop-color:#5ca911;stop-opacity:1;" + offset="1" + id="stop3050" /> + </linearGradient> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3816" + id="radialGradient3064" + cx="31.112698" + cy="19.008621" + fx="31.112698" + fy="19.008621" + r="8.6620579" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.914124,0,0,1.631747,2.671799,-12.00863)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2851" + id="linearGradient3066" + x1="6.878005" + y1="11.789385" + x2="12.233074" + y2="27.77807" + gradientUnits="userSpaceOnUse" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2898" + id="radialGradient2904" + cx="4.8470273" + cy="6.9473476" + fx="4.8470273" + fy="6.9473476" + r="0.8078171" + gradientTransform="matrix(3.018423,0.664359,-1.388844,4.257661,-0.134567,-26.02469)" + gradientUnits="userSpaceOnUse" /> + <radialGradient + gradientUnits="userSpaceOnUse" + r="8.6620579" + fy="19.008621" + fx="31.112698" + cy="19.008621" + cx="31.112698" + id="radialGradient2818" + xlink:href="#linearGradient2812" + inkscape:collect="always" /> + <linearGradient + gradientUnits="userSpaceOnUse" + y2="11.024895" + x2="10.623409" + y1="2.7991772" + x1="4.5264969" + id="linearGradient2810" + xlink:href="#linearGradient2804" + inkscape:collect="always" /> + <linearGradient + gradientUnits="userSpaceOnUse" + y2="27.77807" + x2="12.233074" + y1="11.789385" + x1="6.878005" + id="linearGradient2963" + xlink:href="#linearGradient2851" + inkscape:collect="always" /> + <linearGradient + id="linearGradient2951"> + <stop + id="stop2953" + offset="0" + style="stop-color:#73d216;stop-opacity:1;" /> + <stop + id="stop2955" + offset="1" + style="stop-color:#5ca911;stop-opacity:1;" /> + </linearGradient> + <linearGradient + y2="40.032413" + x2="17.890068" + y1="8.0617304" + x1="17.890068" + gradientUnits="userSpaceOnUse" + id="linearGradient2949" + xlink:href="#linearGradient3149" + inkscape:collect="always" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2812" + id="radialGradient3005" + gradientUnits="userSpaceOnUse" + cx="31.112698" + cy="19.008621" + fx="31.112698" + fy="19.008621" + r="8.6620579" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient3007" + gradientUnits="userSpaceOnUse" + x1="4.5264969" + y1="2.7991772" + x2="10.623409" + y2="11.024895" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2812" + id="radialGradient3025" + gradientUnits="userSpaceOnUse" + cx="31.112698" + cy="19.008621" + fx="31.112698" + fy="19.008621" + r="8.6620579" /> + <linearGradient + gradientUnits="userSpaceOnUse" + y2="10.018044" + x2="10.043059" + y1="1.3319674" + x1="1.5769236" + id="linearGradient2995" + xlink:href="#linearGradient2989" + inkscape:collect="always" /> + <radialGradient + r="8.6620579" + fy="19.008621" + fx="31.112698" + cy="19.008621" + cx="31.112698" + gradientUnits="userSpaceOnUse" + id="radialGradient2084" + xlink:href="#linearGradient2812" + inkscape:collect="always" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3149" + id="linearGradient2046" + gradientUnits="userSpaceOnUse" + x1="17.890068" + y1="8.0617304" + x2="17.890068" + y2="40.032413" /> + <linearGradient + id="linearGradient2048"> + <stop + style="stop-color:#73d216;stop-opacity:1;" + offset="0" + id="stop2050" /> + <stop + style="stop-color:#5ca911;stop-opacity:1;" + offset="1" + id="stop2052" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2851" + id="linearGradient2060" + x1="6.878005" + y1="11.789385" + x2="12.233074" + y2="27.77807" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient2062" + x1="4.5264969" + y1="2.7991772" + x2="10.623409" + y2="11.024895" + gradientUnits="userSpaceOnUse" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2812" + id="radialGradient2064" + cx="31.112698" + cy="19.008621" + fx="31.112698" + fy="19.008621" + r="8.6620579" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + id="linearGradient2812"> + <stop + style="stop-color:#2e3436;stop-opacity:1;" + offset="0" + id="stop2814" /> + <stop + style="stop-color:#2e3436;stop-opacity:0;" + offset="1" + id="stop2816" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3149" + id="linearGradient2269" + gradientUnits="userSpaceOnUse" + x1="17.890068" + y1="8.0617304" + x2="17.890068" + y2="40.032413" /> + <linearGradient + id="linearGradient2055"> + <stop + style="stop-color:#73d216;stop-opacity:1;" + offset="0" + id="stop2057" /> + <stop + style="stop-color:#5ca911;stop-opacity:1;" + offset="1" + id="stop2059" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2851" + id="linearGradient2857" + x1="6.878005" + y1="11.789385" + x2="12.233074" + y2="27.77807" + gradientUnits="userSpaceOnUse" /> + <linearGradient + y2="14.895812" + x2="11.802028" + y1="1.9986149" + x1="11.802028" + gradientUnits="userSpaceOnUse" + id="linearGradient6606" + xlink:href="#linearGradient2225" + inkscape:collect="always" /> + <linearGradient + y2="48.674999" + x2="15.535398" + y1="1.8014067" + x1="15.535398" + gradientTransform="matrix(0.37378,0,0,0.375227,17.64779,15.86312)" + gradientUnits="userSpaceOnUse" + id="linearGradient2339" + xlink:href="#linearGradient2239" + inkscape:collect="always" /> + <linearGradient + y2="17.697369" + x2="11.226587" + y1="-5.4832759" + x1="11.226587" + gradientTransform="matrix(0.529942,0,0,0.53199,17.26643,15.48536)" + gradientUnits="userSpaceOnUse" + id="linearGradient2337" + xlink:href="#linearGradient2186" + inkscape:collect="always" /> + <linearGradient + y2="33.483475" + x2="15.522223" + y1="1.5657365" + x1="15.602553" + gradientTransform="matrix(0.371983,0,0,0.372254,2.539836,8.539528)" + gradientUnits="userSpaceOnUse" + id="linearGradient1357" + xlink:href="#linearGradient2239" + inkscape:collect="always" /> + <linearGradient + inkscape:collect="always" + id="linearGradient2239"> + <stop + style="stop-color:#ffffff;stop-opacity:1;" + offset="0" + id="stop2241" /> + <stop + style="stop-color:#ffffff;stop-opacity:0;" + offset="1" + id="stop2243" /> + </linearGradient> + <radialGradient + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1,0,0,0.626667,0,6.566431)" + r="6.3436799" + fy="17.588654" + fx="11.756953" + cy="17.588654" + cx="11.756953" + id="radialGradient2266" + xlink:href="#linearGradient2260" + inkscape:collect="always" /> + <radialGradient + r="7.003407" + fy="8.963316" + fx="9.9988937" + cy="8.963316" + cx="9.9988937" + gradientTransform="matrix(-2.522332,0,0,2.521765,40.1904,-21.80154)" + gradientUnits="userSpaceOnUse" + id="radialGradient2225" + xlink:href="#linearGradient2200" + inkscape:collect="always" /> + <radialGradient + r="7.003407" + fy="8.963316" + fx="9.9988937" + cy="8.963316" + cx="9.9988937" + gradientTransform="matrix(-2.522332,0,0,2.521765,40.1904,-21.83521)" + gradientUnits="userSpaceOnUse" + id="radialGradient2216" + xlink:href="#linearGradient2200" + inkscape:collect="always" /> + <linearGradient + id="linearGradient2200" + inkscape:collect="always"> + <stop + id="stop2202" + offset="0" + style="stop-color:#d3d7cf;stop-opacity:1;" /> + <stop + id="stop2204" + offset="1" + style="stop-color:#d3d7cf;stop-opacity:0;" /> + </linearGradient> + <radialGradient + gradientUnits="userSpaceOnUse" + r="8.6620579" + fy="19.008621" + fx="31.112698" + cy="19.008621" + cx="31.112698" + id="radialGradient3822" + xlink:href="#linearGradient3816" + inkscape:collect="always" /> + <linearGradient + id="linearGradient3816" + inkscape:collect="always"> + <stop + id="stop3818" + offset="0" + style="stop-color:#000000;stop-opacity:1;" /> + <stop + id="stop3820" + offset="1" + style="stop-color:#000000;stop-opacity:0;" /> + </linearGradient> + <linearGradient + id="linearGradient2260" + inkscape:collect="always"> + <stop + id="stop2262" + offset="0" + style="stop-color:#555753;stop-opacity:1;" /> + <stop + id="stop2264" + offset="1" + style="stop-color:#555753;stop-opacity:0;" /> + </linearGradient> + <linearGradient + gradientTransform="matrix(0.529942,0,0,0.53199,17.26643,15.48536)" + gradientUnits="userSpaceOnUse" + y2="17.697369" + x2="11.226587" + y1="-5.4832759" + x1="11.226587" + id="linearGradient2194" + xlink:href="#linearGradient2186" + inkscape:collect="always" /> + <linearGradient + id="linearGradient2186" + inkscape:collect="always"> + <stop + id="stop2188" + offset="0" + style="stop-color:#ffffff;stop-opacity:1;" /> + <stop + id="stop2190" + offset="1" + style="stop-color:#ffffff;stop-opacity:0;" /> + </linearGradient> + <linearGradient + gradientTransform="matrix(0.37378,0,0,0.375227,17.64779,15.86312)" + gradientUnits="userSpaceOnUse" + y2="48.674999" + x2="15.535398" + y1="1.8014067" + x1="15.535398" + id="linearGradient2245" + xlink:href="#linearGradient2239" + inkscape:collect="always" /> + <radialGradient + r="5" + fy="44" + fx="1" + cy="44" + cx="1" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + gradientUnits="userSpaceOnUse" + id="radialGradient2827" + xlink:href="#linearGradient2781" + inkscape:collect="always" /> + <radialGradient + r="5" + fy="44" + fx="1" + cy="44" + cx="1" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + gradientUnits="userSpaceOnUse" + id="radialGradient2829" + xlink:href="#linearGradient2781" + inkscape:collect="always" /> + <linearGradient + y2="40" + x2="21.875" + y1="48.000977" + x1="21.875" + gradientUnits="userSpaceOnUse" + id="linearGradient2831" + xlink:href="#linearGradient2804" + inkscape:collect="always" /> + <linearGradient + id="linearGradient2006"> + <stop + id="stop2008" + offset="0" + style="stop-color:black;stop-opacity:0;" /> + <stop + style="stop-color:black;stop-opacity:1;" + offset="0.5" + id="stop2010" /> + <stop + id="stop2012" + offset="1" + style="stop-color:black;stop-opacity:0;" /> + </linearGradient> + <linearGradient + y2="24.143761" + x2="27.2733" + y1="10.957423" + x1="35.003674" + gradientTransform="matrix(-0.977228,0,0,0.995878,50.60272,9.115637)" + gradientUnits="userSpaceOnUse" + id="linearGradient29443" + xlink:href="#linearGradient29418" + inkscape:collect="always" /> + <linearGradient + id="linearGradient29418"> + <stop + id="stop29420" + offset="0.0000000" + style="stop-color:#f5f5f5;stop-opacity:1.0000000;" /> + <stop + id="stop29422" + offset="1.0000000" + style="stop-color:#e9e9e9;stop-opacity:1.0000000;" /> + </linearGradient> + <linearGradient + id="linearGradient2225" + inkscape:collect="always"> + <stop + id="stop2227" + offset="0" + style="stop-color:#eeeeec;stop-opacity:1;" /> + <stop + id="stop2229" + offset="1" + style="stop-color:#eeeeec;stop-opacity:0;" /> + </linearGradient> + <linearGradient + id="linearGradient2989" + inkscape:collect="always"> + <stop + id="stop2991" + offset="0" + style="stop-color:#eeeeec;stop-opacity:1;" /> + <stop + id="stop2993" + offset="1" + style="stop-color:#eeeeec;stop-opacity:0;" /> + </linearGradient> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2812" + id="radialGradient2112" + gradientUnits="userSpaceOnUse" + cx="31.112698" + cy="19.008621" + fx="31.112698" + fy="19.008621" + r="8.6620579" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2851" + id="linearGradient2114" + gradientUnits="userSpaceOnUse" + x1="6.878005" + y1="11.789385" + x2="12.233074" + y2="27.77807" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3149" + id="linearGradient2116" + gradientUnits="userSpaceOnUse" + x1="15.498499" + y1="9.4211226" + x2="24.240097" + y2="36.603138" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3149" + id="linearGradient2119" + gradientUnits="userSpaceOnUse" + x1="15.498499" + y1="9.4211226" + x2="24.240097" + y2="36.603138" + gradientTransform="matrix(0.2512053,0,0,0.2512055,0.505914,0.5856851)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2851" + id="linearGradient2122" + gradientUnits="userSpaceOnUse" + x1="6.878005" + y1="11.789385" + x2="12.233074" + y2="27.77807" + gradientTransform="matrix(0.3229785,0,0,0.3229785,-0.7781054,-0.675548)" /> + <linearGradient + y2="40" + x2="21.875" + y1="48.000977" + x1="21.875" + gradientUnits="userSpaceOnUse" + id="linearGradient2567" + xlink:href="#linearGradient2804" + inkscape:collect="always" /> + <radialGradient + r="5" + fy="44" + fx="1" + cy="44" + cx="1" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + gradientUnits="userSpaceOnUse" + id="radialGradient2565" + xlink:href="#linearGradient2781" + inkscape:collect="always" /> + <radialGradient + r="5" + fy="44" + fx="1" + cy="44" + cx="1" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + gradientUnits="userSpaceOnUse" + id="radialGradient2563" + xlink:href="#linearGradient2781" + inkscape:collect="always" /> + <linearGradient + gradientTransform="matrix(0.36035,0,0,0.358865,4.074001,4.193834)" + y2="27.77807" + x2="12.233074" + y1="11.789385" + x1="6.878005" + gradientUnits="userSpaceOnUse" + id="linearGradient2561" + xlink:href="#linearGradient2851" + inkscape:collect="always" /> + <linearGradient + gradientTransform="matrix(0.287092,0,0,0.287092,5.363906,5.455062)" + y2="34.458977" + x2="17.890068" + y1="2.2464287" + x1="17.890068" + gradientUnits="userSpaceOnUse" + id="linearGradient2559" + xlink:href="#linearGradient3149" + inkscape:collect="always" /> + <linearGradient + id="linearGradient2547"> + <stop + style="stop-color:#73d216;stop-opacity:1;" + offset="0" + id="stop2549" /> + <stop + style="stop-color:#5ca911;stop-opacity:1;" + offset="1" + id="stop2551" /> + </linearGradient> + <linearGradient + id="linearGradient2539"> + <stop + style="stop-color:black;stop-opacity:0;" + offset="0" + id="stop2541" /> + <stop + id="stop2543" + offset="0.5" + style="stop-color:black;stop-opacity:1;" /> + <stop + style="stop-color:black;stop-opacity:0;" + offset="1" + id="stop2545" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient2537" + gradientUnits="userSpaceOnUse" + x1="21.875" + y1="48.000977" + x2="21.875" + y2="40" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient2535" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient2527" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <linearGradient + y2="17.697369" + x2="11.226587" + y1="-5.4832759" + x1="11.226587" + gradientTransform="matrix(-0.420408,0,0,0.420404,15.54691,5.457116)" + gradientUnits="userSpaceOnUse" + id="linearGradient2343" + xlink:href="#linearGradient2186" + inkscape:collect="always" /> + <linearGradient + y2="48.674999" + x2="15.535398" + y1="1.8014067" + x1="15.535398" + gradientTransform="matrix(-0.296523,0,0,0.296522,15.24437,5.75564)" + gradientUnits="userSpaceOnUse" + id="linearGradient2345" + xlink:href="#linearGradient2239" + inkscape:collect="always" /> + <radialGradient + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1,0,0,0.626667,0,6.566431)" + r="6.3436799" + fy="17.588654" + fx="11.756953" + cy="17.588654" + cx="11.756953" + id="radialGradient2511" + xlink:href="#linearGradient2260" + inkscape:collect="always" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2186" + id="linearGradient2583" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-0.420408,0,0,0.420404,23.273502,-1.8126311)" + x1="11.226587" + y1="-5.4832759" + x2="11.226587" + y2="17.697369" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient2585" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-0.296523,0,0,0.296522,22.970962,-1.5141071)" + x1="15.535398" + y1="1.8014067" + x2="15.535398" + y2="48.674999" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2851" + id="linearGradient2597" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.358865,0,0,0.358865,-0.920117,-0.8061648)" + x1="6.878005" + y1="11.789385" + x2="12.233074" + y2="27.77807" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3149" + id="linearGradient2599" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.2870918,0,0,0.287092,0.3639019,0.4550689)" + x1="15.498499" + y1="9.4211226" + x2="24.240097" + y2="36.603138" /> + <linearGradient + y2="40" + x2="21.875" + y1="48.000977" + x1="21.875" + gradientUnits="userSpaceOnUse" + id="linearGradient2713" + xlink:href="#linearGradient2804" + inkscape:collect="always" /> + <radialGradient + r="5" + fy="44" + fx="1" + cy="44" + cx="1" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + gradientUnits="userSpaceOnUse" + id="radialGradient2711" + xlink:href="#linearGradient2781" + inkscape:collect="always" /> + <radialGradient + r="5" + fy="44" + fx="1" + cy="44" + cx="1" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + gradientUnits="userSpaceOnUse" + id="radialGradient2709" + xlink:href="#linearGradient2781" + inkscape:collect="always" /> + <linearGradient + gradientTransform="matrix(0.36035,0,0,0.358865,4.074001,4.193834)" + y2="27.77807" + x2="12.233074" + y1="11.789385" + x1="6.878005" + gradientUnits="userSpaceOnUse" + id="linearGradient2707" + xlink:href="#linearGradient2851" + inkscape:collect="always" /> + <linearGradient + gradientTransform="matrix(0.287092,0,0,0.287092,5.363906,5.455062)" + y2="34.458977" + x2="17.890068" + y1="2.2464287" + x1="17.890068" + gradientUnits="userSpaceOnUse" + id="linearGradient2705" + xlink:href="#linearGradient3149" + inkscape:collect="always" /> + <linearGradient + id="linearGradient2693"> + <stop + style="stop-color:#73d216;stop-opacity:1;" + offset="0" + id="stop2695" /> + <stop + style="stop-color:#5ca911;stop-opacity:1;" + offset="1" + id="stop2697" /> + </linearGradient> + <linearGradient + id="linearGradient2685"> + <stop + style="stop-color:black;stop-opacity:0;" + offset="0" + id="stop2687" /> + <stop + id="stop2689" + offset="0.5" + style="stop-color:black;stop-opacity:1;" /> + <stop + style="stop-color:black;stop-opacity:0;" + offset="1" + id="stop2691" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient2683" + gradientUnits="userSpaceOnUse" + x1="21.875" + y1="48.000977" + x2="21.875" + y2="40" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient2681" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient2673" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <linearGradient + y2="17.697369" + x2="11.226587" + y1="-5.4832759" + x1="11.226587" + gradientTransform="matrix(-0.420408,0,0,0.420404,15.54691,5.457116)" + gradientUnits="userSpaceOnUse" + id="linearGradient2671" + xlink:href="#linearGradient2186" + inkscape:collect="always" /> + <linearGradient + y2="48.674999" + x2="15.535398" + y1="1.8014067" + x1="15.535398" + gradientTransform="matrix(-0.296523,0,0,0.296522,15.24437,5.75564)" + gradientUnits="userSpaceOnUse" + id="linearGradient2663" + xlink:href="#linearGradient2239" + inkscape:collect="always" /> + <radialGradient + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1,0,0,0.626667,0,6.566431)" + r="6.3436799" + fy="17.588654" + fx="11.756953" + cy="17.588654" + cx="11.756953" + id="radialGradient2655" + xlink:href="#linearGradient2260" + inkscape:collect="always" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient2727" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient2729" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient2731" + gradientUnits="userSpaceOnUse" + x1="21.875" + y1="48.000977" + x2="21.875" + y2="40" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2186" + id="linearGradient2733" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-0.420408,0,0,0.420404,15.54691,5.457116)" + x1="11.226587" + y1="-5.4832759" + x2="11.226587" + y2="17.697369" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient2735" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-0.296523,0,0,0.296522,15.24437,5.75564)" + x1="15.535398" + y1="1.8014067" + x2="15.535398" + y2="48.674999" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2186" + id="linearGradient2739" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-0.420408,0,0,0.420404,10.546911,0.4571158)" + x1="11.226587" + y1="-5.4832759" + x2="11.226587" + y2="17.697369" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient2741" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-0.296523,0,0,0.296522,10.244371,0.7556398)" + x1="15.535398" + y1="1.8014067" + x2="15.535398" + y2="48.674999" /> + <linearGradient + y2="10.018044" + x2="10.043059" + y1="1.3319674" + x1="1.5769236" + gradientUnits="userSpaceOnUse" + id="linearGradient2232" + xlink:href="#linearGradient2989" + inkscape:collect="always" /> + <linearGradient + id="linearGradient2098"> + <stop + style="stop-color:#f5f5f5;stop-opacity:1.0000000;" + offset="0.0000000" + id="stop2100" /> + <stop + style="stop-color:#e9e9e9;stop-opacity:1.0000000;" + offset="1.0000000" + id="stop2102" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient29418" + id="linearGradient2104" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-0.977228,0,0,0.995878,50.60272,9.115637)" + x1="35.003674" + y1="10.957423" + x2="27.273300" + y2="24.143761" /> + <linearGradient + id="linearGradient2106"> + <stop + style="stop-color:black;stop-opacity:0;" + offset="0" + id="stop2108" /> + <stop + id="stop2110" + offset="0.5" + style="stop-color:black;stop-opacity:1;" /> + <stop + style="stop-color:black;stop-opacity:0;" + offset="1" + id="stop2112" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient4258" + gradientUnits="userSpaceOnUse" + x1="21.875" + y1="48.000977" + x2="21.875" + y2="40" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient2116" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient2124" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient2126" + x1="15.535398" + y1="1.8014067" + x2="15.535398" + y2="48.674999" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.37378,0,0,0.375227,17.64779,15.86312)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2186" + id="linearGradient2134" + x1="11.226587" + y1="-5.4832759" + x2="11.226587" + y2="17.697369" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.529942,0,0,0.53199,17.26643,15.48536)" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3816" + id="radialGradient2148" + cx="31.112698" + cy="19.008621" + fx="31.112698" + fy="19.008621" + r="8.6620579" + gradientUnits="userSpaceOnUse" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2200" + id="radialGradient2156" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-2.522332,-1.518129e-16,-1.517788e-16,2.521765,40.1904,-21.83521)" + cx="9.9988937" + cy="8.963316" + fx="9.9988937" + fy="8.963316" + r="7.0034069" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2200" + id="radialGradient2158" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-2.522332,-1.518129e-16,-1.517788e-16,2.521765,40.1904,-21.80154)" + cx="9.9988937" + cy="8.963316" + fx="9.9988937" + fy="8.963316" + r="7.0034069" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2260" + id="radialGradient4249" + cx="11.756953" + cy="17.588654" + fx="11.756953" + fy="17.588654" + r="6.3436799" + gradientTransform="matrix(1,0,0,0.626667,0,6.566431)" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient4247" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.371983,0,0,0.372254,2.539836,8.539528)" + x1="15.602553" + y1="1.5657365" + x2="15.522223" + y2="33.483475" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2186" + id="linearGradient2168" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.529942,0,0,0.53199,17.26643,15.48536)" + x1="11.226587" + y1="-5.4832759" + x2="11.226587" + y2="17.697369" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient2170" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.37378,0,0,0.375227,17.64779,15.86312)" + x1="15.535398" + y1="1.8014067" + x2="15.535398" + y2="48.674999" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2225" + id="linearGradient4243" + gradientUnits="userSpaceOnUse" + x1="11.802028" + y1="1.9986149" + x2="11.802028" + y2="14.895812" /> + <linearGradient + gradientUnits="userSpaceOnUse" + y2="27.77807" + x2="12.233074" + y1="11.789385" + x1="6.878005" + id="linearGradient4241" + xlink:href="#linearGradient2851" + inkscape:collect="always" /> + <linearGradient + id="linearGradient2177"> + <stop + id="stop2179" + offset="0" + style="stop-color:#73d216;stop-opacity:1;" /> + <stop + id="stop2181" + offset="1" + style="stop-color:#5ca911;stop-opacity:1;" /> + </linearGradient> + <linearGradient + y2="40.032413" + x2="17.890068" + y1="8.0617304" + x1="17.890068" + gradientUnits="userSpaceOnUse" + id="linearGradient4230" + xlink:href="#linearGradient3149" + inkscape:collect="always" /> + <radialGradient + gradientUnits="userSpaceOnUse" + r="8.6620579" + fy="19.008621" + fx="31.112698" + cy="19.008621" + cx="31.112698" + id="radialGradient4222" + xlink:href="#linearGradient2812" + inkscape:collect="always" /> + <linearGradient + gradientUnits="userSpaceOnUse" + y2="11.024895" + x2="10.623409" + y1="2.7991772" + x1="4.5264969" + id="linearGradient4220" + xlink:href="#linearGradient2804" + inkscape:collect="always" /> + <linearGradient + gradientUnits="userSpaceOnUse" + y2="27.77807" + x2="12.233074" + y1="11.789385" + x1="6.878005" + id="linearGradient4218" + xlink:href="#linearGradient2851" + inkscape:collect="always" /> + <linearGradient + id="linearGradient4212"> + <stop + id="stop4214" + offset="0" + style="stop-color:#73d216;stop-opacity:1;" /> + <stop + id="stop4216" + offset="1" + style="stop-color:#5ca911;stop-opacity:1;" /> + </linearGradient> + <linearGradient + y2="40.032413" + x2="17.890068" + y1="8.0617304" + x1="17.890068" + gradientUnits="userSpaceOnUse" + id="linearGradient4210" + xlink:href="#linearGradient3149" + inkscape:collect="always" /> + <linearGradient + id="linearGradient3292"> + <stop + style="stop-color:#f5f5f5;stop-opacity:1.0000000;" + offset="0.0000000" + id="stop3294" /> + <stop + style="stop-color:#e9e9e9;stop-opacity:1.0000000;" + offset="1.0000000" + id="stop3296" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient29418" + id="linearGradient3298" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-0.977228,0,0,0.995878,50.60272,9.115637)" + x1="35.003674" + y1="10.957423" + x2="27.273300" + y2="24.143761" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient3300" + gradientUnits="userSpaceOnUse" + x1="21.875" + y1="48.000977" + x2="21.875" + y2="40" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient3302" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient3304" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <linearGradient + id="linearGradient3306"> + <stop + style="stop-color:black;stop-opacity:0;" + offset="0" + id="stop3308" /> + <stop + id="stop3310" + offset="0.5" + style="stop-color:black;stop-opacity:1;" /> + <stop + style="stop-color:black;stop-opacity:0;" + offset="1" + id="stop3312" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient3314" + gradientUnits="userSpaceOnUse" + x1="21.875" + y1="48.000977" + x2="21.875" + y2="40" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient3316" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient3324" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient3326" + x1="15.535398" + y1="1.8014067" + x2="15.535398" + y2="48.674999" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.37378,0,0,0.375227,17.64779,15.86312)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2186" + id="linearGradient3334" + x1="11.226587" + y1="-5.4832759" + x2="11.226587" + y2="17.697369" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.529942,0,0,0.53199,17.26643,15.48536)" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3816" + id="radialGradient3348" + cx="31.112698" + cy="19.008621" + fx="31.112698" + fy="19.008621" + r="8.6620579" + gradientUnits="userSpaceOnUse" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2200" + id="radialGradient3356" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-2.522332,-1.518129e-16,-1.517788e-16,2.521765,40.1904,-21.83521)" + cx="9.9988937" + cy="8.963316" + fx="9.9988937" + fy="8.963316" + r="7.0034069" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2200" + id="radialGradient3358" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-2.522332,-1.518129e-16,-1.517788e-16,2.521765,40.1904,-21.80154)" + cx="9.9988937" + cy="8.963316" + fx="9.9988937" + fy="8.963316" + r="7.0034069" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2260" + id="radialGradient3360" + cx="11.756953" + cy="17.588654" + fx="11.756953" + fy="17.588654" + r="6.3436799" + gradientTransform="matrix(1,0,0,0.626667,0,6.566431)" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient3368" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.371983,0,0,0.372254,2.539836,8.539528)" + x1="15.602553" + y1="1.5657365" + x2="15.522223" + y2="33.483475" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2186" + id="linearGradient3370" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.529942,0,0,0.53199,17.26643,15.48536)" + x1="11.226587" + y1="-5.4832759" + x2="11.226587" + y2="17.697369" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient3372" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.37378,0,0,0.375227,17.64779,15.86312)" + x1="15.535398" + y1="1.8014067" + x2="15.535398" + y2="48.674999" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2225" + id="linearGradient3374" + gradientUnits="userSpaceOnUse" + x1="11.802028" + y1="1.9986149" + x2="11.802028" + y2="14.895812" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2225" + id="linearGradient2231" + x1="11.802028" + y1="1.9986149" + x2="11.802028" + y2="14.895812" + gradientUnits="userSpaceOnUse" /> + <linearGradient + id="linearGradient3093"> + <stop + style="stop-color:#f5f5f5;stop-opacity:1.0000000;" + offset="0.0000000" + id="stop3095" /> + <stop + style="stop-color:#e9e9e9;stop-opacity:1.0000000;" + offset="1.0000000" + id="stop3097" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient29418" + id="linearGradient3099" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-0.977228,0,0,0.995878,50.60272,9.115637)" + x1="35.003674" + y1="10.957423" + x2="27.273300" + y2="24.143761" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient3101" + gradientUnits="userSpaceOnUse" + x1="21.875" + y1="48.000977" + x2="21.875" + y2="40" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient3103" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient3105" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <linearGradient + id="linearGradient3107"> + <stop + style="stop-color:black;stop-opacity:0;" + offset="0" + id="stop3109" /> + <stop + id="stop3111" + offset="0.5" + style="stop-color:black;stop-opacity:1;" /> + <stop + style="stop-color:black;stop-opacity:0;" + offset="1" + id="stop3113" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient3115" + gradientUnits="userSpaceOnUse" + x1="21.875" + y1="48.000977" + x2="21.875" + y2="40" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient3117" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient3125" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient3127" + x1="15.535398" + y1="1.8014067" + x2="15.535398" + y2="48.674999" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.37378,0,0,0.375227,17.64779,15.86312)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2186" + id="linearGradient3135" + x1="11.226587" + y1="-5.4832759" + x2="11.226587" + y2="17.697369" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.529942,0,0,0.53199,17.26643,15.48536)" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3816" + id="radialGradient3149" + cx="31.112698" + cy="19.008621" + fx="31.112698" + fy="19.008621" + r="8.6620579" + gradientUnits="userSpaceOnUse" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2200" + id="radialGradient3158" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-2.522332,-1.518129e-16,-1.517788e-16,2.521765,40.1904,-21.83521)" + cx="9.9988937" + cy="8.963316" + fx="9.9988937" + fy="8.963316" + r="7.0034069" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2200" + id="radialGradient3160" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-2.522332,-1.518129e-16,-1.517788e-16,2.521765,40.1904,-21.80154)" + cx="9.9988937" + cy="8.963316" + fx="9.9988937" + fy="8.963316" + r="7.0034069" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2260" + id="radialGradient3162" + cx="11.756953" + cy="17.588654" + fx="11.756953" + fy="17.588654" + r="6.3436799" + gradientTransform="matrix(1,0,0,0.626667,0,6.566431)" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient3170" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.371983,0,0,0.372254,2.539836,8.539528)" + x1="15.602553" + y1="1.5657365" + x2="15.522223" + y2="33.483475" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2186" + id="linearGradient3172" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.529942,0,0,0.53199,17.26643,15.48536)" + x1="11.226587" + y1="-5.4832759" + x2="11.226587" + y2="17.697369" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient3174" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.37378,0,0,0.375227,17.64779,15.86312)" + x1="15.535398" + y1="1.8014067" + x2="15.535398" + y2="48.674999" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2186" + id="linearGradient3176" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.525701,0,0,0.525844,2.191252,8.189764)" + x1="11.226587" + y1="-5.4832759" + x2="11.226587" + y2="17.697369" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient3178" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.370788,0,0,0.370892,2.569561,8.563159)" + x1="15.535398" + y1="1.8014067" + x2="15.535398" + y2="48.674999" /> + <linearGradient + id="linearGradient4148"> + <stop + style="stop-color:#f5f5f5;stop-opacity:1.0000000;" + offset="0.0000000" + id="stop4150" /> + <stop + style="stop-color:#e9e9e9;stop-opacity:1.0000000;" + offset="1.0000000" + id="stop4152" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient29418" + id="linearGradient4146" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-0.977228,0,0,0.995878,50.60272,9.115637)" + x1="35.003674" + y1="10.957423" + x2="27.273300" + y2="24.143761" /> + <linearGradient + id="linearGradient2947"> + <stop + style="stop-color:black;stop-opacity:0;" + offset="0" + id="stop2949" /> + <stop + id="stop2951" + offset="0.5" + style="stop-color:black;stop-opacity:1;" /> + <stop + style="stop-color:black;stop-opacity:0;" + offset="1" + id="stop4144" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient4139" + gradientUnits="userSpaceOnUse" + x1="21.875" + y1="48.000977" + x2="21.875" + y2="40" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient4137" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient4135" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient4133" + x1="15.535398" + y1="1.8014067" + x2="15.535398" + y2="48.674999" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.37378,0,0,0.375227,17.64779,15.86312)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2186" + id="linearGradient4125" + x1="11.226587" + y1="-5.4832759" + x2="11.226587" + y2="17.697369" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.529942,0,0,0.53199,17.26643,15.48536)" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3816" + id="radialGradient4111" + cx="31.112698" + cy="19.008621" + fx="31.112698" + fy="19.008621" + r="8.6620579" + gradientUnits="userSpaceOnUse" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2200" + id="radialGradient4103" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-2.522332,-1.518129e-16,-1.517788e-16,2.521765,40.1904,-21.83521)" + cx="9.9988937" + cy="8.963316" + fx="9.9988937" + fy="8.963316" + r="7.0034069" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2200" + id="radialGradient4101" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-2.522332,-1.518129e-16,-1.517788e-16,2.521765,40.1904,-21.80154)" + cx="9.9988937" + cy="8.963316" + fx="9.9988937" + fy="8.963316" + r="7.0034069" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2186" + id="linearGradient4093" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.529942,0,0,0.53199,17.26643,15.48536)" + x1="11.226587" + y1="-5.4832759" + x2="11.226587" + y2="17.697369" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient4091" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.37378,0,0,0.375227,17.64779,15.86312)" + x1="15.535398" + y1="1.8014067" + x2="15.535398" + y2="48.674999" /> + <linearGradient + y2="40" + x2="21.875" + y1="48.000977" + x1="21.875" + gradientUnits="userSpaceOnUse" + id="linearGradient4089" + xlink:href="#linearGradient2804" + inkscape:collect="always" /> + <radialGradient + r="5" + fy="44" + fx="1" + cy="44" + cx="1" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + gradientUnits="userSpaceOnUse" + id="radialGradient4087" + xlink:href="#linearGradient2781" + inkscape:collect="always" /> + <radialGradient + r="5" + fy="44" + fx="1" + cy="44" + cx="1" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + gradientUnits="userSpaceOnUse" + id="radialGradient4085" + xlink:href="#linearGradient2781" + inkscape:collect="always" /> + <linearGradient + id="linearGradient4079"> + <stop + style="stop-color:#73d216;stop-opacity:1;" + offset="0" + id="stop4081" /> + <stop + style="stop-color:#5ca911;stop-opacity:1;" + offset="1" + id="stop4083" /> + </linearGradient> + <linearGradient + id="linearGradient4071"> + <stop + style="stop-color:black;stop-opacity:0;" + offset="0" + id="stop4073" /> + <stop + id="stop4075" + offset="0.5" + style="stop-color:black;stop-opacity:1;" /> + <stop + style="stop-color:black;stop-opacity:0;" + offset="1" + id="stop4077" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient4069" + gradientUnits="userSpaceOnUse" + x1="21.875" + y1="48.000977" + x2="21.875" + y2="40" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient4067" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient4059" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2260" + id="radialGradient5300" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1,0,0,0.626667,0,6.566431)" + cx="11.756953" + cy="17.588654" + fx="11.756953" + fy="17.588654" + r="6.3436799" /> + <linearGradient + id="linearGradient3466"> + <stop + style="stop-color:black;stop-opacity:0;" + offset="0" + id="stop3468" /> + <stop + id="stop3470" + offset="0.5" + style="stop-color:black;stop-opacity:1;" /> + <stop + style="stop-color:black;stop-opacity:0;" + offset="1" + id="stop3472" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient5306" + gradientUnits="userSpaceOnUse" + x1="21.875" + y1="48.000977" + x2="21.875" + y2="40" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient5304" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient5302" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <linearGradient + id="linearGradient4633"> + <stop + style="stop-color:#f5f5f5;stop-opacity:1.0000000;" + offset="0.0000000" + id="stop4635" /> + <stop + style="stop-color:#e9e9e9;stop-opacity:1.0000000;" + offset="1.0000000" + id="stop4637" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient29418" + id="linearGradient4631" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-0.977228,0,0,0.995878,50.60272,9.115637)" + x1="35.003674" + y1="10.957423" + x2="27.273300" + y2="24.143761" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient4629" + gradientUnits="userSpaceOnUse" + x1="21.875" + y1="48.000977" + x2="21.875" + y2="40" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient4627" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient4625" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <linearGradient + id="linearGradient4617"> + <stop + style="stop-color:black;stop-opacity:0;" + offset="0" + id="stop4619" /> + <stop + id="stop4621" + offset="0.5" + style="stop-color:black;stop-opacity:1;" /> + <stop + style="stop-color:black;stop-opacity:0;" + offset="1" + id="stop4623" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient4615" + gradientUnits="userSpaceOnUse" + x1="21.875" + y1="48.000977" + x2="21.875" + y2="40" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient4613" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient4611" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient4609" + x1="15.535398" + y1="1.8014067" + x2="15.535398" + y2="48.674999" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.37378,0,0,0.375227,17.64779,15.86312)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2186" + id="linearGradient4607" + x1="11.226587" + y1="-5.4832759" + x2="11.226587" + y2="17.697369" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.529942,0,0,0.53199,17.26643,15.48536)" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3816" + id="radialGradient4605" + cx="31.112698" + cy="19.008621" + fx="31.112698" + fy="19.008621" + r="8.6620579" + gradientUnits="userSpaceOnUse" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2200" + id="radialGradient4603" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-2.522332,-1.518129e-16,-1.517788e-16,2.521765,40.1904,-21.83521)" + cx="9.9988937" + cy="8.963316" + fx="9.9988937" + fy="8.963316" + r="7.0034069" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2200" + id="radialGradient4601" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-2.522332,-1.518129e-16,-1.517788e-16,2.521765,40.1904,-21.80154)" + cx="9.9988937" + cy="8.963316" + fx="9.9988937" + fy="8.963316" + r="7.0034069" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2260" + id="radialGradient4599" + cx="11.756953" + cy="17.588654" + fx="11.756953" + fy="17.588654" + r="6.3436799" + gradientTransform="matrix(1,0,0,0.626667,0,6.566431)" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient4597" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.371983,0,0,0.372254,2.539836,8.539528)" + x1="15.602553" + y1="1.5657365" + x2="15.522223" + y2="33.483475" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2186" + id="linearGradient4595" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.529942,0,0,0.53199,17.26643,15.48536)" + x1="11.226587" + y1="-5.4832759" + x2="11.226587" + y2="17.697369" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient4593" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.37378,0,0,0.375227,17.64779,15.86312)" + x1="15.535398" + y1="1.8014067" + x2="15.535398" + y2="48.674999" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2225" + id="linearGradient4591" + gradientUnits="userSpaceOnUse" + x1="11.802028" + y1="1.9986149" + x2="11.802028" + y2="14.895812" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2225" + id="linearGradient4583" + x1="11.802028" + y1="1.9986149" + x2="11.802028" + y2="14.895812" + gradientUnits="userSpaceOnUse" /> + <linearGradient + id="linearGradient4577"> + <stop + style="stop-color:#f5f5f5;stop-opacity:1.0000000;" + offset="0.0000000" + id="stop4579" /> + <stop + style="stop-color:#e9e9e9;stop-opacity:1.0000000;" + offset="1.0000000" + id="stop4581" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient29418" + id="linearGradient4575" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-0.977228,0,0,0.995878,50.60272,9.115637)" + x1="35.003674" + y1="10.957423" + x2="27.273300" + y2="24.143761" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient4573" + gradientUnits="userSpaceOnUse" + x1="21.875" + y1="48.000977" + x2="21.875" + y2="40" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient4571" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient4569" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <linearGradient + id="linearGradient4561"> + <stop + style="stop-color:black;stop-opacity:0;" + offset="0" + id="stop4563" /> + <stop + id="stop4565" + offset="0.5" + style="stop-color:black;stop-opacity:1;" /> + <stop + style="stop-color:black;stop-opacity:0;" + offset="1" + id="stop4567" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient4559" + gradientUnits="userSpaceOnUse" + x1="21.875" + y1="48.000977" + x2="21.875" + y2="40" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient4557" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient4555" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient4553" + x1="15.535398" + y1="1.8014067" + x2="15.535398" + y2="48.674999" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.37378,0,0,0.375227,17.64779,15.86312)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2186" + id="linearGradient4551" + x1="11.226587" + y1="-5.4832759" + x2="11.226587" + y2="17.697369" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.529942,0,0,0.53199,17.26643,15.48536)" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3816" + id="radialGradient4549" + cx="31.112698" + cy="19.008621" + fx="31.112698" + fy="19.008621" + r="8.6620579" + gradientUnits="userSpaceOnUse" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2200" + id="radialGradient4547" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-2.522332,-1.518129e-16,-1.517788e-16,2.521765,40.1904,-21.83521)" + cx="9.9988937" + cy="8.963316" + fx="9.9988937" + fy="8.963316" + r="7.0034069" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2200" + id="radialGradient4545" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-2.522332,-1.518129e-16,-1.517788e-16,2.521765,40.1904,-21.80154)" + cx="9.9988937" + cy="8.963316" + fx="9.9988937" + fy="8.963316" + r="7.0034069" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2260" + id="radialGradient4543" + cx="11.756953" + cy="17.588654" + fx="11.756953" + fy="17.588654" + r="6.3436799" + gradientTransform="matrix(1,0,0,0.626667,0,6.566431)" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient4541" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.371983,0,0,0.372254,2.539836,8.539528)" + x1="15.602553" + y1="1.5657365" + x2="15.522223" + y2="33.483475" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2186" + id="linearGradient4539" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.529942,0,0,0.53199,17.26643,15.48536)" + x1="11.226587" + y1="-5.4832759" + x2="11.226587" + y2="17.697369" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient4537" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.37378,0,0,0.375227,17.64779,15.86312)" + x1="15.535398" + y1="1.8014067" + x2="15.535398" + y2="48.674999" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2186" + id="linearGradient4535" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.525701,0,0,0.525844,2.191252,8.189764)" + x1="11.226587" + y1="-5.4832759" + x2="11.226587" + y2="17.697369" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient4533" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.370788,0,0,0.370892,2.569561,8.563159)" + x1="15.535398" + y1="1.8014067" + x2="15.535398" + y2="48.674999" /> + <linearGradient + id="linearGradient4527"> + <stop + style="stop-color:#f5f5f5;stop-opacity:1.0000000;" + offset="0.0000000" + id="stop4529" /> + <stop + style="stop-color:#e9e9e9;stop-opacity:1.0000000;" + offset="1.0000000" + id="stop4531" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient29418" + id="linearGradient4525" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-0.977228,0,0,0.995878,50.60272,9.115637)" + x1="35.003674" + y1="10.957423" + x2="27.273300" + y2="24.143761" /> + <linearGradient + id="linearGradient4517"> + <stop + style="stop-color:black;stop-opacity:0;" + offset="0" + id="stop4519" /> + <stop + id="stop4521" + offset="0.5" + style="stop-color:black;stop-opacity:1;" /> + <stop + style="stop-color:black;stop-opacity:0;" + offset="1" + id="stop4523" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient4515" + gradientUnits="userSpaceOnUse" + x1="21.875" + y1="48.000977" + x2="21.875" + y2="40" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient4513" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient4511" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient4509" + x1="15.535398" + y1="1.8014067" + x2="15.535398" + y2="48.674999" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.37378,0,0,0.375227,17.64779,15.86312)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2186" + id="linearGradient4501" + x1="11.226587" + y1="-5.4832759" + x2="11.226587" + y2="17.697369" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.529942,0,0,0.53199,17.26643,15.48536)" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3816" + id="radialGradient4487" + cx="31.112698" + cy="19.008621" + fx="31.112698" + fy="19.008621" + r="8.6620579" + gradientUnits="userSpaceOnUse" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2200" + id="radialGradient4479" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-2.522332,-1.518129e-16,-1.517788e-16,2.521765,40.1904,-21.83521)" + cx="9.9988937" + cy="8.963316" + fx="9.9988937" + fy="8.963316" + r="7.0034069" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2200" + id="radialGradient4477" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-2.522332,-1.518129e-16,-1.517788e-16,2.521765,40.1904,-21.80154)" + cx="9.9988937" + cy="8.963316" + fx="9.9988937" + fy="8.963316" + r="7.0034069" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2186" + id="linearGradient4469" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.529942,0,0,0.53199,17.26643,15.48536)" + x1="11.226587" + y1="-5.4832759" + x2="11.226587" + y2="17.697369" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient4467" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.37378,0,0,0.375227,17.64779,15.86312)" + x1="15.535398" + y1="1.8014067" + x2="15.535398" + y2="48.674999" /> + <linearGradient + y2="40" + x2="21.875" + y1="48.000977" + x1="21.875" + gradientUnits="userSpaceOnUse" + id="linearGradient4465" + xlink:href="#linearGradient2804" + inkscape:collect="always" /> + <radialGradient + r="5" + fy="44" + fx="1" + cy="44" + cx="1" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + gradientUnits="userSpaceOnUse" + id="radialGradient4463" + xlink:href="#linearGradient2781" + inkscape:collect="always" /> + <radialGradient + r="5" + fy="44" + fx="1" + cy="44" + cx="1" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + gradientUnits="userSpaceOnUse" + id="radialGradient4461" + xlink:href="#linearGradient2781" + inkscape:collect="always" /> + <linearGradient + id="linearGradient4455"> + <stop + style="stop-color:#73d216;stop-opacity:1;" + offset="0" + id="stop4457" /> + <stop + style="stop-color:#5ca911;stop-opacity:1;" + offset="1" + id="stop4459" /> + </linearGradient> + <linearGradient + id="linearGradient4447"> + <stop + style="stop-color:black;stop-opacity:0;" + offset="0" + id="stop4449" /> + <stop + id="stop4451" + offset="0.5" + style="stop-color:black;stop-opacity:1;" /> + <stop + style="stop-color:black;stop-opacity:0;" + offset="1" + id="stop4453" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient4445" + gradientUnits="userSpaceOnUse" + x1="21.875" + y1="48.000977" + x2="21.875" + y2="40" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient4443" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient4435" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="31.392433" + inkscape:cx="17.632615" + inkscape:cy="9.3032494" + inkscape:current-layer="layer1" + showgrid="true" + inkscape:grid-bbox="true" + inkscape:document-units="px" + inkscape:window-width="1440" + inkscape:window-height="847" + inkscape:window-x="0" + inkscape:window-y="0" + width="11px" + height="11px" /> + <metadata + id="metadata1877"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + id="layer1" + inkscape:label="Layer 1" + inkscape:groupmode="layer"> + <path + style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M -10.795455,-3.5 C -10.618367,-3.5 -10.5,-3.3971157 -10.5,-3.2012194 L -10.5,2.3475645 C -10.5,2.5434609 -10.618367,2.6463452 -10.795455,2.6463452 L -14.999998,3.3220878 C -15.175778,3.3232474 -15.345224,3.383862 -15.477271,3.4928196 L -16.295452,4.1757469 L -16.295452,4.005015 C -16.297398,3.628604 -16.621872,3.3239147 -17.022725,3.3220878 L -18.204542,2.6463452 C -18.38163,2.6463452 -18.499997,2.5434595 -18.499997,2.3475645 L -18.499997,-3.2012194 C -18.499997,-3.3971155 -18.38163,-3.5 -18.204542,-3.5 L -10.795455,-3.5 z " + id="path5807" + sodipodi:nodetypes="cccccccccccccc" /> + <path + style="fill:#fce94f;fill-opacity:1;stroke:#ce5c00;stroke-width:0.99999905;stroke-miterlimit:4;stroke-opacity:1" + d="M 10.499996,3.1704551 L 7.6022705,0.49999908 L 1.9176175,0.49999908 C 1.0082505,0.49999908 0.49999952,1.0912623 0.49999952,1.8290758 L 0.49999952,10.5 L 10.499996,10.5 L 10.499996,3.1704551 z " + id="rect5097" + sodipodi:nodetypes="ccccccc" /> + <path + style="opacity:0.5625;fill:none;fill-opacity:1;stroke:#eeeeec;stroke-width:0.99999952;stroke-miterlimit:4;stroke-opacity:1" + d="M 9.4572875,3.5607647 L 7.1836985,1.5000008 L 1.5000025,1.5128215 L 1.5000025,9.5000007 L 9.5000005,9.5000007 L 9.4572875,3.5607647 z " + id="rect5099" + sodipodi:nodetypes="cccccc" /> + <rect + style="opacity:0.4;fill:#ce5c00;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect5988" + width="1" + height="2.0000002" + x="-7.0000048" + y="1.9999998" + transform="scale(-1,1)" /> + <rect + style="opacity:0.4;fill:#ce5c00;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect5990" + width="0.99999851" + height="1.9999995" + x="3.0000069" + y="7.0000057" + transform="matrix(-2.004699e-7,1,1,-8.326572e-7,0,0)" /> + <rect + style="fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect7300" + width="4" + height="1" + x="3.0000041" + y="6.9999995" /> + <rect + style="fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect7302" + width="3.6559839" + height="0.91399604" + x="3.0000041" + y="5.0860038" /> + <rect + style="fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect7304" + width="2" + height="1" + x="3.0000041" + y="2.9999998" /> + </g> +</svg>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pidgin/pixmaps/status/11/scalable/invisible.svg Mon Aug 27 21:59:11 2007 +0000 @@ -0,0 +1,255 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://web.resource.org/cc/" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="11" + height="11" + id="svg2" + sodipodi:version="0.32" + inkscape:version="0.45.1" + version="1.0" + inkscape:export-filename="/home/hbons/Desktop/invisible.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" + sodipodi:docbase="/home/hbons/Desktop" + sodipodi:docname="invisible.svg" + inkscape:output_extension="org.inkscape.output.svg.inkscape"> + <defs + id="defs4"> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3149" + id="linearGradient4740" + gradientUnits="userSpaceOnUse" + x1="15.498499" + y1="9.4211226" + x2="24.240097" + y2="36.603138" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3149" + id="linearGradient2269" + gradientUnits="userSpaceOnUse" + x1="17.890068" + y1="8.0617304" + x2="17.890068" + y2="40.032413" /> + <linearGradient + id="linearGradient2851"> + <stop + style="stop-color:#73d216;stop-opacity:1;" + offset="0" + id="stop2853" /> + <stop + style="stop-color:#5ca911;stop-opacity:1;" + offset="1" + id="stop2855" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + id="linearGradient3149"> + <stop + style="stop-color:#eeeeec;stop-opacity:1;" + offset="0" + id="stop3151" /> + <stop + style="stop-color:#eeeeec;stop-opacity:0;" + offset="1" + id="stop3153" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + id="linearGradient3816"> + <stop + style="stop-color:#000000;stop-opacity:1;" + offset="0" + id="stop3818" /> + <stop + style="stop-color:#000000;stop-opacity:0;" + offset="1" + id="stop3820" /> + </linearGradient> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3816" + id="radialGradient3822" + cx="31.112698" + cy="19.008621" + fx="31.112698" + fy="19.008621" + r="8.6620579" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.914124,0,0,1.631747,2.671799,-12.00863)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2851" + id="linearGradient2857" + x1="6.878005" + y1="11.789385" + x2="12.233074" + y2="27.77807" + gradientUnits="userSpaceOnUse" /> + <radialGradient + gradientUnits="userSpaceOnUse" + r="8.6620579" + fy="19.008621" + fx="31.112698" + cy="19.008621" + cx="31.112698" + id="radialGradient2818" + xlink:href="#linearGradient2812" + inkscape:collect="always" /> + <linearGradient + gradientUnits="userSpaceOnUse" + y2="11.024895" + x2="10.623409" + y1="2.7991772" + x1="4.5264969" + id="linearGradient2810" + xlink:href="#linearGradient2804" + inkscape:collect="always" /> + <linearGradient + gradientUnits="userSpaceOnUse" + y2="27.77807" + x2="12.233074" + y1="11.789385" + x1="6.878005" + id="linearGradient2963" + xlink:href="#linearGradient2851" + inkscape:collect="always" /> + <linearGradient + id="linearGradient2951"> + <stop + id="stop2953" + offset="0" + style="stop-color:#73d216;stop-opacity:1;" /> + <stop + id="stop2955" + offset="1" + style="stop-color:#5ca911;stop-opacity:1;" /> + </linearGradient> + <linearGradient + y2="40.032413" + x2="17.890068" + y1="8.0617304" + x1="17.890068" + gradientUnits="userSpaceOnUse" + id="linearGradient2949" + xlink:href="#linearGradient3149" + inkscape:collect="always" /> + <linearGradient + id="linearGradient2804" + inkscape:collect="always"> + <stop + id="stop2806" + offset="0" + style="stop-color:white;stop-opacity:1;" /> + <stop + id="stop2808" + offset="1" + style="stop-color:white;stop-opacity:0;" /> + </linearGradient> + <linearGradient + id="linearGradient2812" + inkscape:collect="always"> + <stop + id="stop2814" + offset="0" + style="stop-color:#2e3436;stop-opacity:1;" /> + <stop + id="stop2816" + offset="1" + style="stop-color:#2e3436;stop-opacity:0;" /> + </linearGradient> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2812" + id="radialGradient3005" + gradientUnits="userSpaceOnUse" + cx="31.112698" + cy="19.008621" + fx="31.112698" + fy="19.008621" + r="8.6620579" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient3007" + gradientUnits="userSpaceOnUse" + x1="4.5264969" + y1="2.7991772" + x2="10.623409" + y2="11.024895" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2812" + id="radialGradient3025" + gradientUnits="userSpaceOnUse" + cx="31.112698" + cy="19.008621" + fx="31.112698" + fy="19.008621" + r="8.6620579" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3149" + id="linearGradient3162" + gradientUnits="userSpaceOnUse" + x1="15.498499" + y1="9.4211226" + x2="24.240097" + y2="36.603138" + gradientTransform="matrix(0.287092,0,0,0.2870921,0.3639043,0.4550679)" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="25.992076" + inkscape:cx="14.809403" + inkscape:cy="5.0224378" + inkscape:document-units="px" + inkscape:current-layer="layer1" + showgrid="true" + fill="#eeeeec" + inkscape:window-width="1440" + inkscape:window-height="843" + inkscape:window-x="0" + inkscape:window-y="0" + width="11px" + height="11px" /> + <metadata + id="metadata7"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1"> + <path + style="opacity:0.8;fill:#babdb6;fill-opacity:1;fill-rule:evenodd;stroke:#888a85;stroke-width:0.99999934;stroke-miterlimit:4;stroke-opacity:1" + d="M 10.5,5.4999993 C 10.5,8.2599995 8.2599997,10.5 5.4999997,10.5 C 2.7399994,10.5 0.49999907,8.2599995 0.49999907,5.4999993 C 0.49999907,2.7399988 2.7399994,0.49999858 5.4999997,0.49999858 C 8.2599997,0.49999858 10.5,2.7399988 10.5,5.4999993 z " + id="path4331" /> + <path + style="opacity:0.47999998;fill:url(#linearGradient3162);fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:0.99999887;stroke-miterlimit:4;stroke-opacity:1" + d="M 9.5000004,5.5000003 C 9.5000004,7.7080004 7.7080003,9.500001 5.4999998,9.500001 C 3.2919997,9.500001 1.4999994,7.7080004 1.4999994,5.5000003 C 1.4999994,3.2919997 3.2919997,1.4999995 5.4999998,1.4999995 C 7.7080003,1.4999995 9.5000004,3.2919997 9.5000004,5.5000003 z " + id="path4333" /> + </g> +</svg>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pidgin/pixmaps/status/11/scalable/offline.svg Mon Aug 27 21:59:11 2007 +0000 @@ -0,0 +1,3384 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://web.resource.org/cc/" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="11" + height="11" + id="svg1872" + sodipodi:version="0.32" + inkscape:version="0.45.1" + sodipodi:docbase="/home/hbons/Desktop/tabs" + sodipodi:docname="offline.svg" + inkscape:output_extension="org.inkscape.output.svg.inkscape" + version="1.0" + inkscape:export-filename="/home/hbons/Desktop/tabs/extended-away.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90"> + <defs + id="defs1874"> + <radialGradient + r="5" + fy="44" + fx="1" + cy="44" + cx="1" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + gradientUnits="userSpaceOnUse" + id="radialGradient7751" + xlink:href="#linearGradient2781" + inkscape:collect="always" /> + <linearGradient + id="linearGradient2781" + inkscape:collect="always"> + <stop + id="stop2783" + offset="0" + style="stop-color:black;stop-opacity:1;" /> + <stop + id="stop2785" + offset="1" + style="stop-color:black;stop-opacity:0;" /> + </linearGradient> + <radialGradient + r="5" + fy="44" + fx="1" + cy="44" + cx="1" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + gradientUnits="userSpaceOnUse" + id="radialGradient7753" + xlink:href="#linearGradient2781" + inkscape:collect="always" /> + <linearGradient + y2="40" + x2="21.875" + y1="48.000977" + x1="21.875" + gradientUnits="userSpaceOnUse" + id="linearGradient7755" + xlink:href="#linearGradient2804" + inkscape:collect="always" /> + <linearGradient + id="linearGradient2804"> + <stop + id="stop2806" + offset="0" + style="stop-color:black;stop-opacity:0;" /> + <stop + style="stop-color:black;stop-opacity:1;" + offset="0.5" + id="stop2812" /> + <stop + id="stop2808" + offset="1" + style="stop-color:black;stop-opacity:0;" /> + </linearGradient> + <linearGradient + id="linearGradient2851"> + <stop + id="stop2853" + offset="0" + style="stop-color:#73d216;stop-opacity:1;" /> + <stop + id="stop2855" + offset="1" + style="stop-color:#5ca911;stop-opacity:1;" /> + </linearGradient> + <linearGradient + id="linearGradient3149" + inkscape:collect="always"> + <stop + id="stop3151" + offset="0" + style="stop-color:#eeeeec;stop-opacity:1;" /> + <stop + id="stop3153" + offset="1" + style="stop-color:#eeeeec;stop-opacity:0;" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3149" + id="linearGradient1956" + gradientUnits="userSpaceOnUse" + x1="17.890068" + y1="2.2464287" + x2="17.890068" + y2="34.458977" + gradientTransform="matrix(0.287092,0,0,0.287092,5.363906,5.455062)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2851" + id="linearGradient1959" + gradientUnits="userSpaceOnUse" + x1="6.878005" + y1="11.789385" + x2="12.233074" + y2="27.77807" + gradientTransform="matrix(0.36035,0,0,0.358865,4.074001,4.193834)" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient1970" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient1972" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient1974" + gradientUnits="userSpaceOnUse" + x1="21.875" + y1="48.000977" + x2="21.875" + y2="40" /> + <linearGradient + inkscape:collect="always" + id="linearGradient2898"> + <stop + style="stop-color:white;stop-opacity:1;" + offset="0" + id="stop2900" /> + <stop + style="stop-color:white;stop-opacity:0;" + offset="1" + id="stop2902" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2851" + id="linearGradient4738" + gradientUnits="userSpaceOnUse" + x1="6.878005" + y1="11.789385" + x2="12.233074" + y2="27.77807" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3149" + id="linearGradient4740" + gradientUnits="userSpaceOnUse" + x1="15.498499" + y1="9.4211226" + x2="24.240097" + y2="36.603138" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3149" + id="linearGradient3044" + gradientUnits="userSpaceOnUse" + x1="17.890068" + y1="8.0617304" + x2="17.890068" + y2="40.032413" /> + <linearGradient + id="linearGradient3046"> + <stop + style="stop-color:#73d216;stop-opacity:1;" + offset="0" + id="stop3048" /> + <stop + style="stop-color:#5ca911;stop-opacity:1;" + offset="1" + id="stop3050" /> + </linearGradient> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3816" + id="radialGradient3064" + cx="31.112698" + cy="19.008621" + fx="31.112698" + fy="19.008621" + r="8.6620579" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.914124,0,0,1.631747,2.671799,-12.00863)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2851" + id="linearGradient3066" + x1="6.878005" + y1="11.789385" + x2="12.233074" + y2="27.77807" + gradientUnits="userSpaceOnUse" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2898" + id="radialGradient2904" + cx="4.8470273" + cy="6.9473476" + fx="4.8470273" + fy="6.9473476" + r="0.8078171" + gradientTransform="matrix(3.018423,0.664359,-1.388844,4.257661,-0.134567,-26.02469)" + gradientUnits="userSpaceOnUse" /> + <radialGradient + gradientUnits="userSpaceOnUse" + r="8.6620579" + fy="19.008621" + fx="31.112698" + cy="19.008621" + cx="31.112698" + id="radialGradient2818" + xlink:href="#linearGradient2812" + inkscape:collect="always" /> + <linearGradient + gradientUnits="userSpaceOnUse" + y2="11.024895" + x2="10.623409" + y1="2.7991772" + x1="4.5264969" + id="linearGradient2810" + xlink:href="#linearGradient2804" + inkscape:collect="always" /> + <linearGradient + gradientUnits="userSpaceOnUse" + y2="27.77807" + x2="12.233074" + y1="11.789385" + x1="6.878005" + id="linearGradient2963" + xlink:href="#linearGradient2851" + inkscape:collect="always" /> + <linearGradient + id="linearGradient2951"> + <stop + id="stop2953" + offset="0" + style="stop-color:#73d216;stop-opacity:1;" /> + <stop + id="stop2955" + offset="1" + style="stop-color:#5ca911;stop-opacity:1;" /> + </linearGradient> + <linearGradient + y2="40.032413" + x2="17.890068" + y1="8.0617304" + x1="17.890068" + gradientUnits="userSpaceOnUse" + id="linearGradient2949" + xlink:href="#linearGradient3149" + inkscape:collect="always" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2812" + id="radialGradient3005" + gradientUnits="userSpaceOnUse" + cx="31.112698" + cy="19.008621" + fx="31.112698" + fy="19.008621" + r="8.6620579" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient3007" + gradientUnits="userSpaceOnUse" + x1="4.5264969" + y1="2.7991772" + x2="10.623409" + y2="11.024895" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2812" + id="radialGradient3025" + gradientUnits="userSpaceOnUse" + cx="31.112698" + cy="19.008621" + fx="31.112698" + fy="19.008621" + r="8.6620579" /> + <linearGradient + gradientUnits="userSpaceOnUse" + y2="10.018044" + x2="10.043059" + y1="1.3319674" + x1="1.5769236" + id="linearGradient2995" + xlink:href="#linearGradient2989" + inkscape:collect="always" /> + <radialGradient + r="8.6620579" + fy="19.008621" + fx="31.112698" + cy="19.008621" + cx="31.112698" + gradientUnits="userSpaceOnUse" + id="radialGradient2084" + xlink:href="#linearGradient2812" + inkscape:collect="always" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3149" + id="linearGradient2046" + gradientUnits="userSpaceOnUse" + x1="17.890068" + y1="8.0617304" + x2="17.890068" + y2="40.032413" /> + <linearGradient + id="linearGradient2048"> + <stop + style="stop-color:#73d216;stop-opacity:1;" + offset="0" + id="stop2050" /> + <stop + style="stop-color:#5ca911;stop-opacity:1;" + offset="1" + id="stop2052" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2851" + id="linearGradient2060" + x1="6.878005" + y1="11.789385" + x2="12.233074" + y2="27.77807" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient2062" + x1="4.5264969" + y1="2.7991772" + x2="10.623409" + y2="11.024895" + gradientUnits="userSpaceOnUse" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2812" + id="radialGradient2064" + cx="31.112698" + cy="19.008621" + fx="31.112698" + fy="19.008621" + r="8.6620579" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + id="linearGradient2812"> + <stop + style="stop-color:#2e3436;stop-opacity:1;" + offset="0" + id="stop2814" /> + <stop + style="stop-color:#2e3436;stop-opacity:0;" + offset="1" + id="stop2816" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3149" + id="linearGradient2269" + gradientUnits="userSpaceOnUse" + x1="17.890068" + y1="8.0617304" + x2="17.890068" + y2="40.032413" /> + <linearGradient + id="linearGradient2055"> + <stop + style="stop-color:#73d216;stop-opacity:1;" + offset="0" + id="stop2057" /> + <stop + style="stop-color:#5ca911;stop-opacity:1;" + offset="1" + id="stop2059" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2851" + id="linearGradient2857" + x1="6.878005" + y1="11.789385" + x2="12.233074" + y2="27.77807" + gradientUnits="userSpaceOnUse" /> + <linearGradient + y2="14.895812" + x2="11.802028" + y1="1.9986149" + x1="11.802028" + gradientUnits="userSpaceOnUse" + id="linearGradient6606" + xlink:href="#linearGradient2225" + inkscape:collect="always" /> + <linearGradient + y2="48.674999" + x2="15.535398" + y1="1.8014067" + x1="15.535398" + gradientTransform="matrix(0.37378,0,0,0.375227,17.64779,15.86312)" + gradientUnits="userSpaceOnUse" + id="linearGradient2339" + xlink:href="#linearGradient2239" + inkscape:collect="always" /> + <linearGradient + y2="17.697369" + x2="11.226587" + y1="-5.4832759" + x1="11.226587" + gradientTransform="matrix(0.529942,0,0,0.53199,17.26643,15.48536)" + gradientUnits="userSpaceOnUse" + id="linearGradient2337" + xlink:href="#linearGradient2186" + inkscape:collect="always" /> + <linearGradient + y2="33.483475" + x2="15.522223" + y1="1.5657365" + x1="15.602553" + gradientTransform="matrix(0.371983,0,0,0.372254,2.539836,8.539528)" + gradientUnits="userSpaceOnUse" + id="linearGradient1357" + xlink:href="#linearGradient2239" + inkscape:collect="always" /> + <linearGradient + inkscape:collect="always" + id="linearGradient2239"> + <stop + style="stop-color:#ffffff;stop-opacity:1;" + offset="0" + id="stop2241" /> + <stop + style="stop-color:#ffffff;stop-opacity:0;" + offset="1" + id="stop2243" /> + </linearGradient> + <radialGradient + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1,0,0,0.626667,0,6.566431)" + r="6.3436799" + fy="17.588654" + fx="11.756953" + cy="17.588654" + cx="11.756953" + id="radialGradient2266" + xlink:href="#linearGradient2260" + inkscape:collect="always" /> + <radialGradient + r="7.003407" + fy="8.963316" + fx="9.9988937" + cy="8.963316" + cx="9.9988937" + gradientTransform="matrix(-2.522332,0,0,2.521765,40.1904,-21.80154)" + gradientUnits="userSpaceOnUse" + id="radialGradient2225" + xlink:href="#linearGradient2200" + inkscape:collect="always" /> + <radialGradient + r="7.003407" + fy="8.963316" + fx="9.9988937" + cy="8.963316" + cx="9.9988937" + gradientTransform="matrix(-2.522332,0,0,2.521765,40.1904,-21.83521)" + gradientUnits="userSpaceOnUse" + id="radialGradient2216" + xlink:href="#linearGradient2200" + inkscape:collect="always" /> + <linearGradient + id="linearGradient2200" + inkscape:collect="always"> + <stop + id="stop2202" + offset="0" + style="stop-color:#d3d7cf;stop-opacity:1;" /> + <stop + id="stop2204" + offset="1" + style="stop-color:#d3d7cf;stop-opacity:0;" /> + </linearGradient> + <radialGradient + gradientUnits="userSpaceOnUse" + r="8.6620579" + fy="19.008621" + fx="31.112698" + cy="19.008621" + cx="31.112698" + id="radialGradient3822" + xlink:href="#linearGradient3816" + inkscape:collect="always" /> + <linearGradient + id="linearGradient3816" + inkscape:collect="always"> + <stop + id="stop3818" + offset="0" + style="stop-color:#000000;stop-opacity:1;" /> + <stop + id="stop3820" + offset="1" + style="stop-color:#000000;stop-opacity:0;" /> + </linearGradient> + <linearGradient + id="linearGradient2260" + inkscape:collect="always"> + <stop + id="stop2262" + offset="0" + style="stop-color:#555753;stop-opacity:1;" /> + <stop + id="stop2264" + offset="1" + style="stop-color:#555753;stop-opacity:0;" /> + </linearGradient> + <linearGradient + gradientTransform="matrix(0.529942,0,0,0.53199,17.26643,15.48536)" + gradientUnits="userSpaceOnUse" + y2="17.697369" + x2="11.226587" + y1="-5.4832759" + x1="11.226587" + id="linearGradient2194" + xlink:href="#linearGradient2186" + inkscape:collect="always" /> + <linearGradient + id="linearGradient2186" + inkscape:collect="always"> + <stop + id="stop2188" + offset="0" + style="stop-color:#ffffff;stop-opacity:1;" /> + <stop + id="stop2190" + offset="1" + style="stop-color:#ffffff;stop-opacity:0;" /> + </linearGradient> + <linearGradient + gradientTransform="matrix(0.37378,0,0,0.375227,17.64779,15.86312)" + gradientUnits="userSpaceOnUse" + y2="48.674999" + x2="15.535398" + y1="1.8014067" + x1="15.535398" + id="linearGradient2245" + xlink:href="#linearGradient2239" + inkscape:collect="always" /> + <radialGradient + r="5" + fy="44" + fx="1" + cy="44" + cx="1" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + gradientUnits="userSpaceOnUse" + id="radialGradient2827" + xlink:href="#linearGradient2781" + inkscape:collect="always" /> + <radialGradient + r="5" + fy="44" + fx="1" + cy="44" + cx="1" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + gradientUnits="userSpaceOnUse" + id="radialGradient2829" + xlink:href="#linearGradient2781" + inkscape:collect="always" /> + <linearGradient + y2="40" + x2="21.875" + y1="48.000977" + x1="21.875" + gradientUnits="userSpaceOnUse" + id="linearGradient2831" + xlink:href="#linearGradient2804" + inkscape:collect="always" /> + <linearGradient + id="linearGradient2006"> + <stop + id="stop2008" + offset="0" + style="stop-color:black;stop-opacity:0;" /> + <stop + style="stop-color:black;stop-opacity:1;" + offset="0.5" + id="stop2010" /> + <stop + id="stop2012" + offset="1" + style="stop-color:black;stop-opacity:0;" /> + </linearGradient> + <linearGradient + y2="24.143761" + x2="27.2733" + y1="10.957423" + x1="35.003674" + gradientTransform="matrix(-0.977228,0,0,0.995878,50.60272,9.115637)" + gradientUnits="userSpaceOnUse" + id="linearGradient29443" + xlink:href="#linearGradient29418" + inkscape:collect="always" /> + <linearGradient + id="linearGradient29418"> + <stop + id="stop29420" + offset="0.0000000" + style="stop-color:#f5f5f5;stop-opacity:1.0000000;" /> + <stop + id="stop29422" + offset="1.0000000" + style="stop-color:#e9e9e9;stop-opacity:1.0000000;" /> + </linearGradient> + <linearGradient + id="linearGradient2225" + inkscape:collect="always"> + <stop + id="stop2227" + offset="0" + style="stop-color:#eeeeec;stop-opacity:1;" /> + <stop + id="stop2229" + offset="1" + style="stop-color:#eeeeec;stop-opacity:0;" /> + </linearGradient> + <linearGradient + id="linearGradient2989" + inkscape:collect="always"> + <stop + id="stop2991" + offset="0" + style="stop-color:#eeeeec;stop-opacity:1;" /> + <stop + id="stop2993" + offset="1" + style="stop-color:#eeeeec;stop-opacity:0;" /> + </linearGradient> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2812" + id="radialGradient2112" + gradientUnits="userSpaceOnUse" + cx="31.112698" + cy="19.008621" + fx="31.112698" + fy="19.008621" + r="8.6620579" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2851" + id="linearGradient2114" + gradientUnits="userSpaceOnUse" + x1="6.878005" + y1="11.789385" + x2="12.233074" + y2="27.77807" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3149" + id="linearGradient2116" + gradientUnits="userSpaceOnUse" + x1="15.498499" + y1="9.4211226" + x2="24.240097" + y2="36.603138" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3149" + id="linearGradient2119" + gradientUnits="userSpaceOnUse" + x1="15.498499" + y1="9.4211226" + x2="24.240097" + y2="36.603138" + gradientTransform="matrix(0.2512053,0,0,0.2512055,0.505914,0.5856851)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2851" + id="linearGradient2122" + gradientUnits="userSpaceOnUse" + x1="6.878005" + y1="11.789385" + x2="12.233074" + y2="27.77807" + gradientTransform="matrix(0.3229785,0,0,0.3229785,-0.7781054,-0.675548)" /> + <linearGradient + y2="40" + x2="21.875" + y1="48.000977" + x1="21.875" + gradientUnits="userSpaceOnUse" + id="linearGradient2567" + xlink:href="#linearGradient2804" + inkscape:collect="always" /> + <radialGradient + r="5" + fy="44" + fx="1" + cy="44" + cx="1" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + gradientUnits="userSpaceOnUse" + id="radialGradient2565" + xlink:href="#linearGradient2781" + inkscape:collect="always" /> + <radialGradient + r="5" + fy="44" + fx="1" + cy="44" + cx="1" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + gradientUnits="userSpaceOnUse" + id="radialGradient2563" + xlink:href="#linearGradient2781" + inkscape:collect="always" /> + <linearGradient + gradientTransform="matrix(0.36035,0,0,0.358865,4.074001,4.193834)" + y2="27.77807" + x2="12.233074" + y1="11.789385" + x1="6.878005" + gradientUnits="userSpaceOnUse" + id="linearGradient2561" + xlink:href="#linearGradient2851" + inkscape:collect="always" /> + <linearGradient + gradientTransform="matrix(0.287092,0,0,0.287092,5.363906,5.455062)" + y2="34.458977" + x2="17.890068" + y1="2.2464287" + x1="17.890068" + gradientUnits="userSpaceOnUse" + id="linearGradient2559" + xlink:href="#linearGradient3149" + inkscape:collect="always" /> + <linearGradient + id="linearGradient2547"> + <stop + style="stop-color:#73d216;stop-opacity:1;" + offset="0" + id="stop2549" /> + <stop + style="stop-color:#5ca911;stop-opacity:1;" + offset="1" + id="stop2551" /> + </linearGradient> + <linearGradient + id="linearGradient2539"> + <stop + style="stop-color:black;stop-opacity:0;" + offset="0" + id="stop2541" /> + <stop + id="stop2543" + offset="0.5" + style="stop-color:black;stop-opacity:1;" /> + <stop + style="stop-color:black;stop-opacity:0;" + offset="1" + id="stop2545" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient2537" + gradientUnits="userSpaceOnUse" + x1="21.875" + y1="48.000977" + x2="21.875" + y2="40" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient2535" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient2527" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <linearGradient + y2="17.697369" + x2="11.226587" + y1="-5.4832759" + x1="11.226587" + gradientTransform="matrix(-0.420408,0,0,0.420404,15.54691,5.457116)" + gradientUnits="userSpaceOnUse" + id="linearGradient2343" + xlink:href="#linearGradient2186" + inkscape:collect="always" /> + <linearGradient + y2="48.674999" + x2="15.535398" + y1="1.8014067" + x1="15.535398" + gradientTransform="matrix(-0.296523,0,0,0.296522,15.24437,5.75564)" + gradientUnits="userSpaceOnUse" + id="linearGradient2345" + xlink:href="#linearGradient2239" + inkscape:collect="always" /> + <radialGradient + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1,0,0,0.626667,0,6.566431)" + r="6.3436799" + fy="17.588654" + fx="11.756953" + cy="17.588654" + cx="11.756953" + id="radialGradient2511" + xlink:href="#linearGradient2260" + inkscape:collect="always" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2186" + id="linearGradient2583" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-0.420408,0,0,0.420404,23.273502,-1.8126311)" + x1="11.226587" + y1="-5.4832759" + x2="11.226587" + y2="17.697369" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient2585" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-0.296523,0,0,0.296522,22.970962,-1.5141071)" + x1="15.535398" + y1="1.8014067" + x2="15.535398" + y2="48.674999" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2851" + id="linearGradient2597" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.358865,0,0,0.358865,-0.920117,-0.8061648)" + x1="6.878005" + y1="11.789385" + x2="12.233074" + y2="27.77807" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3149" + id="linearGradient2599" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.2870918,0,0,0.287092,0.3639019,0.4550689)" + x1="15.498499" + y1="9.4211226" + x2="24.240097" + y2="36.603138" /> + <linearGradient + y2="40" + x2="21.875" + y1="48.000977" + x1="21.875" + gradientUnits="userSpaceOnUse" + id="linearGradient2713" + xlink:href="#linearGradient2804" + inkscape:collect="always" /> + <radialGradient + r="5" + fy="44" + fx="1" + cy="44" + cx="1" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + gradientUnits="userSpaceOnUse" + id="radialGradient2711" + xlink:href="#linearGradient2781" + inkscape:collect="always" /> + <radialGradient + r="5" + fy="44" + fx="1" + cy="44" + cx="1" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + gradientUnits="userSpaceOnUse" + id="radialGradient2709" + xlink:href="#linearGradient2781" + inkscape:collect="always" /> + <linearGradient + gradientTransform="matrix(0.36035,0,0,0.358865,4.074001,4.193834)" + y2="27.77807" + x2="12.233074" + y1="11.789385" + x1="6.878005" + gradientUnits="userSpaceOnUse" + id="linearGradient2707" + xlink:href="#linearGradient2851" + inkscape:collect="always" /> + <linearGradient + gradientTransform="matrix(0.287092,0,0,0.287092,5.363906,5.455062)" + y2="34.458977" + x2="17.890068" + y1="2.2464287" + x1="17.890068" + gradientUnits="userSpaceOnUse" + id="linearGradient2705" + xlink:href="#linearGradient3149" + inkscape:collect="always" /> + <linearGradient + id="linearGradient2693"> + <stop + style="stop-color:#73d216;stop-opacity:1;" + offset="0" + id="stop2695" /> + <stop + style="stop-color:#5ca911;stop-opacity:1;" + offset="1" + id="stop2697" /> + </linearGradient> + <linearGradient + id="linearGradient2685"> + <stop + style="stop-color:black;stop-opacity:0;" + offset="0" + id="stop2687" /> + <stop + id="stop2689" + offset="0.5" + style="stop-color:black;stop-opacity:1;" /> + <stop + style="stop-color:black;stop-opacity:0;" + offset="1" + id="stop2691" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient2683" + gradientUnits="userSpaceOnUse" + x1="21.875" + y1="48.000977" + x2="21.875" + y2="40" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient2681" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient2673" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <linearGradient + y2="17.697369" + x2="11.226587" + y1="-5.4832759" + x1="11.226587" + gradientTransform="matrix(-0.420408,0,0,0.420404,15.54691,5.457116)" + gradientUnits="userSpaceOnUse" + id="linearGradient2671" + xlink:href="#linearGradient2186" + inkscape:collect="always" /> + <linearGradient + y2="48.674999" + x2="15.535398" + y1="1.8014067" + x1="15.535398" + gradientTransform="matrix(-0.296523,0,0,0.296522,15.24437,5.75564)" + gradientUnits="userSpaceOnUse" + id="linearGradient2663" + xlink:href="#linearGradient2239" + inkscape:collect="always" /> + <radialGradient + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1,0,0,0.626667,0,6.566431)" + r="6.3436799" + fy="17.588654" + fx="11.756953" + cy="17.588654" + cx="11.756953" + id="radialGradient2655" + xlink:href="#linearGradient2260" + inkscape:collect="always" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient2727" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient2729" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient2731" + gradientUnits="userSpaceOnUse" + x1="21.875" + y1="48.000977" + x2="21.875" + y2="40" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2186" + id="linearGradient2733" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-0.420408,0,0,0.420404,15.54691,5.457116)" + x1="11.226587" + y1="-5.4832759" + x2="11.226587" + y2="17.697369" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient2735" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-0.296523,0,0,0.296522,15.24437,5.75564)" + x1="15.535398" + y1="1.8014067" + x2="15.535398" + y2="48.674999" /> + <linearGradient + y2="10.018044" + x2="10.043059" + y1="1.3319674" + x1="1.5769236" + gradientUnits="userSpaceOnUse" + id="linearGradient2232" + xlink:href="#linearGradient2989" + inkscape:collect="always" /> + <linearGradient + id="linearGradient2098"> + <stop + style="stop-color:#f5f5f5;stop-opacity:1.0000000;" + offset="0.0000000" + id="stop2100" /> + <stop + style="stop-color:#e9e9e9;stop-opacity:1.0000000;" + offset="1.0000000" + id="stop2102" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient29418" + id="linearGradient2104" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-0.977228,0,0,0.995878,50.60272,9.115637)" + x1="35.003674" + y1="10.957423" + x2="27.273300" + y2="24.143761" /> + <linearGradient + id="linearGradient2106"> + <stop + style="stop-color:black;stop-opacity:0;" + offset="0" + id="stop2108" /> + <stop + id="stop2110" + offset="0.5" + style="stop-color:black;stop-opacity:1;" /> + <stop + style="stop-color:black;stop-opacity:0;" + offset="1" + id="stop2112" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient4258" + gradientUnits="userSpaceOnUse" + x1="21.875" + y1="48.000977" + x2="21.875" + y2="40" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient2116" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient2124" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient2126" + x1="15.535398" + y1="1.8014067" + x2="15.535398" + y2="48.674999" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.37378,0,0,0.375227,17.64779,15.86312)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2186" + id="linearGradient2134" + x1="11.226587" + y1="-5.4832759" + x2="11.226587" + y2="17.697369" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.529942,0,0,0.53199,17.26643,15.48536)" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3816" + id="radialGradient2148" + cx="31.112698" + cy="19.008621" + fx="31.112698" + fy="19.008621" + r="8.6620579" + gradientUnits="userSpaceOnUse" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2200" + id="radialGradient2156" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-2.522332,-1.518129e-16,-1.517788e-16,2.521765,40.1904,-21.83521)" + cx="9.9988937" + cy="8.963316" + fx="9.9988937" + fy="8.963316" + r="7.0034069" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2200" + id="radialGradient2158" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-2.522332,-1.518129e-16,-1.517788e-16,2.521765,40.1904,-21.80154)" + cx="9.9988937" + cy="8.963316" + fx="9.9988937" + fy="8.963316" + r="7.0034069" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2260" + id="radialGradient4249" + cx="11.756953" + cy="17.588654" + fx="11.756953" + fy="17.588654" + r="6.3436799" + gradientTransform="matrix(1,0,0,0.626667,0,6.566431)" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient4247" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.371983,0,0,0.372254,2.539836,8.539528)" + x1="15.602553" + y1="1.5657365" + x2="15.522223" + y2="33.483475" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2186" + id="linearGradient2168" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.529942,0,0,0.53199,17.26643,15.48536)" + x1="11.226587" + y1="-5.4832759" + x2="11.226587" + y2="17.697369" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient2170" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.37378,0,0,0.375227,17.64779,15.86312)" + x1="15.535398" + y1="1.8014067" + x2="15.535398" + y2="48.674999" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2225" + id="linearGradient4243" + gradientUnits="userSpaceOnUse" + x1="11.802028" + y1="1.9986149" + x2="11.802028" + y2="14.895812" /> + <linearGradient + gradientUnits="userSpaceOnUse" + y2="27.77807" + x2="12.233074" + y1="11.789385" + x1="6.878005" + id="linearGradient4241" + xlink:href="#linearGradient2851" + inkscape:collect="always" /> + <linearGradient + id="linearGradient2177"> + <stop + id="stop2179" + offset="0" + style="stop-color:#73d216;stop-opacity:1;" /> + <stop + id="stop2181" + offset="1" + style="stop-color:#5ca911;stop-opacity:1;" /> + </linearGradient> + <linearGradient + y2="40.032413" + x2="17.890068" + y1="8.0617304" + x1="17.890068" + gradientUnits="userSpaceOnUse" + id="linearGradient4230" + xlink:href="#linearGradient3149" + inkscape:collect="always" /> + <radialGradient + gradientUnits="userSpaceOnUse" + r="8.6620579" + fy="19.008621" + fx="31.112698" + cy="19.008621" + cx="31.112698" + id="radialGradient4222" + xlink:href="#linearGradient2812" + inkscape:collect="always" /> + <linearGradient + gradientUnits="userSpaceOnUse" + y2="11.024895" + x2="10.623409" + y1="2.7991772" + x1="4.5264969" + id="linearGradient4220" + xlink:href="#linearGradient2804" + inkscape:collect="always" /> + <linearGradient + gradientUnits="userSpaceOnUse" + y2="27.77807" + x2="12.233074" + y1="11.789385" + x1="6.878005" + id="linearGradient4218" + xlink:href="#linearGradient2851" + inkscape:collect="always" /> + <linearGradient + id="linearGradient4212"> + <stop + id="stop4214" + offset="0" + style="stop-color:#73d216;stop-opacity:1;" /> + <stop + id="stop4216" + offset="1" + style="stop-color:#5ca911;stop-opacity:1;" /> + </linearGradient> + <linearGradient + y2="40.032413" + x2="17.890068" + y1="8.0617304" + x1="17.890068" + gradientUnits="userSpaceOnUse" + id="linearGradient4210" + xlink:href="#linearGradient3149" + inkscape:collect="always" /> + <linearGradient + id="linearGradient3292"> + <stop + style="stop-color:#f5f5f5;stop-opacity:1.0000000;" + offset="0.0000000" + id="stop3294" /> + <stop + style="stop-color:#e9e9e9;stop-opacity:1.0000000;" + offset="1.0000000" + id="stop3296" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient29418" + id="linearGradient3298" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-0.977228,0,0,0.995878,50.60272,9.115637)" + x1="35.003674" + y1="10.957423" + x2="27.273300" + y2="24.143761" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient3300" + gradientUnits="userSpaceOnUse" + x1="21.875" + y1="48.000977" + x2="21.875" + y2="40" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient3302" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient3304" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <linearGradient + id="linearGradient3306"> + <stop + style="stop-color:black;stop-opacity:0;" + offset="0" + id="stop3308" /> + <stop + id="stop3310" + offset="0.5" + style="stop-color:black;stop-opacity:1;" /> + <stop + style="stop-color:black;stop-opacity:0;" + offset="1" + id="stop3312" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient3314" + gradientUnits="userSpaceOnUse" + x1="21.875" + y1="48.000977" + x2="21.875" + y2="40" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient3316" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient3324" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient3326" + x1="15.535398" + y1="1.8014067" + x2="15.535398" + y2="48.674999" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.37378,0,0,0.375227,17.64779,15.86312)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2186" + id="linearGradient3334" + x1="11.226587" + y1="-5.4832759" + x2="11.226587" + y2="17.697369" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.529942,0,0,0.53199,17.26643,15.48536)" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3816" + id="radialGradient3348" + cx="31.112698" + cy="19.008621" + fx="31.112698" + fy="19.008621" + r="8.6620579" + gradientUnits="userSpaceOnUse" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2200" + id="radialGradient3356" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-2.522332,-1.518129e-16,-1.517788e-16,2.521765,40.1904,-21.83521)" + cx="9.9988937" + cy="8.963316" + fx="9.9988937" + fy="8.963316" + r="7.0034069" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2200" + id="radialGradient3358" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-2.522332,-1.518129e-16,-1.517788e-16,2.521765,40.1904,-21.80154)" + cx="9.9988937" + cy="8.963316" + fx="9.9988937" + fy="8.963316" + r="7.0034069" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2260" + id="radialGradient3360" + cx="11.756953" + cy="17.588654" + fx="11.756953" + fy="17.588654" + r="6.3436799" + gradientTransform="matrix(1,0,0,0.626667,0,6.566431)" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient3368" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.371983,0,0,0.372254,2.539836,8.539528)" + x1="15.602553" + y1="1.5657365" + x2="15.522223" + y2="33.483475" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2186" + id="linearGradient3370" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.529942,0,0,0.53199,17.26643,15.48536)" + x1="11.226587" + y1="-5.4832759" + x2="11.226587" + y2="17.697369" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient3372" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.37378,0,0,0.375227,17.64779,15.86312)" + x1="15.535398" + y1="1.8014067" + x2="15.535398" + y2="48.674999" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2225" + id="linearGradient3374" + gradientUnits="userSpaceOnUse" + x1="11.802028" + y1="1.9986149" + x2="11.802028" + y2="14.895812" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2225" + id="linearGradient2231" + x1="11.802028" + y1="1.9986149" + x2="11.802028" + y2="14.895812" + gradientUnits="userSpaceOnUse" /> + <linearGradient + id="linearGradient3093"> + <stop + style="stop-color:#f5f5f5;stop-opacity:1.0000000;" + offset="0.0000000" + id="stop3095" /> + <stop + style="stop-color:#e9e9e9;stop-opacity:1.0000000;" + offset="1.0000000" + id="stop3097" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient29418" + id="linearGradient3099" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-0.977228,0,0,0.995878,50.60272,9.115637)" + x1="35.003674" + y1="10.957423" + x2="27.273300" + y2="24.143761" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient3101" + gradientUnits="userSpaceOnUse" + x1="21.875" + y1="48.000977" + x2="21.875" + y2="40" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient3103" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient3105" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <linearGradient + id="linearGradient3107"> + <stop + style="stop-color:black;stop-opacity:0;" + offset="0" + id="stop3109" /> + <stop + id="stop3111" + offset="0.5" + style="stop-color:black;stop-opacity:1;" /> + <stop + style="stop-color:black;stop-opacity:0;" + offset="1" + id="stop3113" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient3115" + gradientUnits="userSpaceOnUse" + x1="21.875" + y1="48.000977" + x2="21.875" + y2="40" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient3117" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient3125" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient3127" + x1="15.535398" + y1="1.8014067" + x2="15.535398" + y2="48.674999" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.37378,0,0,0.375227,17.64779,15.86312)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2186" + id="linearGradient3135" + x1="11.226587" + y1="-5.4832759" + x2="11.226587" + y2="17.697369" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.529942,0,0,0.53199,17.26643,15.48536)" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3816" + id="radialGradient3149" + cx="31.112698" + cy="19.008621" + fx="31.112698" + fy="19.008621" + r="8.6620579" + gradientUnits="userSpaceOnUse" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2200" + id="radialGradient3158" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-2.522332,-1.518129e-16,-1.517788e-16,2.521765,40.1904,-21.83521)" + cx="9.9988937" + cy="8.963316" + fx="9.9988937" + fy="8.963316" + r="7.0034069" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2200" + id="radialGradient3160" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-2.522332,-1.518129e-16,-1.517788e-16,2.521765,40.1904,-21.80154)" + cx="9.9988937" + cy="8.963316" + fx="9.9988937" + fy="8.963316" + r="7.0034069" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2260" + id="radialGradient3162" + cx="11.756953" + cy="17.588654" + fx="11.756953" + fy="17.588654" + r="6.3436799" + gradientTransform="matrix(1,0,0,0.626667,0,6.566431)" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient3170" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.371983,0,0,0.372254,2.539836,8.539528)" + x1="15.602553" + y1="1.5657365" + x2="15.522223" + y2="33.483475" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2186" + id="linearGradient3172" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.529942,0,0,0.53199,17.26643,15.48536)" + x1="11.226587" + y1="-5.4832759" + x2="11.226587" + y2="17.697369" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient3174" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.37378,0,0,0.375227,17.64779,15.86312)" + x1="15.535398" + y1="1.8014067" + x2="15.535398" + y2="48.674999" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2186" + id="linearGradient3176" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.525701,0,0,0.525844,2.191252,8.189764)" + x1="11.226587" + y1="-5.4832759" + x2="11.226587" + y2="17.697369" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient3178" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.370788,0,0,0.370892,2.569561,8.563159)" + x1="15.535398" + y1="1.8014067" + x2="15.535398" + y2="48.674999" /> + <linearGradient + id="linearGradient4148"> + <stop + style="stop-color:#f5f5f5;stop-opacity:1.0000000;" + offset="0.0000000" + id="stop4150" /> + <stop + style="stop-color:#e9e9e9;stop-opacity:1.0000000;" + offset="1.0000000" + id="stop4152" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient29418" + id="linearGradient4146" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-0.977228,0,0,0.995878,50.60272,9.115637)" + x1="35.003674" + y1="10.957423" + x2="27.273300" + y2="24.143761" /> + <linearGradient + id="linearGradient2947"> + <stop + style="stop-color:black;stop-opacity:0;" + offset="0" + id="stop2949" /> + <stop + id="stop2951" + offset="0.5" + style="stop-color:black;stop-opacity:1;" /> + <stop + style="stop-color:black;stop-opacity:0;" + offset="1" + id="stop4144" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient4139" + gradientUnits="userSpaceOnUse" + x1="21.875" + y1="48.000977" + x2="21.875" + y2="40" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient4137" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient4135" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient4133" + x1="15.535398" + y1="1.8014067" + x2="15.535398" + y2="48.674999" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.37378,0,0,0.375227,17.64779,15.86312)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2186" + id="linearGradient4125" + x1="11.226587" + y1="-5.4832759" + x2="11.226587" + y2="17.697369" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.529942,0,0,0.53199,17.26643,15.48536)" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3816" + id="radialGradient4111" + cx="31.112698" + cy="19.008621" + fx="31.112698" + fy="19.008621" + r="8.6620579" + gradientUnits="userSpaceOnUse" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2200" + id="radialGradient4103" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-2.522332,-1.518129e-16,-1.517788e-16,2.521765,40.1904,-21.83521)" + cx="9.9988937" + cy="8.963316" + fx="9.9988937" + fy="8.963316" + r="7.0034069" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2200" + id="radialGradient4101" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-2.522332,-1.518129e-16,-1.517788e-16,2.521765,40.1904,-21.80154)" + cx="9.9988937" + cy="8.963316" + fx="9.9988937" + fy="8.963316" + r="7.0034069" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2186" + id="linearGradient4093" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.529942,0,0,0.53199,17.26643,15.48536)" + x1="11.226587" + y1="-5.4832759" + x2="11.226587" + y2="17.697369" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient4091" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.37378,0,0,0.375227,17.64779,15.86312)" + x1="15.535398" + y1="1.8014067" + x2="15.535398" + y2="48.674999" /> + <linearGradient + y2="40" + x2="21.875" + y1="48.000977" + x1="21.875" + gradientUnits="userSpaceOnUse" + id="linearGradient4089" + xlink:href="#linearGradient2804" + inkscape:collect="always" /> + <radialGradient + r="5" + fy="44" + fx="1" + cy="44" + cx="1" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + gradientUnits="userSpaceOnUse" + id="radialGradient4087" + xlink:href="#linearGradient2781" + inkscape:collect="always" /> + <radialGradient + r="5" + fy="44" + fx="1" + cy="44" + cx="1" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + gradientUnits="userSpaceOnUse" + id="radialGradient4085" + xlink:href="#linearGradient2781" + inkscape:collect="always" /> + <linearGradient + id="linearGradient4079"> + <stop + style="stop-color:#73d216;stop-opacity:1;" + offset="0" + id="stop4081" /> + <stop + style="stop-color:#5ca911;stop-opacity:1;" + offset="1" + id="stop4083" /> + </linearGradient> + <linearGradient + id="linearGradient4071"> + <stop + style="stop-color:black;stop-opacity:0;" + offset="0" + id="stop4073" /> + <stop + id="stop4075" + offset="0.5" + style="stop-color:black;stop-opacity:1;" /> + <stop + style="stop-color:black;stop-opacity:0;" + offset="1" + id="stop4077" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient4069" + gradientUnits="userSpaceOnUse" + x1="21.875" + y1="48.000977" + x2="21.875" + y2="40" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient4067" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient4059" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2260" + id="radialGradient5300" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1,0,0,0.626667,0,6.566431)" + cx="11.756953" + cy="17.588654" + fx="11.756953" + fy="17.588654" + r="6.3436799" /> + <linearGradient + id="linearGradient3466"> + <stop + style="stop-color:black;stop-opacity:0;" + offset="0" + id="stop3468" /> + <stop + id="stop3470" + offset="0.5" + style="stop-color:black;stop-opacity:1;" /> + <stop + style="stop-color:black;stop-opacity:0;" + offset="1" + id="stop3472" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient5306" + gradientUnits="userSpaceOnUse" + x1="21.875" + y1="48.000977" + x2="21.875" + y2="40" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient5304" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient5302" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <linearGradient + id="linearGradient4633"> + <stop + style="stop-color:#f5f5f5;stop-opacity:1.0000000;" + offset="0.0000000" + id="stop4635" /> + <stop + style="stop-color:#e9e9e9;stop-opacity:1.0000000;" + offset="1.0000000" + id="stop4637" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient29418" + id="linearGradient4631" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-0.977228,0,0,0.995878,50.60272,9.115637)" + x1="35.003674" + y1="10.957423" + x2="27.273300" + y2="24.143761" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient4629" + gradientUnits="userSpaceOnUse" + x1="21.875" + y1="48.000977" + x2="21.875" + y2="40" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient4627" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient4625" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <linearGradient + id="linearGradient4617"> + <stop + style="stop-color:black;stop-opacity:0;" + offset="0" + id="stop4619" /> + <stop + id="stop4621" + offset="0.5" + style="stop-color:black;stop-opacity:1;" /> + <stop + style="stop-color:black;stop-opacity:0;" + offset="1" + id="stop4623" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient4615" + gradientUnits="userSpaceOnUse" + x1="21.875" + y1="48.000977" + x2="21.875" + y2="40" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient4613" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient4611" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient4609" + x1="15.535398" + y1="1.8014067" + x2="15.535398" + y2="48.674999" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.37378,0,0,0.375227,17.64779,15.86312)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2186" + id="linearGradient4607" + x1="11.226587" + y1="-5.4832759" + x2="11.226587" + y2="17.697369" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.529942,0,0,0.53199,17.26643,15.48536)" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3816" + id="radialGradient4605" + cx="31.112698" + cy="19.008621" + fx="31.112698" + fy="19.008621" + r="8.6620579" + gradientUnits="userSpaceOnUse" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2200" + id="radialGradient4603" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-2.522332,-1.518129e-16,-1.517788e-16,2.521765,40.1904,-21.83521)" + cx="9.9988937" + cy="8.963316" + fx="9.9988937" + fy="8.963316" + r="7.0034069" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2200" + id="radialGradient4601" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-2.522332,-1.518129e-16,-1.517788e-16,2.521765,40.1904,-21.80154)" + cx="9.9988937" + cy="8.963316" + fx="9.9988937" + fy="8.963316" + r="7.0034069" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2260" + id="radialGradient4599" + cx="11.756953" + cy="17.588654" + fx="11.756953" + fy="17.588654" + r="6.3436799" + gradientTransform="matrix(1,0,0,0.626667,0,6.566431)" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient4597" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.371983,0,0,0.372254,2.539836,8.539528)" + x1="15.602553" + y1="1.5657365" + x2="15.522223" + y2="33.483475" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2186" + id="linearGradient4595" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.529942,0,0,0.53199,17.26643,15.48536)" + x1="11.226587" + y1="-5.4832759" + x2="11.226587" + y2="17.697369" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient4593" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.37378,0,0,0.375227,17.64779,15.86312)" + x1="15.535398" + y1="1.8014067" + x2="15.535398" + y2="48.674999" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2225" + id="linearGradient4591" + gradientUnits="userSpaceOnUse" + x1="11.802028" + y1="1.9986149" + x2="11.802028" + y2="14.895812" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2225" + id="linearGradient4583" + x1="11.802028" + y1="1.9986149" + x2="11.802028" + y2="14.895812" + gradientUnits="userSpaceOnUse" /> + <linearGradient + id="linearGradient4577"> + <stop + style="stop-color:#f5f5f5;stop-opacity:1.0000000;" + offset="0.0000000" + id="stop4579" /> + <stop + style="stop-color:#e9e9e9;stop-opacity:1.0000000;" + offset="1.0000000" + id="stop4581" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient29418" + id="linearGradient4575" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-0.977228,0,0,0.995878,50.60272,9.115637)" + x1="35.003674" + y1="10.957423" + x2="27.273300" + y2="24.143761" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient4573" + gradientUnits="userSpaceOnUse" + x1="21.875" + y1="48.000977" + x2="21.875" + y2="40" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient4571" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient4569" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <linearGradient + id="linearGradient4561"> + <stop + style="stop-color:black;stop-opacity:0;" + offset="0" + id="stop4563" /> + <stop + id="stop4565" + offset="0.5" + style="stop-color:black;stop-opacity:1;" /> + <stop + style="stop-color:black;stop-opacity:0;" + offset="1" + id="stop4567" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient4559" + gradientUnits="userSpaceOnUse" + x1="21.875" + y1="48.000977" + x2="21.875" + y2="40" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient4557" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient4555" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient4553" + x1="15.535398" + y1="1.8014067" + x2="15.535398" + y2="48.674999" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.37378,0,0,0.375227,17.64779,15.86312)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2186" + id="linearGradient4551" + x1="11.226587" + y1="-5.4832759" + x2="11.226587" + y2="17.697369" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.529942,0,0,0.53199,17.26643,15.48536)" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3816" + id="radialGradient4549" + cx="31.112698" + cy="19.008621" + fx="31.112698" + fy="19.008621" + r="8.6620579" + gradientUnits="userSpaceOnUse" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2200" + id="radialGradient4547" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-2.522332,-1.518129e-16,-1.517788e-16,2.521765,40.1904,-21.83521)" + cx="9.9988937" + cy="8.963316" + fx="9.9988937" + fy="8.963316" + r="7.0034069" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2200" + id="radialGradient4545" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-2.522332,-1.518129e-16,-1.517788e-16,2.521765,40.1904,-21.80154)" + cx="9.9988937" + cy="8.963316" + fx="9.9988937" + fy="8.963316" + r="7.0034069" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2260" + id="radialGradient4543" + cx="11.756953" + cy="17.588654" + fx="11.756953" + fy="17.588654" + r="6.3436799" + gradientTransform="matrix(1,0,0,0.626667,0,6.566431)" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient4541" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.371983,0,0,0.372254,2.539836,8.539528)" + x1="15.602553" + y1="1.5657365" + x2="15.522223" + y2="33.483475" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2186" + id="linearGradient4539" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.529942,0,0,0.53199,17.26643,15.48536)" + x1="11.226587" + y1="-5.4832759" + x2="11.226587" + y2="17.697369" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient4537" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.37378,0,0,0.375227,17.64779,15.86312)" + x1="15.535398" + y1="1.8014067" + x2="15.535398" + y2="48.674999" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2186" + id="linearGradient4535" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.525701,0,0,0.525844,2.191252,8.189764)" + x1="11.226587" + y1="-5.4832759" + x2="11.226587" + y2="17.697369" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient4533" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.370788,0,0,0.370892,2.569561,8.563159)" + x1="15.535398" + y1="1.8014067" + x2="15.535398" + y2="48.674999" /> + <linearGradient + id="linearGradient4527"> + <stop + style="stop-color:#f5f5f5;stop-opacity:1.0000000;" + offset="0.0000000" + id="stop4529" /> + <stop + style="stop-color:#e9e9e9;stop-opacity:1.0000000;" + offset="1.0000000" + id="stop4531" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient29418" + id="linearGradient4525" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-0.977228,0,0,0.995878,50.60272,9.115637)" + x1="35.003674" + y1="10.957423" + x2="27.273300" + y2="24.143761" /> + <linearGradient + id="linearGradient4517"> + <stop + style="stop-color:black;stop-opacity:0;" + offset="0" + id="stop4519" /> + <stop + id="stop4521" + offset="0.5" + style="stop-color:black;stop-opacity:1;" /> + <stop + style="stop-color:black;stop-opacity:0;" + offset="1" + id="stop4523" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient4515" + gradientUnits="userSpaceOnUse" + x1="21.875" + y1="48.000977" + x2="21.875" + y2="40" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient4513" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient4511" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient4509" + x1="15.535398" + y1="1.8014067" + x2="15.535398" + y2="48.674999" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.37378,0,0,0.375227,17.64779,15.86312)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2186" + id="linearGradient4501" + x1="11.226587" + y1="-5.4832759" + x2="11.226587" + y2="17.697369" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.529942,0,0,0.53199,17.26643,15.48536)" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3816" + id="radialGradient4487" + cx="31.112698" + cy="19.008621" + fx="31.112698" + fy="19.008621" + r="8.6620579" + gradientUnits="userSpaceOnUse" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2200" + id="radialGradient4479" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-2.522332,-1.518129e-16,-1.517788e-16,2.521765,40.1904,-21.83521)" + cx="9.9988937" + cy="8.963316" + fx="9.9988937" + fy="8.963316" + r="7.0034069" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2200" + id="radialGradient4477" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-2.522332,-1.518129e-16,-1.517788e-16,2.521765,40.1904,-21.80154)" + cx="9.9988937" + cy="8.963316" + fx="9.9988937" + fy="8.963316" + r="7.0034069" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2186" + id="linearGradient4469" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.529942,0,0,0.53199,17.26643,15.48536)" + x1="11.226587" + y1="-5.4832759" + x2="11.226587" + y2="17.697369" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient4467" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.37378,0,0,0.375227,17.64779,15.86312)" + x1="15.535398" + y1="1.8014067" + x2="15.535398" + y2="48.674999" /> + <linearGradient + y2="40" + x2="21.875" + y1="48.000977" + x1="21.875" + gradientUnits="userSpaceOnUse" + id="linearGradient4465" + xlink:href="#linearGradient2804" + inkscape:collect="always" /> + <radialGradient + r="5" + fy="44" + fx="1" + cy="44" + cx="1" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + gradientUnits="userSpaceOnUse" + id="radialGradient4463" + xlink:href="#linearGradient2781" + inkscape:collect="always" /> + <radialGradient + r="5" + fy="44" + fx="1" + cy="44" + cx="1" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + gradientUnits="userSpaceOnUse" + id="radialGradient4461" + xlink:href="#linearGradient2781" + inkscape:collect="always" /> + <linearGradient + id="linearGradient4455"> + <stop + style="stop-color:#73d216;stop-opacity:1;" + offset="0" + id="stop4457" /> + <stop + style="stop-color:#5ca911;stop-opacity:1;" + offset="1" + id="stop4459" /> + </linearGradient> + <linearGradient + id="linearGradient4447"> + <stop + style="stop-color:black;stop-opacity:0;" + offset="0" + id="stop4449" /> + <stop + id="stop4451" + offset="0.5" + style="stop-color:black;stop-opacity:1;" /> + <stop + style="stop-color:black;stop-opacity:0;" + offset="1" + id="stop4453" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient4445" + gradientUnits="userSpaceOnUse" + x1="21.875" + y1="48.000977" + x2="21.875" + y2="40" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient4443" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient4435" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <linearGradient + gradientTransform="matrix(0.799641,0,0,0.799917,3.703059,-1.099214)" + y2="14.895812" + x2="11.802028" + y1="1.9986149" + x1="11.802028" + gradientUnits="userSpaceOnUse" + id="linearGradient3211" + xlink:href="#linearGradient2225" + inkscape:collect="always" /> + <radialGradient + r="6.3436799" + fy="17.588654" + fx="11.756953" + cy="17.588654" + cx="11.756953" + gradientTransform="matrix(1,0,0,0.626667,0,6.566431)" + gradientUnits="userSpaceOnUse" + id="radialGradient3207" + xlink:href="#linearGradient2260" + inkscape:collect="always" /> + <linearGradient + y2="40" + x2="21.875" + y1="48.000977" + x1="21.875" + gradientUnits="userSpaceOnUse" + id="linearGradient3205" + xlink:href="#linearGradient2804" + inkscape:collect="always" /> + <radialGradient + r="5" + fy="44" + fx="1" + cy="44" + cx="1" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + gradientUnits="userSpaceOnUse" + id="radialGradient3203" + xlink:href="#linearGradient2781" + inkscape:collect="always" /> + <radialGradient + r="5" + fy="44" + fx="1" + cy="44" + cx="1" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + gradientUnits="userSpaceOnUse" + id="radialGradient3201" + xlink:href="#linearGradient2781" + inkscape:collect="always" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2225" + id="linearGradient5259" + x1="11.802028" + y1="1.9986149" + x2="11.802028" + y2="14.895812" + gradientUnits="userSpaceOnUse" /> + <linearGradient + id="linearGradient5253"> + <stop + style="stop-color:#f5f5f5;stop-opacity:1.0000000;" + offset="0.0000000" + id="stop5255" /> + <stop + style="stop-color:#e9e9e9;stop-opacity:1.0000000;" + offset="1.0000000" + id="stop5257" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient29418" + id="linearGradient5251" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-0.977228,0,0,0.995878,50.60272,9.115637)" + x1="35.003674" + y1="10.957423" + x2="27.273300" + y2="24.143761" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient5249" + gradientUnits="userSpaceOnUse" + x1="21.875" + y1="48.000977" + x2="21.875" + y2="40" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient5247" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient5245" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <linearGradient + id="linearGradient5237"> + <stop + style="stop-color:black;stop-opacity:0;" + offset="0" + id="stop5239" /> + <stop + id="stop5241" + offset="0.5" + style="stop-color:black;stop-opacity:1;" /> + <stop + style="stop-color:black;stop-opacity:0;" + offset="1" + id="stop5243" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient5235" + gradientUnits="userSpaceOnUse" + x1="21.875" + y1="48.000977" + x2="21.875" + y2="40" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient5233" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient5231" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient5229" + x1="15.535398" + y1="1.8014067" + x2="15.535398" + y2="48.674999" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.37378,0,0,0.375227,17.64779,15.86312)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2186" + id="linearGradient5227" + x1="11.226587" + y1="-5.4832759" + x2="11.226587" + y2="17.697369" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.529942,0,0,0.53199,17.26643,15.48536)" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3816" + id="radialGradient5225" + cx="31.112698" + cy="19.008621" + fx="31.112698" + fy="19.008621" + r="8.6620579" + gradientUnits="userSpaceOnUse" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2200" + id="radialGradient5223" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-2.522332,-1.518129e-16,-1.517788e-16,2.521765,40.1904,-21.83521)" + cx="9.9988937" + cy="8.963316" + fx="9.9988937" + fy="8.963316" + r="7.0034069" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2200" + id="radialGradient5221" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-2.522332,-1.518129e-16,-1.517788e-16,2.521765,40.1904,-21.80154)" + cx="9.9988937" + cy="8.963316" + fx="9.9988937" + fy="8.963316" + r="7.0034069" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2260" + id="radialGradient5219" + cx="11.756953" + cy="17.588654" + fx="11.756953" + fy="17.588654" + r="6.3436799" + gradientTransform="matrix(1,0,0,0.626667,0,6.566431)" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient5217" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.371983,0,0,0.372254,2.539836,8.539528)" + x1="15.602553" + y1="1.5657365" + x2="15.522223" + y2="33.483475" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2186" + id="linearGradient5215" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.529942,0,0,0.53199,17.26643,15.48536)" + x1="11.226587" + y1="-5.4832759" + x2="11.226587" + y2="17.697369" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient5213" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.37378,0,0,0.375227,17.64779,15.86312)" + x1="15.535398" + y1="1.8014067" + x2="15.535398" + y2="48.674999" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2186" + id="linearGradient5211" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.525701,0,0,0.525844,2.191252,8.189764)" + x1="11.226587" + y1="-5.4832759" + x2="11.226587" + y2="17.697369" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient5209" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.370788,0,0,0.370892,2.569561,8.563159)" + x1="15.535398" + y1="1.8014067" + x2="15.535398" + y2="48.674999" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2225" + id="linearGradient5207" + gradientUnits="userSpaceOnUse" + x1="11.802028" + y1="1.9986149" + x2="11.802028" + y2="14.895812" /> + <linearGradient + y2="48.674999" + x2="15.535398" + y1="1.8014067" + x1="15.535398" + gradientTransform="matrix(-0.296522,0,0,0.296523,15.24437,5.755639)" + gradientUnits="userSpaceOnUse" + id="linearGradient3013" + xlink:href="#linearGradient2239" + inkscape:collect="always" /> + <linearGradient + y2="17.697369" + x2="11.226587" + y1="-5.4832759" + x1="11.226587" + gradientTransform="matrix(-0.420408,0,0,0.420404,15.5469,5.457115)" + gradientUnits="userSpaceOnUse" + id="linearGradient3011" + xlink:href="#linearGradient2186" + inkscape:collect="always" /> + <linearGradient + id="linearGradient5199"> + <stop + style="stop-color:#f5f5f5;stop-opacity:1.0000000;" + offset="0.0000000" + id="stop5201" /> + <stop + style="stop-color:#e9e9e9;stop-opacity:1.0000000;" + offset="1.0000000" + id="stop5203" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient29418" + id="linearGradient5197" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-0.977228,0,0,0.995878,50.60272,9.115637)" + x1="35.003674" + y1="10.957423" + x2="27.273300" + y2="24.143761" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient2261" + gradientUnits="userSpaceOnUse" + x1="21.875" + y1="48.000977" + x2="21.875" + y2="40" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient2259" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient2257" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <linearGradient + id="linearGradient5186"> + <stop + style="stop-color:black;stop-opacity:0;" + offset="0" + id="stop5188" /> + <stop + id="stop5190" + offset="0.5" + style="stop-color:black;stop-opacity:1;" /> + <stop + style="stop-color:black;stop-opacity:0;" + offset="1" + id="stop5192" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient5184" + gradientUnits="userSpaceOnUse" + x1="21.875" + y1="48.000977" + x2="21.875" + y2="40" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient5182" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient5180" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient5178" + x1="15.535398" + y1="1.8014067" + x2="15.535398" + y2="48.674999" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.37378,0,0,0.375227,17.64779,15.86312)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2186" + id="linearGradient5170" + x1="11.226587" + y1="-5.4832759" + x2="11.226587" + y2="17.697369" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.529942,0,0,0.53199,17.26643,15.48536)" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3816" + id="radialGradient5156" + cx="31.112698" + cy="19.008621" + fx="31.112698" + fy="19.008621" + r="8.6620579" + gradientUnits="userSpaceOnUse" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2200" + id="radialGradient5148" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-2.522332,-1.518129e-16,-1.517788e-16,2.521765,40.1904,-21.83521)" + cx="9.9988937" + cy="8.963316" + fx="9.9988937" + fy="8.963316" + r="7.0034069" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2200" + id="radialGradient5146" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-2.522332,-1.518129e-16,-1.517788e-16,2.521765,40.1904,-21.80154)" + cx="9.9988937" + cy="8.963316" + fx="9.9988937" + fy="8.963316" + r="7.0034069" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2260" + id="radialGradient5144" + cx="11.756953" + cy="17.588654" + fx="11.756953" + fy="17.588654" + r="6.3436799" + gradientTransform="matrix(1,0,0,0.626667,0,6.566431)" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient5136" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.371983,0,0,0.372254,2.539836,8.539528)" + x1="15.602553" + y1="1.5657365" + x2="15.522223" + y2="33.483475" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2186" + id="linearGradient5134" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.529942,0,0,0.53199,17.26643,15.48536)" + x1="11.226587" + y1="-5.4832759" + x2="11.226587" + y2="17.697369" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient5132" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.37378,0,0,0.375227,17.64779,15.86312)" + x1="15.535398" + y1="1.8014067" + x2="15.535398" + y2="48.674999" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2186" + id="linearGradient5130" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.525701,0,0,0.525844,2.191252,8.189764)" + x1="11.226587" + y1="-5.4832759" + x2="11.226587" + y2="17.697369" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2239" + id="linearGradient5128" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.370788,0,0,0.370892,2.569561,8.563159)" + x1="15.535398" + y1="1.8014067" + x2="15.535398" + y2="48.674999" /> + <linearGradient + y2="40" + x2="21.875" + y1="48.000977" + x1="21.875" + gradientUnits="userSpaceOnUse" + id="linearGradient5126" + xlink:href="#linearGradient2804" + inkscape:collect="always" /> + <radialGradient + r="5" + fy="44" + fx="1" + cy="44" + cx="1" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + gradientUnits="userSpaceOnUse" + id="radialGradient5124" + xlink:href="#linearGradient2781" + inkscape:collect="always" /> + <radialGradient + r="5" + fy="44" + fx="1" + cy="44" + cx="1" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + gradientUnits="userSpaceOnUse" + id="radialGradient5122" + xlink:href="#linearGradient2781" + inkscape:collect="always" /> + <linearGradient + gradientTransform="matrix(0.36035,0,0,0.358865,4.074001,4.193834)" + y2="27.77807" + x2="12.233074" + y1="11.789385" + x1="6.878005" + gradientUnits="userSpaceOnUse" + id="linearGradient5120" + xlink:href="#linearGradient2851" + inkscape:collect="always" /> + <linearGradient + gradientTransform="matrix(0.287092,0,0,0.287092,5.363906,5.455062)" + y2="34.458977" + x2="17.890068" + y1="2.2464287" + x1="17.890068" + gradientUnits="userSpaceOnUse" + id="linearGradient5118" + xlink:href="#linearGradient3149" + inkscape:collect="always" /> + <linearGradient + id="linearGradient5106"> + <stop + style="stop-color:#73d216;stop-opacity:1;" + offset="0" + id="stop5108" /> + <stop + style="stop-color:#5ca911;stop-opacity:1;" + offset="1" + id="stop5110" /> + </linearGradient> + <linearGradient + id="linearGradient5098"> + <stop + style="stop-color:black;stop-opacity:0;" + offset="0" + id="stop5100" /> + <stop + id="stop5102" + offset="0.5" + style="stop-color:black;stop-opacity:1;" /> + <stop + style="stop-color:black;stop-opacity:0;" + offset="1" + id="stop5104" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2804" + id="linearGradient5096" + gradientUnits="userSpaceOnUse" + x1="21.875" + y1="48.000977" + x2="21.875" + y2="40" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient5094" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,36,8.8)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2781" + id="radialGradient5086" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" + cx="1" + cy="44" + fx="1" + fy="44" + r="5" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2225" + id="linearGradient5293" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.799641,0,0,0.799917,-1.2969486,-6.0992136)" + x1="11.802028" + y1="1.9986149" + x2="11.802028" + y2="14.895812" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="11.098901" + inkscape:cx="24.268079" + inkscape:cy="12.383905" + inkscape:current-layer="layer1" + showgrid="true" + inkscape:grid-bbox="true" + inkscape:document-units="px" + inkscape:window-width="1440" + inkscape:window-height="847" + inkscape:window-x="0" + inkscape:window-y="0" + width="11px" + height="11px" /> + <metadata + id="metadata1877"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + id="layer1" + inkscape:label="Layer 1" + inkscape:groupmode="layer"> + <path + style="fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1" + d="M 7.4671024,3.5945806 C 7.6975914,3.5945816 7.8846544,4.1557556 7.8846544,4.8472026 C 7.8846544,5.5386494 7.6975914,6.0998244 7.4671024,6.0998234 C 7.2366144,6.0998234 7.0495504,5.5386484 7.0495504,4.8472026 C 7.0495504,4.1557546 7.2366144,3.5945806 7.4671024,3.5945806 z " + id="path1588" /> + <path + style="fill:#888a85;fill-opacity:1;stroke:#555753;stroke-width:0.99999905;stroke-miterlimit:4;stroke-opacity:1" + d="M 9.0356994,9.0357004 C 7.0835864,10.987813 3.9152694,10.988142 1.9635634,9.0364384 C 0.011857449,7.0847304 0.012187449,3.916415 1.9643014,1.9643009 C 3.9164144,0.012187388 7.0847294,0.011856588 9.0364364,1.9635636 C 10.988143,3.9152692 10.987812,7.0835864 9.0356994,9.0357004 z " + id="path2187" /> + <path + style="opacity:0.4;fill:url(#linearGradient5293);fill-opacity:1;stroke:#ffffff;stroke-width:0.99999774;stroke-miterlimit:4;stroke-opacity:1" + d="M 5.4999974,1.4999993 C 4.4701574,1.5001066 3.4600094,1.8920184 2.6762664,2.6748775 C 1.1077144,4.2416618 1.1080924,6.7578834 2.6762664,8.3242924 C 4.2454614,9.8917164 6.7541574,9.8920954 8.3237284,8.3242924 C 9.8922794,6.7575084 9.8919014,4.2412844 8.3237284,2.6748775 C 7.5401624,1.8921947 6.5295274,1.499892 5.4999974,1.4999993 z " + id="path2215" /> + <path + style="fill:#eeeeec;fill-opacity:1;stroke:#555753;stroke-width:0.99999911;stroke-miterlimit:4;stroke-opacity:1" + d="M 7.0127094,2.0856389 L 5.4931354,3.5136891 L 4.0186124,1.9641835 L 1.9054394,4.0600449 L 3.5171444,5.4862974 L 1.9955384,6.9712984 L 4.1224304,9.0945484 L 5.4931354,7.4589104 L 6.9676594,9.0358034 L 9.0945514,6.9125544 L 7.4691314,5.4862974 L 9.1258834,4.2088865 L 7.0127094,2.0856389 z " + id="rect1322" + sodipodi:nodetypes="ccccccccccccc" /> + </g> +</svg>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pidgin/pixmaps/status/11/scalable/person.svg Mon Aug 27 21:59:11 2007 +0000 @@ -0,0 +1,212 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://web.resource.org/cc/" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="11" + height="11" + id="svg7380" + sodipodi:version="0.32" + inkscape:version="0.45.1" + sodipodi:docbase="/home/hbons/Desktop" + sodipodi:docname="person.svg" + inkscape:export-filename="/home/hbons/Desktop/person.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" + inkscape:output_extension="org.inkscape.output.svg.inkscape" + version="1.0"> + <defs + id="defs7382"> + <linearGradient + id="linearGradient3800"> + <stop + style="stop-color:#f4d9b1;stop-opacity:1.0000000;" + offset="0.0000000" + id="stop3802" /> + <stop + style="stop-color:#df9725;stop-opacity:1.0000000;" + offset="1.0000000" + id="stop3804" /> + </linearGradient> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3800" + id="radialGradient4171" + gradientUnits="userSpaceOnUse" + cx="27.702486" + cy="14.540437" + fx="27.702486" + fy="14.540437" + r="9.1620579" + gradientTransform="matrix(1.191087,0,0,1.124022,-5.086983,-1.361697)" /> + <linearGradient + inkscape:collect="always" + id="linearGradient7300"> + <stop + style="stop-color:#eeeeec;stop-opacity:1;" + offset="0" + id="stop7302" /> + <stop + style="stop-color:#eeeeec;stop-opacity:0;" + offset="1" + id="stop7304" /> + </linearGradient> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient7300" + id="radialGradient7306" + cx="24.248138" + cy="27.184834" + fx="24.248138" + fy="27.184834" + r="12.499089" + gradientTransform="matrix(0.964825,0,0,0.631898,0.954495,11.94073)" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + id="linearGradient3816"> + <stop + style="stop-color:#000000;stop-opacity:1;" + offset="0" + id="stop3818" /> + <stop + style="stop-color:#000000;stop-opacity:0;" + offset="1" + id="stop3820" /> + </linearGradient> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3816" + id="radialGradient4179" + gradientUnits="userSpaceOnUse" + cx="31.112698" + cy="19.008621" + fx="31.112698" + fy="19.008621" + r="8.6620579" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient7300" + id="radialGradient4244" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.964825,0,0,0.631898,0.954495,11.94073)" + cx="24.248138" + cy="27.184834" + fx="24.248138" + fy="27.184834" + r="12.499089" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3800" + id="radialGradient4246" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.191087,0,0,1.124022,-5.086983,-1.361697)" + cx="27.702486" + cy="14.540437" + fx="27.702486" + fy="14.540437" + r="9.1620579" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient7300" + id="radialGradient2631" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.964825,0,0,0.631898,0.954495,11.94073)" + cx="24.248138" + cy="27.184834" + fx="24.248138" + fy="27.184834" + r="12.499089" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3800" + id="radialGradient2633" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.191087,0,0,1.124022,-5.086983,-1.361697)" + cx="27.702486" + cy="14.540437" + fx="27.702486" + fy="14.540437" + r="9.1620579" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="36.060436" + inkscape:cx="13.678969" + inkscape:cy="6.3391799" + inkscape:current-layer="layer1" + showgrid="true" + inkscape:grid-bbox="true" + inkscape:document-units="px" + inkscape:window-width="1440" + inkscape:window-height="843" + inkscape:window-x="0" + inkscape:window-y="0" + width="11px" + height="11px" /> + <metadata + id="metadata7385"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + id="layer1" + inkscape:label="Layer 1" + inkscape:groupmode="layer"> + <path + style="opacity:1;color:#000000;fill:#ad7fa8;fill-opacity:1;fill-rule:evenodd;stroke:#5c3566;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" + d="M 3.6663219,10.5 L 6.5076606,10.5 C 7.3127061,10.5 8.109736,10.185178 8.4018859,9.2878787 C 8.6793163,8.4357862 8.449241,6.8131314 6.6497273,5.5000002 L 3.2874766,5.5000002 C 1.4879625,6.7121211 1.2630802,8.3698053 1.6773852,9.3383836 C 2.0994617,10.32513 2.8139203,10.5 3.6663219,10.5 z " + id="path4308" + sodipodi:nodetypes="cczcczc" /> + <path + sodipodi:type="inkscape:offset" + inkscape:radius="-1.1784238" + inkscape:original="M 24.5625 24.125 C 17.844986 28.367641 17.015916 34.172303 18.5625 37.5625 C 20.138096 41.016289 22.818019 41.625 26 41.625 L 36.59375 41.625 C 39.598953 41.624999 42.565667 40.546959 43.65625 37.40625 C 44.691891 34.423774 43.842514 28.721194 37.125 24.125 L 24.5625 24.125 z " + style="opacity:0.45454544;color:#000000;fill:url(#radialGradient2631);fill-opacity:1;fill-rule:evenodd;stroke:#eeeeec;stroke-width:4.89376259px;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" + id="path7281" + d="M 24.96875,25.3125 C 18.887883,29.293056 18.373983,34.320202 19.625,37.0625 C 20.318936,38.583645 21.166625,39.341162 22.1875,39.8125 C 23.208375,40.283838 24.484153,40.4375 26,40.4375 L 36.59375,40.4375 C 37.955442,40.4375 39.252462,40.19959 40.28125,39.65625 C 41.310038,39.11291 42.08087,38.328274 42.53125,37.03125 C 43.335253,34.715853 42.805994,29.63256 36.71875,25.3125 L 24.96875,25.3125 z " + transform="matrix(0.2105175,0,0,0.1983472,-1.5150706,1.4793374)" /> + <path + style="opacity:0.78977272;fill:#eeeeec;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1" + d="M 7,7.5000002 C 7,8.3280002 5.9468853,8.570739 5.0000003,9 C 3.660327,8.5959899 3,8.3280002 3,7.5000002 C 3,6.6720005 3.8959999,6 5.0000003,6 C 6.104,6 7,6.6720005 7,7.5000002 z " + id="path7285" + sodipodi:nodetypes="ccssc" /> + <path + sodipodi:type="arc" + style="opacity:1;color:#000000;fill:url(#radialGradient2633);fill-opacity:1;fill-rule:evenodd;stroke:#b2730d;stroke-width:2.47487783px;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" + id="path4320" + sodipodi:cx="31.112698" + sodipodi:cy="19.008621" + sodipodi:rx="8.6620579" + sodipodi:ry="8.6620579" + d="M 39.774755 19.008621 A 8.6620579 8.6620579 0 1 1 22.45064,19.008621 A 8.6620579 8.6620579 0 1 1 39.774755 19.008621 z" + transform="matrix(0.4040609,0,0,0.4040609,-7.5714258,-3.6806412)" /> + <path + d="M 39.774755 19.008621 A 8.6620579 8.6620579 0 1 1 22.45064,19.008621 A 8.6620579 8.6620579 0 1 1 39.774755 19.008621 z" + sodipodi:ry="8.6620579" + sodipodi:rx="8.6620579" + sodipodi:cy="19.008621" + sodipodi:cx="31.112698" + id="path4322" + style="opacity:0.25;color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:3.46482706px;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" + sodipodi:type="arc" + transform="matrix(0.288615,0,0,0.288615,-3.9795917,-1.4861729)" /> + </g> +</svg>
--- a/pidgin/pixmaps/status/16/rtl/Makefile.am Fri Aug 17 02:26:42 2007 +0000 +++ b/pidgin/pixmaps/status/16/rtl/Makefile.am Mon Aug 27 21:59:11 2007 +0000 @@ -1,4 +1,4 @@ -EXTRA_DIST = extended-away.png +EXTRA_DIST = extended-away.png log-in.png log-out.png pidginstatuspixdir = $(datadir)/pixmaps/pidgin/status/16/rtl
--- a/pidgin/pixmaps/status/16/scalable/away.svg Fri Aug 17 02:26:42 2007 +0000 +++ b/pidgin/pixmaps/status/16/scalable/away.svg Mon Aug 27 21:59:11 2007 +0000 @@ -18,7 +18,7 @@ inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/status/16/available16.png" inkscape:export-xdpi="90" inkscape:export-ydpi="90" - sodipodi:docbase="/home/hbons/Desktop/experiment/status/16/scalable" + sodipodi:docbase="/home/hbons/Desktop/2.0.2/pidgin/pixmaps/status/16/scalable" sodipodi:docname="away.svg"> <defs id="defs4"> @@ -122,7 +122,7 @@ showgrid="true" fill="#eeeeec" inkscape:window-width="1434" - inkscape:window-height="844" + inkscape:window-height="840" inkscape:window-x="0" inkscape:window-y="0" inkscape:object-paths="false" @@ -186,7 +186,7 @@ transform="matrix(0.383404,0,0,0.383404,2.022641,1.646167)" /> <path sodipodi:type="arc" - style="opacity:1;fill:#dcdcd8;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + style="opacity:1;fill:white;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path2796" sodipodi:cx="6.0403023" sodipodi:cy="7.5551186" @@ -220,18 +220,6 @@ x="7" y="-9" transform="matrix(0,1,-1,0,0,0)" /> - <path - sodipodi:type="arc" - style="opacity:1;fill:white;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - id="path2852" - sodipodi:cx="6.0403023" - sodipodi:cy="7.5551186" - sodipodi:rx="1.615877" - sodipodi:ry="1.3273276" - d="M 4.835244,8.4394021 A 1.615877,1.3273276 0 0 1 6.0776839,6.2281462 L 6.0403023,7.5551186 z" - transform="matrix(2.475436,0,0,3.013575,-6.952382,-14.76791)" - sodipodi:start="2.4124729" - sodipodi:end="4.735525" /> <rect style="opacity:1;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="rect2838"
--- a/pidgin/pixmaps/status/22/rtl/Makefile.am Fri Aug 17 02:26:42 2007 +0000 +++ b/pidgin/pixmaps/status/22/rtl/Makefile.am Mon Aug 27 21:59:11 2007 +0000 @@ -1,4 +1,4 @@ -EXTRA_DIST = extended-away.png +EXTRA_DIST = extended-away.png log-in.png log-out.png pidginstatuspixdir = $(datadir)/pixmaps/pidgin/status/22/rtl
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pidgin/pixmaps/status/22/scalable/sign-off.svg Mon Aug 27 21:59:11 2007 +0000 @@ -0,0 +1,196 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://web.resource.org/cc/" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="24" + height="24" + id="svg1316" + sodipodi:version="0.32" + inkscape:version="0.44.1" + version="1.0" + inkscape:export-filename="/home/hbons/Desktop/logout.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" + sodipodi:docbase="/home/hbons/Desktop/experiment/status/22/scalable" + sodipodi:docname="sign-off.svg"> + <defs + id="defs1318"> + <linearGradient + inkscape:collect="always" + id="linearGradient2773"> + <stop + style="stop-color:#eeeeec;stop-opacity:1;" + offset="0" + id="stop2775" /> + <stop + style="stop-color:#eeeeec;stop-opacity:0;" + offset="1" + id="stop2777" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + id="linearGradient3150"> + <stop + style="stop-color:#2e3436;stop-opacity:1;" + offset="0" + id="stop3152" /> + <stop + style="stop-color:#2e3436;stop-opacity:0;" + offset="1" + id="stop3154" /> + </linearGradient> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3150" + id="radialGradient3156" + cx="10.748654" + cy="10.457643" + fx="10.748654" + fy="10.457643" + r="6.6449099" + gradientTransform="matrix(-0.842757,0,0,-0.35721,19.80716,14.19321)" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + id="linearGradient2241"> + <stop + style="stop-color:#eeeeec;stop-opacity:1;" + offset="0" + id="stop2243" /> + <stop + style="stop-color:#eeeeec;stop-opacity:0;" + offset="1" + id="stop2245" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + id="linearGradient2203"> + <stop + style="stop-color:#727e0a;stop-opacity:1;" + offset="0" + id="stop2205" /> + <stop + style="stop-color:#727e0a;stop-opacity:0;" + offset="1" + id="stop2207" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2203" + id="linearGradient2209" + x1="16" + y1="24.34691" + x2="16" + y2="13.322957" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2241" + id="linearGradient2247" + x1="12.733098" + y1="7.7892389" + x2="17.02302" + y2="14.684355" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.113542,0,0,1.199983,-25.30573,-2.899671)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2773" + id="linearGradient2779" + x1="12.611981" + y1="7.7485132" + x2="17.922712" + y2="13.177787" + gradientUnits="userSpaceOnUse" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="18.473111" + inkscape:cx="23.638942" + inkscape:cy="12.598308" + inkscape:current-layer="layer1" + showgrid="true" + inkscape:grid-bbox="true" + inkscape:document-units="px" + fill="#eeeeec" + inkscape:window-width="1268" + inkscape:window-height="844" + inkscape:window-x="6" + inkscape:window-y="0" /> + <metadata + id="metadata1321"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + id="layer1" + inkscape:label="Layer 1" + inkscape:groupmode="layer"> + <path + sodipodi:type="arc" + style="opacity:0.5;fill:url(#radialGradient3156);fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="path3140" + sodipodi:cx="10.748654" + sodipodi:cy="10.457643" + sodipodi:rx="6.6449099" + sodipodi:ry="2.3675451" + d="M 17.393564 10.457643 A 6.6449099 2.3675451 0 1 1 4.1037445,10.457643 A 6.6449099 2.3675451 0 1 1 17.393564 10.457643 z" + transform="matrix(-1.580156,0,0,1.267134,27.48455,7.748764)" /> + <rect + style="opacity:1;fill:#c17d11;fill-opacity:1;stroke:#8f5902;stroke-width:0.99999899;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect1324" + width="12.000006" + height="19.999994" + x="-13.500007" + y="1.4999995" + ry="0" + transform="scale(-1,1)" /> + <rect + style="opacity:0.3;fill:url(#linearGradient2247);fill-opacity:1;stroke:white;stroke-width:0.99999833;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect2211" + width="10.000002" + height="18.000004" + x="-12.500002" + y="2.499999" + ry="0" + transform="scale(-1,1)" /> + <path + sodipodi:type="arc" + style="opacity:1;fill:#fcaf3e;fill-opacity:1;stroke:none;stroke-width:2.03035927;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="path2215" + sodipodi:cx="17.607706" + sodipodi:cy="10.679387" + sodipodi:rx="0.80383009" + sodipodi:ry="0.80383009" + d="M 18.411536 10.679387 A 0.80383009 0.80383009 0 1 1 16.803876,10.679387 A 0.80383009 0.80383009 0 1 1 18.411536 10.679387 z" + transform="matrix(-1.244041,0,0,1.244044,26.90471,-1.285625)" /> + <path + style="fill:#ef2929;fill-opacity:1;stroke:#a40000;stroke-width:1.00000012;stroke-miterlimit:4;stroke-opacity:1" + d="M 15.505983,6.2306652 L 15.513747,9.502742 L 22.5,9.5142628 L 22.495831,14.508783 L 15.513174,14.508783 L 15.50541,17.807767 L 9.3375971,12.000936 L 15.505983,6.2306652 z " + id="rect2249" + sodipodi:nodetypes="cccccccc" /> + <path + transform="matrix(1,0,0,0.978166,-0.125,0.246725)" + style="opacity:0.33300003;fill:url(#linearGradient2779);fill-opacity:1.0;stroke:white;stroke-width:1.0110991;stroke-miterlimit:4;stroke-opacity:1" + d="M 14.53125,8.5 L 10.78125,12 L 14.53125,15.53125 L 14.53125,14.5 C 14.539661,13.968497 14.968497,13.539661 15.5,13.53125 L 21.53125,13.53125 L 21.53125,10.46875 L 15.5,10.46875 C 14.968497,10.460339 14.539661,10.031503 14.53125,9.5 L 14.53125,8.5 z " + id="path2256" /> + </g> +</svg>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pidgin/pixmaps/status/22/scalable/sign-on.svg Mon Aug 27 21:59:11 2007 +0000 @@ -0,0 +1,197 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://web.resource.org/cc/" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="24" + height="24" + id="svg1316" + sodipodi:version="0.32" + inkscape:version="0.44.1" + version="1.0" + inkscape:export-filename="/home/hbons/Desktop/logout.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" + sodipodi:docbase="/home/hbons/Desktop/experiment/status/22/scalable" + sodipodi:docname="sign-on.svg"> + <defs + id="defs1318"> + <linearGradient + inkscape:collect="always" + id="linearGradient2773"> + <stop + style="stop-color:#eeeeec;stop-opacity:1;" + offset="0" + id="stop2775" /> + <stop + style="stop-color:#eeeeec;stop-opacity:0;" + offset="1" + id="stop2777" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + id="linearGradient3150"> + <stop + style="stop-color:#2e3436;stop-opacity:1;" + offset="0" + id="stop3152" /> + <stop + style="stop-color:#2e3436;stop-opacity:0;" + offset="1" + id="stop3154" /> + </linearGradient> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3150" + id="radialGradient3156" + cx="10.748654" + cy="10.457643" + fx="10.748654" + fy="10.457643" + r="6.6449099" + gradientTransform="matrix(-0.842757,0,0,-0.35721,19.80716,14.19321)" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + id="linearGradient2241"> + <stop + style="stop-color:#eeeeec;stop-opacity:1;" + offset="0" + id="stop2243" /> + <stop + style="stop-color:#eeeeec;stop-opacity:0;" + offset="1" + id="stop2245" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + id="linearGradient2203"> + <stop + style="stop-color:#727e0a;stop-opacity:1;" + offset="0" + id="stop2205" /> + <stop + style="stop-color:#727e0a;stop-opacity:0;" + offset="1" + id="stop2207" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2203" + id="linearGradient2209" + x1="16" + y1="24.34691" + x2="16" + y2="13.322957" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2241" + id="linearGradient2247" + x1="18.91893" + y1="8.0836868" + x2="15.486184" + y2="14.556396" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.113542,0,0,1.199983,-25.30573,-2.899671)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2773" + id="linearGradient2779" + x1="17.595509" + y1="8.398921" + x2="12.611981" + y2="13.493687" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-1,0,0,0.978166,32.125,0.246725)" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="18.473111" + inkscape:cx="23.638942" + inkscape:cy="12.598308" + inkscape:current-layer="layer1" + showgrid="true" + inkscape:grid-bbox="true" + inkscape:document-units="px" + fill="#eeeeec" + inkscape:window-width="1268" + inkscape:window-height="844" + inkscape:window-x="6" + inkscape:window-y="0" /> + <metadata + id="metadata1321"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + id="layer1" + inkscape:label="Layer 1" + inkscape:groupmode="layer"> + <path + sodipodi:type="arc" + style="opacity:0.5;fill:url(#radialGradient3156);fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="path3140" + sodipodi:cx="10.748654" + sodipodi:cy="10.457643" + sodipodi:rx="6.6449099" + sodipodi:ry="2.3675451" + d="M 17.393564 10.457643 A 6.6449099 2.3675451 0 1 1 4.1037445,10.457643 A 6.6449099 2.3675451 0 1 1 17.393564 10.457643 z" + transform="matrix(-1.580156,0,0,1.267134,27.48455,7.748764)" /> + <rect + style="opacity:1;fill:#c17d11;fill-opacity:1;stroke:#8f5902;stroke-width:0.99999899;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect1324" + width="12.000006" + height="19.999994" + x="-13.500007" + y="1.4999995" + ry="0" + transform="scale(-1,1)" /> + <rect + style="opacity:0.3;fill:url(#linearGradient2247);fill-opacity:1;stroke:white;stroke-width:0.99999833;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect2211" + width="10.000002" + height="18.000004" + x="-12.500002" + y="2.499999" + ry="0" + transform="scale(-1,1)" /> + <path + sodipodi:type="arc" + style="opacity:1;fill:#fcaf3e;fill-opacity:1;stroke:none;stroke-width:2.03035927;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="path2215" + sodipodi:cx="17.607706" + sodipodi:cy="10.679387" + sodipodi:rx="0.80383009" + sodipodi:ry="0.80383009" + d="M 18.411536 10.679387 A 0.80383009 0.80383009 0 1 1 16.803876,10.679387 A 0.80383009 0.80383009 0 1 1 18.411536 10.679387 z" + transform="matrix(-1.244041,0,0,1.244044,26.90471,-1.285625)" /> + <path + style="fill:#8ae234;fill-opacity:1;stroke:#458905;stroke-width:1.00000012;stroke-miterlimit:4;stroke-opacity:1" + d="M 16.494017,6.2306652 L 16.486253,9.502742 L 9.5000001,9.5142628 L 9.5041691,14.508783 L 16.486826,14.508783 L 16.49459,17.807767 L 23.149598,12.000936 L 16.494017,6.2306652 z " + id="rect2249" + sodipodi:nodetypes="cccccccc" /> + <path + style="opacity:0.33300003;fill:url(#linearGradient2779);fill-opacity:1;stroke:white;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1" + d="M 17.59375,8.561136 L 21.668546,11.984717 L 17.59375,15.438866 L 17.59375,14.430132 C 17.585339,13.910234 17.156503,13.490761 16.625,13.482534 L 10.59375,13.482534 L 10.59375,10.4869 L 16.625,10.4869 C 17.156503,10.478673 17.585339,10.0592 17.59375,9.539302 L 17.59375,8.561136 z " + id="path2256" + sodipodi:nodetypes="cccccccccc" /> + </g> +</svg>
--- a/pidgin/pixmaps/status/32/rtl/Makefile.am Fri Aug 17 02:26:42 2007 +0000 +++ b/pidgin/pixmaps/status/32/rtl/Makefile.am Mon Aug 27 21:59:11 2007 +0000 @@ -1,4 +1,4 @@ -EXTRA_DIST = extended-away.png +EXTRA_DIST = extended-away.png log-in.png log-out.png pidginstatuspixdir = $(datadir)/pixmaps/pidgin/status/32/rtl
--- a/pidgin/pixmaps/status/Makefile.am Fri Aug 17 02:26:42 2007 +0000 +++ b/pidgin/pixmaps/status/Makefile.am Mon Aug 27 21:59:11 2007 +0000 @@ -1,7 +1,8 @@ -SUBDIRS = 16 22 32 48 +SUBDIRS = 11 16 22 32 48 EXTRA_DIST = \ Makefile.mingw \ + 11/Makefile.mingw \ 16/Makefile.mingw \ 16/rtl/Makefile.mingw \ 22/Makefile.mingw \
--- a/pidgin/plugins/musicmessaging/musicmessaging.c Fri Aug 17 02:26:42 2007 +0000 +++ b/pidgin/plugins/musicmessaging/musicmessaging.c Mon Aug 27 21:59:11 2007 +0000 @@ -71,10 +71,10 @@ /* Globals */ /* List of sessions */ -GList *conversations; +static GList *conversations; /* Pointer to this plugin */ -PurplePlugin *plugin_pointer; +static PurplePlugin *plugin_pointer; /* Define types needed for DBus */ DBusGConnection *connection; @@ -350,7 +350,16 @@ static gboolean intercept_received(PurpleAccount *account, char **sender, char **message, PurpleConversation *conv, int *flags) { - MMConversation *mmconv = mmconv_from_conv(conv); + MMConversation *mmconv; + + if (conv == NULL) { + /* XXX: This is just to avoid a crash (#2726). + * We may want to create the conversation instead of returning from here + */ + return FALSE; + } + + mmconv = mmconv_from_conv(conv); purple_debug_misc("purple-musicmessaging", "Intercepted: %s\n", *message); if (strstr(*message, MUSICMESSAGING_PREFIX))
--- a/pidgin/plugins/spellchk.c Fri Aug 17 02:26:42 2007 +0000 +++ b/pidgin/plugins/spellchk.c Mon Aug 27 21:59:11 2007 +0000 @@ -667,7 +667,7 @@ return; } -static int buf_get_line(char *ibuf, char **buf, int *position, int len) +static int buf_get_line(char *ibuf, char **buf, int *position, gsize len) { int pos = *position; int spos = pos;
--- a/pidgin/plugins/win32/transparency/win2ktrans.c Fri Aug 17 02:26:42 2007 +0000 +++ b/pidgin/plugins/win32/transparency/win2ktrans.c Mon Aug 27 21:59:11 2007 +0000 @@ -396,8 +396,12 @@ && pconv->unseen_state == PIDGIN_UNSEEN_NONE && pidgin_conv_window_get_gtkconv_count(win) == 1) { GtkWidget *window = win->window; + gboolean has_focus; - set_conv_window_trans(NULL, win); + g_object_get(G_OBJECT(window), "has-toplevel-focus", &has_focus, NULL); + + if (!has_focus) + set_conv_window_trans(NULL, win); if (g_signal_handler_find(G_OBJECT(window), G_SIGNAL_MATCH_FUNC, 0, 0, NULL, G_CALLBACK(focus_conv_win_cb), NULL) == 0) {
--- a/pidgin/plugins/win32/winprefs/gtkappbar.c Fri Aug 17 02:26:42 2007 +0000 +++ b/pidgin/plugins/win32/winprefs/gtkappbar.c Mon Aug 27 21:59:11 2007 +0000 @@ -41,6 +41,8 @@ typedef HMONITOR WINAPI purple_MonitorFromWindow(HWND, DWORD); typedef BOOL WINAPI purple_GetMonitorInfo(HMONITOR, LPMONITORINFO); +static void gtk_appbar_do_dock(GtkAppBar *ab, UINT side); + /* Retrieve the rectangular display area from the specified monitor * Return TRUE if successful, otherwise FALSE */ @@ -154,9 +156,8 @@ #endif /** Set the window style to be the "Tool Window" style - small header, no min/max buttons */ static void set_toolbar(HWND hwnd, gboolean val) { - LONG style=0; + LONG style = GetWindowLong(hwnd, GWL_EXSTYLE); - style = GetWindowLong(hwnd, GWL_EXSTYLE); if(val && !(style & WS_EX_TOOLWINDOW)) style |= WS_EX_TOOLWINDOW; else if(!val && style & WS_EX_TOOLWINDOW) @@ -199,6 +200,7 @@ ab->registered = FALSE; ab->docked = FALSE; + ab->undocking = FALSE; ab->docking = FALSE; return TRUE; @@ -264,7 +266,7 @@ } /** Let any callbacks know that we have docked or undocked */ static void gtk_appbar_dispatch_dock_cbs(GtkAppBar *ab, gboolean val) { - GList *lst = ab->dock_cbs; + GSList *lst = ab->dock_cbs; while(lst) { GtkAppBarDockCB dock_cb = lst->data; @@ -311,15 +313,10 @@ } else if(side < 0) { gtk_appbar_unregister(ab, msg->hwnd); + ab->undocking = TRUE; rc->bottom = rc->top + ab->undocked_height; } - /* Switch to toolbar/regular caption*/ - if(ab->docking) - set_toolbar(msg->hwnd, TRUE); - else if(!ab->docked) - set_toolbar(msg->hwnd, FALSE); - return GDK_FILTER_CONTINUE; } @@ -393,14 +390,19 @@ purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "wnd_exitsizemove\n"); if(ab->docking) { - gtk_appbar_setpos(ab, msg->hwnd); - ab->docking = FALSE; - ab->docked = TRUE; - gtk_appbar_dispatch_dock_cbs(ab, TRUE); - } - else if(!ab->docked) { - gtk_appbar_unregister(ab, msg->hwnd); - gtk_appbar_dispatch_dock_cbs(ab, FALSE); + gtk_appbar_setpos(ab, msg->hwnd); + ab->docking = FALSE; + ab->docked = TRUE; + ShowWindow(msg->hwnd, SW_HIDE); + set_toolbar(msg->hwnd, TRUE); + ShowWindow(msg->hwnd, SW_SHOW); + gtk_appbar_dispatch_dock_cbs(ab, TRUE); + } else if(ab->undocking) { + ShowWindow(msg->hwnd, SW_HIDE); + set_toolbar(msg->hwnd, FALSE); + ShowWindow(msg->hwnd, SW_SHOW); + gtk_appbar_dispatch_dock_cbs(ab, FALSE); + ab->undocking = FALSE; } return GDK_FILTER_CONTINUE; @@ -414,12 +416,11 @@ ab->iconized = FALSE; purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "shown\n"); ab->docked = FALSE; - gtk_appbar_dock(ab, ab->side); + gtk_appbar_do_dock(ab, ab->side); } else if(!msg->wParam && ab->docked) { purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "hidden\n"); gtk_appbar_unregister(ab, GDK_WINDOW_HWND(ab->win->window)); - set_toolbar(GDK_WINDOW_HWND(ab->win->window), FALSE); ab->docked = TRUE; ab->iconized = TRUE; } @@ -441,7 +442,7 @@ else if(msg->wParam == SIZE_RESTORED) { purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "Restore\n"); if (!ab->iconized && ab->docked) { - gtk_appbar_dock(ab, ab->side); + gtk_appbar_do_dock(ab, ab->side); } } return GDK_FILTER_CONTINUE; @@ -572,10 +573,10 @@ return GDK_FILTER_CONTINUE; } -void gtk_appbar_dock(GtkAppBar *ab, UINT side) { +static void gtk_appbar_do_dock(GtkAppBar *ab, UINT side) { RECT orig, windowRect; - purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "gtk_appbar_dock\n"); + purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "gtk_appbar_do_dock\n"); if(!ab || !IsWindow(GDK_WINDOW_HWND(ab->win->window))) return; @@ -592,14 +593,32 @@ ab->docked_rect.right - ab->docked_rect.left, ab->docked_rect.bottom - ab->docked_rect.top, TRUE); gtk_appbar_setpos(ab, GDK_WINDOW_HWND(ab->win->window)); - set_toolbar(GDK_WINDOW_HWND(ab->win->window), TRUE); ab->docked = TRUE; } +void gtk_appbar_dock(GtkAppBar *ab, UINT side) { + HWND hwnd; + + g_return_if_fail(ab != NULL); + + hwnd = GDK_WINDOW_HWND(ab->win->window); + + g_return_if_fail(IsWindow(hwnd)); + + ab->iconized = IsIconic(hwnd); + + if (!ab->docked && !ab->iconized) + ShowWindow(hwnd, SW_HIDE); + gtk_appbar_do_dock(ab, side); + set_toolbar(hwnd, TRUE); + if (!ab->iconized) + ShowWindow(hwnd, SW_SHOW); +} + void gtk_appbar_add_dock_cb(GtkAppBar *ab, GtkAppBarDockCB dock_cb) { if(!ab) return; - ab->dock_cbs = g_list_append(ab->dock_cbs, dock_cb); + ab->dock_cbs = g_slist_prepend(ab->dock_cbs, dock_cb); } GtkAppBar *gtk_appbar_add(GtkWidget *win) { @@ -623,10 +642,13 @@ } void gtk_appbar_remove(GtkAppBar *ab) { + HWND hwnd; purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "gtk_appbar_remove\n"); if(!ab) return; + + hwnd = GDK_WINDOW_HWND(ab->win->window); gdk_window_remove_filter(ab->win->window, gtk_appbar_event_filter, ab); @@ -634,9 +656,16 @@ gtk_window_resize(GTK_WINDOW(ab->win), ab->docked_rect.right - ab->docked_rect.left, ab->undocked_height); - set_toolbar(GDK_WINDOW_HWND(ab->win->window), FALSE); + if (!ab->iconized) + ShowWindow(hwnd, SW_HIDE); + set_toolbar(hwnd, FALSE); + if (!ab->iconized) + ShowWindow(hwnd, SW_SHOW); } - gtk_appbar_unregister(ab, GDK_WINDOW_HWND(ab->win->window)); + gtk_appbar_unregister(ab, hwnd); - g_free(ab); + while (ab->dock_cbs) + ab->dock_cbs = g_slist_remove(ab->dock_cbs, ab->dock_cbs->data); + + g_free(ab); }
--- a/pidgin/plugins/win32/winprefs/gtkappbar.h Fri Aug 17 02:26:42 2007 +0000 +++ b/pidgin/plugins/win32/winprefs/gtkappbar.h Mon Aug 27 21:59:11 2007 +0000 @@ -25,22 +25,26 @@ #ifndef _GTKAPPBAR_H_ #define _GTKAPPBAR_H_ +#include <glib.h> +#include <gtk/gtk.h> + typedef struct { - GtkWidget *win; + GtkWidget *win; /** The rectangle of the screen area used for docking */ - RECT docked_rect; + RECT docked_rect; /** The height of the window prior to docking */ - UINT undocked_height; + UINT undocked_height;