# HG changeset patch # User Mark Doliner # Date 1304915206 0 # Node ID 0d4702446530b6d4af70d103e56de081f94de5a4 # Parent ea4bb5fe1fdcbdcafd8b35e2fbd7298fea4b4339# Parent dd83aa0bc5c0ca7887a0eca9fe681bff0ef1cb97 propagate from branch 'im.pidgin.pidgin' (head d6053150b258c5c8b2ac60e091a7d0d1b2d9be1d) to branch 'im.pidgin.pidgin.next.major' (head 5a8d4b649d9f0206f65aff9c3c657bf0271cb36c) diff -r ea4bb5fe1fdc -r 0d4702446530 AUTHORS --- a/AUTHORS Thu May 05 03:40:29 2011 +0000 +++ b/AUTHORS Mon May 09 04:26:46 2011 +0000 @@ -138,4 +138,4 @@ Thanks to Jeroen van der Vegt for the initial smiley plugin and images. The OpenQ Team - Wrote the QQ plugin (see AUTHORS in the qq directory) + Wrote the QQ plugin dropped in 2.8.0 (see libpurple/qq/AUTHORS in 2.7.11) diff -r ea4bb5fe1fdc -r 0d4702446530 COPYRIGHT --- a/COPYRIGHT Thu May 05 03:40:29 2011 +0000 +++ b/COPYRIGHT Mon May 09 04:26:46 2011 +0000 @@ -48,6 +48,7 @@ Stefan Becker Carlos Bederian Dave Bell +Matthew W.S. Bell Igor Belyi David Benjamin Brian Bernas @@ -156,6 +157,7 @@ Ignacio J. Elia Brian Enigma Mattias Eriksson +Pat Erley Stefan Esser Steffen Eschenbacher Marc Etcheverry diff -r ea4bb5fe1fdc -r 0d4702446530 ChangeLog --- a/ChangeLog Thu May 05 03:40:29 2011 +0000 +++ b/ChangeLog Mon May 09 04:26:46 2011 +0000 @@ -6,34 +6,42 @@ version 2.8.0 (??/??/????): General: - * Implement simple silence suppression for voice calls, preventing wasted - bandwidth for silent periods during a call. (Jakub Adam) (half of #13180) + * Implement simple silence suppression for voice calls, preventing + wasted bandwidth for silent periods during a call. (Jakub Adam) + (half of #13180) * Added the DigiCert High Assurance CA-3 intermediate CA, needed for validation of the Facebook XMPP interface's certificate. + * Removed the QQ protocol plugin. It hasn't worked in a long time and + isn't being maintained, therefore we no longer want it. Pidgin: * Duplicate code cleanup. (Gabriel Schulhof) (#10599) - * Voice/Video call window adapts correctly to adding or removing streams - on the fly. (Jakub Adam) (half of #13535) - * Don't cancel an ongoing call when rejecting the addition of a stream to - the existing call. (Jakub Adam) (#13537) + * Voice/Video call window adapts correctly to adding or removing + streams on the fly. (Jakub Adam) (half of #13535) + * Don't cancel an ongoing call when rejecting the addition of a + stream to the existing call. (Jakub Adam) (#13537) * Pidgin plugins can now override tab completion and detect clicks on usernames in the chat userlist. (kawaii.neko) (#12599) libpurple: * media: Allow obtaining active local and remote candidates. (Jakub Adam) (#11830) - * media: Allow getting/setting video capabilities. (Jakub Adam) (half of - #13095) - * Simple Silence Suppression is optional per-account. (Jakub Adam) (half - of #13180) + * media: Allow getting/setting video capabilities. (Jakub Adam) (half + of #13095) + * Simple Silence Suppression is optional per-account. (Jakub Adam) + (half of #13180) * Fix purple-url-handler being unable to find an account. - * media: Allow adding/removing streams on the fly. (Jakub Adam) (half of - #13535) + * media: Allow adding/removing streams on the fly. (Jakub Adam) + (half of #13535) * Support new connection states in NetworkManager 0.9. (Dan Williams) (#13505) * When removing a buddy, delete the pounces associated with it. (Kartik Mohta) (#1131) + * media: Allow libpurple and plugins to set SDES properties for RTP + conferences. (Jakub Adam) (#12981) + * proxy: Add new "Tor/Privacy" proxy type that can be used to + restrict operations that could leak potentially sensitive data + (e.g. DNS queries). (#11110, #13928) Gadu-Gadu: * Allow showing your status only to buddies. (Mateusz Piękos) (#13358) @@ -46,8 +54,8 @@ * Support typing notifications. (Jan Zachorowski, Tomasz Wasilczyk, Krzysztof Klinikowski) (#13362, #13590) * Require libgadu 1.10.1 to avoid using internal libgadu. - * SSL connection support for GNUTLS users (not on Windows yet!). - (Tomasz Wasilczyk) (#13613) + * Optional SSL connection support for GNUTLS users (not on Windows + yet!). (Tomasz Wasilczyk) (#13613, #13894) * Don't count received messages or statuses when determining whether to send a keepalive packet. (Jan Zachorowski) (#13699) * Fix a crash when receiving images on Windows or an incorrect @@ -55,31 +63,50 @@ Wasilczyk) (#10268) * Support XML events, resulting in immediate update of other users' buddy icons. (Tomasz Wasilczyk) (#13739) + * Accept poorly formatted URLs from other third-party clients in + the same manner as the official client. (Tomasz Wasilczyk) + (#13886) ICQ: * Fix unsetting your mood when "None" is selected. (Dustin Gathmann) (#11895) * Ignore Daylight Saving Time when performing calculations related to birthdays. (Dustin Gathmann) (#13533) - * It is now possible to specify multiple encodings on the Advanced tab of - an ICQ account's settings by using a comma-delimited list. (Dmitry - Utkin (#13496) + * It is now possible to specify multiple encodings on the Advanced + tab of an ICQ account's settings by using a comma-delimited list. + (Dmitry Utkin (#13496) IRC: * Add "authserv" service command. (tomos) (#13337) + MXit: + * Support for an Invite Message when adding a buddy. + * Fixed bug in splitting-up of messages that contain a lot of links. + * Fixed crash caused by timer not being disabled on disconnect. + (introduced in 2.7.11) + * Clearing of the conversation window now works. + * When receiving an invite you can display the sender's profile + information, avatar image, invite message. + * The Change PIN option was moved into separate action. + * New profile attributes added and shown. + * Update to protocol v6.3. + XMPP: * Remember the previously entered user directory when searching. (Keith Moyer) (#12451) + * Correctly handle a buddy's unsetting his/her vCard-based avatar. + (Matthew W.S. Bell) (#13370) Plugins: * The Voice/Video Settings plugin now includes the ability to test microphone settings. (Jakub Adam) (#13182) + * Fix a crash when handling some saved settings in the Voice/Video + Settings plugin. (Pat Erley) (13290, #13774) Windows-Specific Changes: - * Fix building libpurple with Visual C++ .NET 2005. This was accidentally - broken in 2.7.11. (Florian Quèze) - * Build internal libgadu without -mms-bitfields, fixing several + * Fix building libpurple with Visual C++ .NET 2005. This was + accidentally broken in 2.7.11. (Florian Quèze) + * Build internal libgadu using packed structs, fixing several long-standing Gadu-Gadu issues. (#11958, #6297) version 2.7.11 (03/10/2011): diff -r ea4bb5fe1fdc -r 0d4702446530 ChangeLog.API --- a/ChangeLog.API Thu May 05 03:40:29 2011 +0000 +++ b/ChangeLog.API Mon May 09 04:26:46 2011 +0000 @@ -19,12 +19,16 @@ * cleared-message-history signal (conversation signals) * purple_account_add_buddy_with_invite * purple_account_add_buddies_with_invite + * purple_dnsquery_a_account * purple_notify_user_info_add_pair_plaintext * purple_media_get_active_local_candidates * purple_media_get_active_remote_candidates * purple_media_manager_get_video_caps (Jakub Adam) (#13095) * purple_media_manager_set_video_caps (Jakub Adam) (#13095) * purple_pounce_destroy_all_by_buddy (Kartik Mohta) (#1131) + * purple_proxy_connect_socks5_account + * purple_srv_resolve_account + * purple_txt_resolve_account * Added add_buddy_with_invite to PurplePluginProtocolInfo * Added add_buddies_with_invite to PurplePluginProtocolInfo * Added PurpleSrvTxtQueryUiOps which allow UIs to specify their @@ -35,6 +39,10 @@ Deprecated: * purple_account_add_buddy * purple_account_add_buddies_with_invite + * purple_dnsquery_a + * purple_proxy_connect_socks5 + * purple_srv_resolve + * purple_txt_resolve * add_buddy from PurplePluginProtocolInfo struct * add_buddies from PurplePluginProtocolInfo struct diff -r ea4bb5fe1fdc -r 0d4702446530 configure.ac --- a/configure.ac Thu May 05 03:40:29 2011 +0000 +++ b/configure.ac Mon May 09 04:26:46 2011 +0000 @@ -1058,7 +1058,7 @@ ]])], [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ #if GG_DEFAULT_PROTOCOL_VERSION < 0x2e -#error "Your libgadu version is too old. libpurple requires 1.9.0-rc2 or higher." +#error "Your libgadu version is too old. libpurple requires 1.10.1 or higher." #endif ]])], [ AC_MSG_RESULT(yes) @@ -1069,7 +1069,7 @@ echo echo echo "Your supplied copy of libgadu is too old." - echo "Install version 1.9.0-rc2 or newer." + echo "Install version 1.10.1 or newer." echo "Then rerun this ./configure" echo echo "Falling back to using our own copy of libgadu" @@ -1114,7 +1114,7 @@ fi if test "x$STATIC_PRPLS" = "xall" ; then - STATIC_PRPLS="bonjour gg irc jabber msn myspace mxit novell oscar qq sametime silc simple yahoo zephyr" + STATIC_PRPLS="bonjour gg irc jabber msn myspace mxit novell oscar sametime silc simple yahoo zephyr" fi if test "x$have_meanwhile" != "xyes" ; then STATIC_PRPLS=`echo $STATIC_PRPLS | $sedpath 's/sametime//'` @@ -1170,7 +1170,6 @@ oscar) static_oscar=yes ;; aim) static_oscar=yes ;; icq) static_oscar=yes ;; - qq) static_qq=yes ;; sametime) static_sametime=yes ;; silc) static_silc=yes ;; silc10) static_silc=yes ;; @@ -1189,7 +1188,6 @@ AM_CONDITIONAL(STATIC_MXIT, test "x$static_mxit" = "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") AM_CONDITIONAL(STATIC_SAMETIME, test "x$static_sametime" = "xyes" -a "x$have_meanwhile" = "xyes") AM_CONDITIONAL(STATIC_SILC, test "x$static_silc" = "xyes" -a "x$have_silc" = "xyes") AM_CONDITIONAL(STATIC_SIMPLE, test "x$static_simple" = "xyes") @@ -1201,7 +1199,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 myspace mxit novell oscar qq sametime silc simple yahoo zephyr" + DYNAMIC_PRPLS="bonjour gg irc jabber msn myspace mxit novell oscar sametime silc simple yahoo zephyr" fi if test "x$have_meanwhile" != "xyes"; then DYNAMIC_PRPLS=`echo $DYNAMIC_PRPLS | $sedpath 's/sametime//'` @@ -1230,7 +1228,6 @@ oscar) dynamic_oscar=yes ;; aim) dynamic_oscar=yes ;; icq) dynamic_oscar=yes ;; - qq) dynamic_qq=yes ;; sametime) dynamic_sametime=yes ;; silc) dynamic_silc=yes ;; silc10) dynamic_silc=yes ;; @@ -2576,7 +2573,6 @@ libpurple/protocols/novell/Makefile libpurple/protocols/null/Makefile libpurple/protocols/oscar/Makefile - libpurple/protocols/qq/Makefile libpurple/protocols/sametime/Makefile libpurple/protocols/silc/Makefile libpurple/protocols/silc10/Makefile diff -r ea4bb5fe1fdc -r 0d4702446530 finch/gntconv.c --- a/finch/gntconv.c Thu May 05 03:40:29 2011 +0000 +++ b/finch/gntconv.c Mon May 09 04:26:46 2011 +0000 @@ -1458,6 +1458,14 @@ " <foreground/background>: black, red, green, blue, white, gray, darkgray, magenta, cyan, default

" "EXAMPLE:
msgcolor send cyan default"), NULL); + purple_cmd_register("msgcolour", "www", PURPLE_CMD_P_DEFAULT, + PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_IM, NULL, + cmd_message_color, _("msgcolor <class> <foreground> <background>: " + "Set the color for different classes of messages in the conversation window.
" + " <class>: receive, send, highlight, action, timestamp
" + " <foreground/background>: black, red, green, blue, white, gray, darkgray, magenta, cyan, default

" + "EXAMPLE:
msgcolor send cyan default"), + NULL); purple_signal_connect(purple_conversations_get_handle(), "buddy-typing", finch_conv_get_handle(), PURPLE_CALLBACK(update_buddy_typing), NULL); diff -r ea4bb5fe1fdc -r 0d4702446530 finch/gntnotify.c --- a/finch/gntnotify.c Thu May 05 03:40:29 2011 +0000 +++ b/finch/gntnotify.c Mon May 09 04:26:46 2011 +0000 @@ -84,6 +84,10 @@ if (secondary) { GntWidget *msg; + /* XXX: This is broken. type is PurpleNotifyMsgType, not + * PurpleNotifyType. Also, the if() followed by the + * inner switch doesn't make much sense. + */ if (type == PURPLE_NOTIFY_FORMATTED) { int width = -1, height = -1; char *plain = (char*)secondary; diff -r ea4bb5fe1fdc -r 0d4702446530 finch/libgnt/gntcolors.c --- a/finch/libgnt/gntcolors.c Thu May 05 03:40:29 2011 +0000 +++ b/finch/libgnt/gntcolors.c Mon May 09 04:26:46 2011 +0000 @@ -161,9 +161,9 @@ color = custom ? GNT_COLOR_BLUE : COLOR_BLUE; else if (strcmp(key, "white") == 0) color = custom ? GNT_COLOR_WHITE : COLOR_WHITE; - else if (strcmp(key, "gray") == 0) + else if (strcmp(key, "gray") == 0 || strcmp(key, "grey") == 0) color = custom ? GNT_COLOR_GRAY : COLOR_YELLOW; /* eh? */ - else if (strcmp(key, "darkgray") == 0) + else if (strcmp(key, "darkgray") == 0 || strcmp(key, "darkgrey") == 0) color = custom ? GNT_COLOR_DARK_GRAY : COLOR_BLACK; else if (strcmp(key, "magenta") == 0) color = COLOR_MAGENTA; diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/account.c --- a/libpurple/account.c Thu May 05 03:40:29 2011 +0000 +++ b/libpurple/account.c Mon May 09 04:26:46 2011 +0000 @@ -294,6 +294,7 @@ proxy_type == PURPLE_PROXY_HTTP ? "http" : proxy_type == PURPLE_PROXY_SOCKS4 ? "socks4" : proxy_type == PURPLE_PROXY_SOCKS5 ? "socks5" : + proxy_type == PURPLE_PROXY_TOR ? "tor" : proxy_type == PURPLE_PROXY_USE_ENVVAR ? "envvar" : "unknown"), -1); if ((value = purple_proxy_info_get_host(proxy_info)) != NULL) @@ -746,6 +747,8 @@ purple_proxy_info_set_type(proxy_info, PURPLE_PROXY_SOCKS4); else if (purple_strequal(data, "socks5")) purple_proxy_info_set_type(proxy_info, PURPLE_PROXY_SOCKS5); + else if (purple_strequal(data, "tor")) + purple_proxy_info_set_type(proxy_info, PURPLE_PROXY_TOR); else if (purple_strequal(data, "envvar")) purple_proxy_info_set_type(proxy_info, PURPLE_PROXY_USE_ENVVAR); else diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/dnsquery.c --- a/libpurple/dnsquery.c Thu May 05 03:40:29 2011 +0000 +++ b/libpurple/dnsquery.c Mon May 09 04:26:46 2011 +0000 @@ -24,6 +24,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA * */ +#define _PURPLE_DNSQUERY_C_ #include "internal.h" #include "debug.h" @@ -54,6 +55,7 @@ PurpleDnsQueryConnectFunction callback; gpointer data; guint timeout; + PurpleAccount *account; #if defined(PURPLE_DNSQUERY_USE_FORK) PurpleDnsQueryResolverProcess *resolver; @@ -153,6 +155,7 @@ resolve_ip(PurpleDnsQueryData *query_data) { struct sockaddr_in sin; + /* TODO: Use inet_pton for IPv6 support */ if (inet_aton(query_data->hostname, &sin.sin_addr)) { /* @@ -341,20 +344,17 @@ } freeaddrinfo(tmp); #else - if (!inet_aton(hostname, &sin.sin_addr)) { - struct hostent *hp; - if (!(hp = gethostbyname(hostname))) { - write_to_parent(child_out, &h_errno, sizeof(int)); - close(child_out); - if (show_debug) - printf("DNS Error: %d\n", h_errno); - _exit(0); - } - memset(&sin, 0, sizeof(struct sockaddr_in)); - memcpy(&sin.sin_addr.s_addr, hp->h_addr, hp->h_length); - sin.sin_family = hp->h_addrtype; - } else - sin.sin_family = AF_INET; + struct hostent *hp; + if (!(hp = gethostbyname(hostname))) { + write_to_parent(child_out, &h_errno, sizeof(int)); + close(child_out); + if (show_debug) + printf("DNS Error: %d\n", h_errno); + _exit(0); + } + memset(&sin, 0, sizeof(struct sockaddr_in)); + memcpy(&sin.sin_addr.s_addr, hp->h_addr, hp->h_length); + sin.sin_family = hp->h_addrtype; sin.sin_port = htons(dns_params.port); rc = 0; @@ -669,62 +669,12 @@ handle_next_queued_request(); } -static gboolean -resolve_host(gpointer data) +static void +resolve_host(PurpleDnsQueryData *query_data) { - PurpleDnsQueryData *query_data; - - query_data = data; - query_data->timeout = 0; - - if (resolve_ip(query_data)) - { - /* resolve_ip calls purple_dnsquery_resolved */ - return FALSE; - } - - if (purple_dnsquery_ui_resolve(query_data)) - { - /* The UI is handling the resolve; we're done */ - return FALSE; - } - queued_requests = g_slist_append(queued_requests, query_data); handle_next_queued_request(); - - return FALSE; -} - -PurpleDnsQueryData * -purple_dnsquery_a(const char *hostname, int port, - PurpleDnsQueryConnectFunction callback, gpointer data) -{ - PurpleDnsQueryData *query_data; - - g_return_val_if_fail(hostname != NULL, NULL); - g_return_val_if_fail(port != 0, NULL); - g_return_val_if_fail(callback != NULL, NULL); - - query_data = g_new(PurpleDnsQueryData, 1); - query_data->hostname = g_strdup(hostname); - g_strstrip(query_data->hostname); - query_data->port = port; - query_data->callback = callback; - query_data->data = data; - query_data->resolver = NULL; - - if (*query_data->hostname == '\0') - { - purple_dnsquery_destroy(query_data); - g_return_val_if_reached(NULL); - } - - purple_debug_info("dns", "DNS query for '%s' queued\n", query_data->hostname); - - query_data->timeout = purple_timeout_add(0, resolve_host, query_data); - - return query_data; } #elif defined _WIN32 /* end PURPLE_DNSQUERY_USE_FORK */ @@ -837,50 +787,116 @@ return 0; } +static void +resolve_host(PurpleDnsQueryData *query_data) +{ + GError *err = NULL; + + /* + * Spin off a separate thread to perform the DNS lookup so + * that we don't block the UI. + */ + query_data->resolver = g_thread_create(dns_thread, + query_data, FALSE, &err); + if (query_data->resolver == NULL) + { + char message[1024]; + g_snprintf(message, sizeof(message), _("Thread creation failure: %s"), + (err && err->message) ? err->message : _("Unknown reason")); + g_error_free(err); + purple_dnsquery_failed(query_data, message); + } +} + +#else /* not PURPLE_DNSQUERY_USE_FORK or _WIN32 */ + +/* + * We weren't able to do anything fancier above, so use the + * fail-safe name resolution code, which is blocking. + */ + +static void +resolve_host(PurpleDnsQueryData *query_data) +{ + struct sockaddr_in sin; + GSList *hosts = NULL; + struct hostent *hp; + gchar *hostname; +#ifdef USE_IDN + if (!dns_str_is_ascii(query_data->hostname)) { + int ret = purple_network_convert_idn_to_ascii(query_data->hostname, + &hostname); + if (ret != 0) { + char message[1024]; + g_snprintf(message, sizeof(message), _("Error resolving %s: %d"), + query_data->hostname, ret); + purple_dnsquery_failed(query_data, message); + return; + } + } else /* fallthrough is intentional to the g_strdup */ +#endif + hostname = g_strdup(query_data->hostname); + + if(!(hp = gethostbyname(hostname))) { + char message[1024]; + g_snprintf(message, sizeof(message), _("Error resolving %s: %d"), + query_data->hostname, h_errno); + purple_dnsquery_failed(query_data, message); + g_free(hostname); + return; + } + memset(&sin, 0, sizeof(struct sockaddr_in)); + memcpy(&sin.sin_addr.s_addr, hp->h_addr, hp->h_length); + sin.sin_family = hp->h_addrtype; + g_free(hostname); + sin.sin_port = htons(query_data->port); + + hosts = g_slist_append(hosts, GINT_TO_POINTER(sizeof(sin))); + hosts = g_slist_append(hosts, g_memdup(&sin, sizeof(sin))); + + purple_dnsquery_resolved(query_data, hosts); +} + +#endif /* not PURPLE_DNSQUERY_USE_FORK or _WIN32 */ + static gboolean -resolve_host(gpointer data) +initiate_resolving(gpointer data) { PurpleDnsQueryData *query_data; - GError *err = NULL; + PurpleProxyType proxy_type; query_data = data; query_data->timeout = 0; - if (purple_dnsquery_ui_resolve(query_data)) - { - /* The UI is handling the resolve; we're done */ + if (resolve_ip(query_data)) + /* resolve_ip calls purple_dnsquery_resolved */ + return FALSE; + + proxy_type = purple_proxy_info_get_type( + purple_proxy_get_setup(query_data->account)); + if (proxy_type == PURPLE_PROXY_TOR) { + purple_dnsquery_failed(query_data, + _("Aborting DNS lookup in Tor Proxy mode.")); return FALSE; } - if (!resolve_ip(query_data)) - { - /* - * Spin off a separate thread to perform the DNS lookup so - * that we don't block the UI. - */ - query_data->resolver = g_thread_create(dns_thread, - query_data, FALSE, &err); - if (query_data->resolver == NULL) - { - char message[1024]; - g_snprintf(message, sizeof(message), _("Thread creation failure: %s"), - (err && err->message) ? err->message : _("Unknown reason")); - g_error_free(err); - purple_dnsquery_failed(query_data, message); - } - } + if (purple_dnsquery_ui_resolve(query_data)) + /* The UI is handling the resolve; we're done */ + return FALSE; + + resolve_host(query_data); return FALSE; } PurpleDnsQueryData * -purple_dnsquery_a(const char *hostname, int port, +purple_dnsquery_a_account(PurpleAccount *account, const char *hostname, int port, PurpleDnsQueryConnectFunction callback, gpointer data) { PurpleDnsQueryData *query_data; g_return_val_if_fail(hostname != NULL, NULL); - g_return_val_if_fail(port != 0, NULL); + g_return_val_if_fail(port != 0, NULL); g_return_val_if_fail(callback != NULL, NULL); purple_debug_info("dnsquery", "Performing DNS lookup for %s\n", hostname); @@ -891,115 +907,26 @@ query_data->port = port; query_data->callback = callback; query_data->data = data; + query_data->account = account; - if (strlen(query_data->hostname) == 0) + if (*query_data->hostname == '\0') { purple_dnsquery_destroy(query_data); g_return_val_if_reached(NULL); } - /* Don't call the callback before returning */ - query_data->timeout = purple_timeout_add(0, resolve_host, query_data); + query_data->timeout = purple_timeout_add(0, initiate_resolving, query_data); return query_data; } -#else /* not PURPLE_DNSQUERY_USE_FORK or _WIN32 */ - -/* - * We weren't able to do anything fancier above, so use the - * fail-safe name resolution code, which is blocking. - */ - -static gboolean -resolve_host(gpointer data) -{ - PurpleDnsQueryData *query_data; - struct sockaddr_in sin; - GSList *hosts = NULL; - - query_data = data; - query_data->timeout = 0; - - if (purple_dnsquery_ui_resolve(query_data)) - { - /* The UI is handling the resolve; we're done */ - return FALSE; - } - - if (!inet_aton(query_data->hostname, &sin.sin_addr)) { - struct hostent *hp; - gchar *hostname; -#ifdef USE_IDN - if (!dns_str_is_ascii(query_data->hostname)) { - int ret = purple_network_convert_idn_to_ascii(query_data->hostname, - &hostname); - if (ret != 0) { - char message[1024]; - g_snprintf(message, sizeof(message), _("Error resolving %s: %d"), - query_data->hostname, ret); - purple_dnsquery_failed(query_data, message); - return FALSE; - } - } else /* fallthrough is intentional to the g_strdup */ -#endif - hostname = g_strdup(query_data->hostname); - - if(!(hp = gethostbyname(hostname))) { - char message[1024]; - g_snprintf(message, sizeof(message), _("Error resolving %s: %d"), - query_data->hostname, h_errno); - purple_dnsquery_failed(query_data, message); - g_free(hostname); - return FALSE; - } - memset(&sin, 0, sizeof(struct sockaddr_in)); - memcpy(&sin.sin_addr.s_addr, hp->h_addr, hp->h_length); - sin.sin_family = hp->h_addrtype; - g_free(hostname); - } else - sin.sin_family = AF_INET; - sin.sin_port = htons(query_data->port); - - hosts = g_slist_append(hosts, GINT_TO_POINTER(sizeof(sin))); - hosts = g_slist_append(hosts, g_memdup(&sin, sizeof(sin))); - - purple_dnsquery_resolved(query_data, hosts); - - return FALSE; -} - PurpleDnsQueryData * purple_dnsquery_a(const char *hostname, int port, PurpleDnsQueryConnectFunction callback, gpointer data) { - PurpleDnsQueryData *query_data; - - g_return_val_if_fail(hostname != NULL, NULL); - g_return_val_if_fail(port != 0, NULL); - g_return_val_if_fail(callback != NULL, NULL); - - query_data = g_new(PurpleDnsQueryData, 1); - query_data->hostname = g_strdup(hostname); - g_strstrip(query_data->hostname); - query_data->port = port; - query_data->callback = callback; - query_data->data = data; - - if (strlen(query_data->hostname) == 0) - { - purple_dnsquery_destroy(query_data); - g_return_val_if_reached(NULL); - } - - /* Don't call the callback before returning */ - query_data->timeout = purple_timeout_add(0, resolve_host, query_data); - - return query_data; + return purple_dnsquery_a_account(NULL, hostname, port, callback, data); } -#endif /* not PURPLE_DNSQUERY_USE_FORK or _WIN32 */ - void purple_dnsquery_destroy(PurpleDnsQueryData *query_data) { diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/dnsquery.h --- a/libpurple/dnsquery.h Thu May 05 03:40:29 2011 +0000 +++ b/libpurple/dnsquery.h Mon May 09 04:26:46 2011 +0000 @@ -88,6 +88,7 @@ /** * Perform an asynchronous DNS query. * + * @param account the account that the query is being done for (or NULL) * @param hostname The hostname to resolve. * @param port A port number which is stored in the struct sockaddr. * @param callback The callback function to call after resolving. @@ -96,8 +97,28 @@ * @return NULL if there was an error, otherwise return a reference to * a data structure that can be used to cancel the pending * DNS query, if needed. + * + * @since 2.8.0 + */ +PurpleDnsQueryData *purple_dnsquery_a_account(PurpleAccount *account, const char *hostname, int port, PurpleDnsQueryConnectFunction callback, gpointer data); + +#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_DNSQUERY_C_) +/** + * Perform an asynchronous DNS query. + * + * @param hostname The hostname to resolve. + * @param port A port number which is stored in the struct sockaddr. + * @param callback The callback function to call after resolving. + * @param data Extra data to pass to the callback function. + * + * @return NULL if there was an error, otherwise return a reference to + * a data structure that can be used to cancel the pending + * DNS query, if needed. + * + * @deprecated Use purple_dnsquery_a_account instead */ PurpleDnsQueryData *purple_dnsquery_a(const char *hostname, int port, PurpleDnsQueryConnectFunction callback, gpointer data); +#endif /** * Cancel a DNS query and destroy the associated data structure. diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/dnssrv.c --- a/libpurple/dnssrv.c Thu May 05 03:40:29 2011 +0000 +++ b/libpurple/dnssrv.c Mon May 09 04:26:46 2011 +0000 @@ -20,6 +20,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ +#define _PURPLE_DNSSRV_C_ #include "internal.h" #include "util.h" @@ -30,12 +31,6 @@ #ifdef HAVE_ARPA_NAMESER_COMPAT_H #include #endif -#ifndef T_SRV -#define T_SRV PurpleDnsTypeSrv -#endif -#ifndef T_TXT -#define T_TXT PurpleDnsTypeTxt -#endif #else /* WIN32 */ #include /* Missing from the mingw headers */ @@ -47,6 +42,13 @@ #endif #endif +#ifndef T_SRV +#define T_SRV PurpleDnsTypeSrv +#endif +#ifndef T_TXT +#define T_TXT PurpleDnsTypeTxt +#endif + #include "debug.h" #include "dnssrv.h" #include "eventloop.h" @@ -673,11 +675,22 @@ #endif PurpleSrvTxtQueryData * -purple_srv_resolve(const char *protocol, const char *transport, const char *domain, PurpleSrvCallback cb, gpointer extradata) +purple_srv_resolve(const char *protocol, const char *transport, + const char *domain, PurpleSrvCallback cb, gpointer extradata) +{ + return purple_srv_resolve_account(NULL, protocol, transport, domain, + cb, extradata); +} + +PurpleSrvTxtQueryData * +purple_srv_resolve_account(PurpleAccount *account, const char *protocol, + const char *transport, const char *domain, PurpleSrvCallback cb, + gpointer extradata) { char *query; char *hostname; PurpleSrvTxtQueryData *query_data; + PurpleProxyType proxy_type; #ifndef _WIN32 PurpleSrvInternalQuery internal_query; int in[2], out[2]; @@ -693,6 +706,14 @@ g_return_val_if_reached(NULL); } + proxy_type = purple_proxy_info_get_type( + purple_proxy_get_setup(account)); + if (proxy_type == PURPLE_PROXY_TOR) { + purple_debug_info("dnssrv", "Aborting SRV lookup in Tor Proxy mode."); + cb(NULL, 0, extradata); + return NULL; + } + #ifdef USE_IDN if (!dns_str_is_ascii(domain)) { int ret = purple_network_convert_idn_to_ascii(domain, &hostname); @@ -794,11 +815,20 @@ #endif } -PurpleSrvTxtQueryData *purple_txt_resolve(const char *owner, const char *domain, PurpleTxtCallback cb, gpointer extradata) +PurpleSrvTxtQueryData *purple_txt_resolve(const char *owner, + const char *domain, PurpleTxtCallback cb, gpointer extradata) +{ + return purple_txt_resolve_account(NULL, owner, domain, cb, extradata); +} + +PurpleSrvTxtQueryData *purple_txt_resolve_account(PurpleAccount *account, + const char *owner, const char *domain, PurpleTxtCallback cb, + gpointer extradata) { char *query; char *hostname; PurpleSrvTxtQueryData *query_data; + PurpleProxyType proxy_type; #ifndef _WIN32 PurpleSrvInternalQuery internal_query; int in[2], out[2]; @@ -808,6 +838,14 @@ static gboolean initialized = FALSE; #endif + proxy_type = purple_proxy_info_get_type( + purple_proxy_get_setup(account)); + if (proxy_type == PURPLE_PROXY_TOR) { + purple_debug_info("dnssrv", "Aborting TXT lookup in Tor Proxy mode."); + cb(NULL, extradata); + return NULL; + } + #ifdef USE_IDN if (!dns_str_is_ascii(domain)) { int ret = purple_network_convert_idn_to_ascii(domain, &hostname); @@ -1042,4 +1080,4 @@ g_return_val_if_fail(query_data != NULL, 0); return query_data->type; -} \ No newline at end of file +} diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/dnssrv.h --- a/libpurple/dnssrv.h Thu May 05 03:40:29 2011 +0000 +++ b/libpurple/dnssrv.h Mon May 09 04:26:46 2011 +0000 @@ -99,13 +99,31 @@ /** * Queries an SRV record. * + * @param account the account that the query is being done for (or NULL) * @param protocol Name of the protocol (e.g. "sip") * @param transport Name of the transport ("tcp" or "udp") * @param domain Domain name to query (e.g. "blubb.com") * @param cb A callback which will be called with the results * @param extradata Extra data to be passed to the callback + * + * @since 2.8.0 + */ +PurpleSrvTxtQueryData *purple_srv_resolve_account(PurpleAccount *account, const char *protocol, const char *transport, const char *domain, PurpleSrvCallback cb, gpointer extradata); + +#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_DNSSRV_C_) +/** + * Queries an SRV record. + * + * @param protocol Name of the protocol (e.g. "sip") + * @param transport Name of the transport ("tcp" or "udp") + * @param domain Domain name to query (e.g. "blubb.com") + * @param cb A callback which will be called with the results + * @param extradata Extra data to be passed to the callback + * + * @deprecated Use purple_srv_resolve_account instead */ PurpleSrvTxtQueryData *purple_srv_resolve(const char *protocol, const char *transport, const char *domain, PurpleSrvCallback cb, gpointer extradata); +#endif /** * Cancel an SRV or DNS query. @@ -117,14 +135,31 @@ /** * Queries an TXT record. * + * @param account the account that the query is being done for (or NULL) * @param owner Name of the protocol (e.g. "_xmppconnect") * @param domain Domain name to query (e.g. "blubb.com") * @param cb A callback which will be called with the results * @param extradata Extra data to be passed to the callback * + * @since 2.8.0 + */ +PurpleSrvTxtQueryData *purple_txt_resolve_account(PurpleAccount *account, const char *owner, const char *domain, PurpleTxtCallback cb, gpointer extradata); + +#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_DNSSRV_C_) +/** + * Queries an TXT record. + * + * @param owner Name of the protocol (e.g. "_xmppconnect") + * @param domain Domain name to query (e.g. "blubb.com") + * @param cb A callback which will be called with the results + * @param extradata Extra data to be passed to the callback + * + * @deprecated Use purple_txt_resolve_account instead + * * @since 2.6.0 */ PurpleSrvTxtQueryData *purple_txt_resolve(const char *owner, const char *domain, PurpleTxtCallback cb, gpointer extradata); +#endif /** * Cancel an TXT DNS query. diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/ft.c --- a/libpurple/ft.c Thu May 05 03:40:29 2011 +0000 +++ b/libpurple/ft.c Mon May 09 04:26:46 2011 +0000 @@ -677,7 +677,6 @@ purple_xfer_set_local_filename(xfer, filename); purple_xfer_set_size(xfer, st.st_size); } else { - utf8 = g_strdup(filename); purple_xfer_set_local_filename(xfer, filename); } diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/media.c --- a/libpurple/media.c Thu May 05 03:40:29 2011 +0000 +++ b/libpurple/media.c Mon May 09 04:26:46 2011 +0000 @@ -916,6 +916,47 @@ #endif } +void +purple_media_set_params(PurpleMedia *media, + guint num_params, GParameter *params) +{ +#ifdef USE_VV + g_return_if_fail(PURPLE_IS_MEDIA(media)); + + purple_media_backend_set_params(media->priv->backend, num_params, params); +#endif +} + +const gchar ** +purple_media_get_available_params(PurpleMedia *media) +{ + static const gchar *NULL_ARRAY[] = { NULL }; +#ifdef USE_VV + g_return_val_if_fail(PURPLE_IS_MEDIA(media), NULL_ARRAY); + + return purple_media_backend_get_available_params(media->priv->backend); +#else + return NULL_ARRAY; +#endif +} + +gboolean +purple_media_param_is_supported(PurpleMedia *media, const gchar *param) +{ +#ifdef USE_VV + const gchar **params; + + g_return_val_if_fail(PURPLE_IS_MEDIA(media), FALSE); + g_return_val_if_fail(param != NULL, FALSE); + + params = purple_media_backend_get_available_params(media->priv->backend); + for (; *params != NULL; ++params) + if (!strcmp(*params, param)) + return TRUE; +#endif + return FALSE; +} + #ifdef USE_VV static void purple_media_new_local_candidate_cb(PurpleMediaBackend *backend, diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/media.h --- a/libpurple/media.h Thu May 05 03:40:29 2011 +0000 +++ b/libpurple/media.h Mon May 09 04:26:46 2011 +0000 @@ -144,6 +144,52 @@ gboolean local); /** + * Sets various optional parameters of the media call. + * + * Currently supported are: + * - "sdes-cname" : The CNAME for the RTP sessions + * - "sdes-name" : Real name used to describe the source in SDES messages + * - "sdes-tool" : The TOOL to put in SDES messages + * - "sdes-email" : Email address to put in SDES messages + * - "sdes-location" : The LOCATION to put in SDES messages + * - "sdes-note" : The NOTE to put in SDES messages + * - "sdes-phone" : The PHONE to put in SDES messages + * + * @param media The media object to set the parameters on. + * @param num_params The number of parameters to pass + * @param params Array of @c GParameter to pass + * + * @since 2.8.0 + */ +void purple_media_set_params(PurpleMedia *media, + guint num_params, GParameter *params); + +/** + * Gets the list of optional parameters supported by the media backend. + * + * The list is owned by the @c PurpleMedia internals and should NOT be freed. + * + * @param media The media object + * + * @return NULL-terminated array of names of supported parameters. + * + * @since 2.8.0 + */ +const gchar **purple_media_get_available_params(PurpleMedia *media); + +/** + * Checks if given optional parameter is supported by the media backend. + * + * @param media The media object + * @param param name of parameter + * + * @return @c TRUE if backend recognizes the parameter, @c FALSE otherwise. + * + * @since 2.8.0 + */ +gboolean purple_media_param_is_supported(PurpleMedia *media, const gchar *param); + +/** * Adds a stream to a session. * * It only adds a stream to one audio session or video session as diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/media/backend-fs2.c --- a/libpurple/media/backend-fs2.c Thu May 05 03:40:29 2011 +0000 +++ b/libpurple/media/backend-fs2.c Mon May 09 04:26:46 2011 +0000 @@ -85,6 +85,9 @@ static gboolean purple_media_backend_fs2_set_send_codec( PurpleMediaBackend *self, const gchar *sess_id, PurpleMediaCodec *codec); +static void purple_media_backend_fs2_set_params(PurpleMediaBackend *self, + guint num_params, GParameter *params); +static const gchar **purple_media_backend_fs2_get_available_params(void); static void free_stream(PurpleMediaBackendFs2Stream *stream); static void free_session(PurpleMediaBackendFs2Session *session); @@ -413,6 +416,8 @@ purple_media_backend_fs2_get_local_candidates; iface->set_remote_codecs = purple_media_backend_fs2_set_remote_codecs; iface->set_send_codec = purple_media_backend_fs2_set_send_codec; + iface->set_params = purple_media_backend_fs2_set_params; + iface->get_available_params = purple_media_backend_fs2_get_available_params; } static FsMediaType @@ -2126,6 +2131,49 @@ return TRUE; } + +static void +purple_media_backend_fs2_set_params(PurpleMediaBackend *self, + guint num_params, GParameter *params) +{ + PurpleMediaBackendFs2Private *priv; + const gchar **supported = purple_media_backend_fs2_get_available_params(); + const gchar **p; + guint i; + + g_return_if_fail(PURPLE_IS_MEDIA_BACKEND_FS2(self)); + + priv = PURPLE_MEDIA_BACKEND_FS2_GET_PRIVATE(self); + + if (priv->conference == NULL && + !init_conference(PURPLE_MEDIA_BACKEND_FS2(self))) { + purple_debug_error("backend-fs2", + "Error initializing the conference.\n"); + return; + } + + for (i = 0; i != num_params; ++i) { + for (p = supported; *p != NULL; ++p) { + if (!strcmp(params[i].name, *p)) { + g_object_set(priv->conference, + params[i].name, g_value_get_string(¶ms[i].value), + NULL); + break; + } + } + } +} + +static const gchar ** +purple_media_backend_fs2_get_available_params(void) +{ + static const gchar *supported_params[] = { + "sdes-cname", "sdes-email", "sdes-location", "sdes-name", "sdes-note", + "sdes-phone", "sdes-tool", NULL + }; + + return supported_params; +} #else GType purple_media_backend_fs2_get_type(void) diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/media/backend-iface.c --- a/libpurple/media/backend-iface.c Thu May 05 03:40:29 2011 +0000 +++ b/libpurple/media/backend-iface.c Mon May 09 04:26:46 2011 +0000 @@ -192,3 +192,20 @@ return PURPLE_MEDIA_BACKEND_GET_INTERFACE(self)->set_send_codec(self, sess_id, codec); } + +void +purple_media_backend_set_params(PurpleMediaBackend *self, + guint num_params, GParameter *params) +{ + g_return_if_fail(PURPLE_IS_MEDIA_BACKEND(self)); + PURPLE_MEDIA_BACKEND_GET_INTERFACE(self)->set_params(self, num_params, params); +} + +const gchar ** +purple_media_backend_get_available_params(PurpleMediaBackend *self) +{ + static const gchar *NULL_ARRAY[] = { NULL }; + + g_return_val_if_fail(PURPLE_IS_MEDIA_BACKEND(self), NULL_ARRAY); + return PURPLE_MEDIA_BACKEND_GET_INTERFACE(self)->get_available_params(); +} diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/media/backend-iface.h --- a/libpurple/media/backend-iface.h Thu May 05 03:40:29 2011 +0000 +++ b/libpurple/media/backend-iface.h Mon May 09 04:26:46 2011 +0000 @@ -68,6 +68,9 @@ GList *codecs); gboolean (*set_send_codec) (PurpleMediaBackend *self, const gchar *sess_id, PurpleMediaCodec *codec); + void (*set_params) (PurpleMediaBackend *self, + guint num_params, GParameter *params); + const gchar **(*get_available_params) (void); }; /** @@ -191,6 +194,31 @@ gboolean purple_media_backend_set_send_codec(PurpleMediaBackend *self, const gchar *sess_id, PurpleMediaCodec *codec); +/** + * Sets various optional parameters of the media backend. + * + * @param self The media backend to set the parameters on. + * @param num_params The number of parameters to pass to backend + * @param params Array of @c GParameter to pass to backend + * + * @since 2.8.0 + */ +void purple_media_backend_set_params(PurpleMediaBackend *self, + guint num_params, GParameter *params); + +/** + * Gets the list of optional parameters supported by the media backend. + * + * The list should NOT be freed. + * + * @param self The media backend + * + * @return NULL-terminated array of names of supported parameters. + * + * @since 2.8.0 + */ +const gchar **purple_media_backend_get_available_params(PurpleMediaBackend *self); + G_END_DECLS #endif /* _MEDIA_BACKEND_IFACE_H_ */ diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/network.c --- a/libpurple/network.c Thu May 05 03:40:29 2011 +0000 +++ b/libpurple/network.c Mon May 09 04:26:46 2011 +0000 @@ -991,7 +991,7 @@ if (stun_server && stun_server[0] != '\0') { if (purple_network_is_available()) { purple_debug_info("network", "running DNS query for STUN server\n"); - purple_dnsquery_a(stun_server, 3478, purple_network_ip_lookup_cb, + purple_dnsquery_a_account(NULL, stun_server, 3478, purple_network_ip_lookup_cb, &stun_ip); } else { purple_debug_info("network", @@ -1009,7 +1009,7 @@ if (turn_server && turn_server[0] != '\0') { if (purple_network_is_available()) { purple_debug_info("network", "running DNS query for TURN server\n"); - purple_dnsquery_a(turn_server, + purple_dnsquery_a_account(NULL, turn_server, purple_prefs_get_int("/purple/network/turn_port"), purple_network_ip_lookup_cb, &turn_ip); } else { diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/Makefile.am --- a/libpurple/protocols/Makefile.am Thu May 05 03:40:29 2011 +0000 +++ b/libpurple/protocols/Makefile.am Mon May 09 04:26:46 2011 +0000 @@ -1,5 +1,5 @@ EXTRA_DIST = Makefile.mingw -DIST_SUBDIRS = bonjour gg irc jabber msn myspace mxit novell null oscar qq sametime silc silc10 simple yahoo zephyr +DIST_SUBDIRS = bonjour gg irc jabber msn myspace mxit novell null oscar sametime silc silc10 simple yahoo zephyr SUBDIRS = $(DYNAMIC_PRPLS) $(STATIC_PRPLS) diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/Makefile.mingw --- a/libpurple/protocols/Makefile.mingw Thu May 05 03:40:29 2011 +0000 +++ b/libpurple/protocols/Makefile.mingw Mon May 09 04:26:46 2011 +0000 @@ -8,7 +8,7 @@ PIDGIN_TREE_TOP := ../.. include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak -SUBDIRS = gg irc jabber msn mxit novell null oscar qq sametime silc simple yahoo bonjour myspace +SUBDIRS = gg irc jabber msn mxit novell null oscar sametime silc simple yahoo bonjour myspace .PHONY: all install clean diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/bonjour/bonjour_ft.c --- a/libpurple/protocols/bonjour/bonjour_ft.c Thu May 05 03:40:29 2011 +0000 +++ b/libpurple/protocols/bonjour/bonjour_ft.c Mon May 09 04:26:46 2011 +0000 @@ -883,8 +883,9 @@ purple_proxy_info_set_type(xf->proxy_info, PURPLE_PROXY_SOCKS5); purple_proxy_info_set_host(xf->proxy_info, xf->proxy_host); purple_proxy_info_set_port(xf->proxy_info, xf->proxy_port); - xf->proxy_connection = purple_proxy_connect_socks5( + xf->proxy_connection = purple_proxy_connect_socks5_account( purple_account_get_connection(account), + account, xf->proxy_info, dstaddr, 0, bonjour_bytestreams_connect_cb, xfer); diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/bonjour/jabber.c --- a/libpurple/protocols/bonjour/jabber.c Thu May 05 03:40:29 2011 +0000 +++ b/libpurple/protocols/bonjour/jabber.c Mon May 09 04:26:46 2011 +0000 @@ -831,12 +831,45 @@ if (source < 0) { PurpleConversation *conv = NULL; PurpleAccount *account = NULL; + GSList *tmp = bb->ips; - purple_debug_error("bonjour", "Error connecting to buddy %s at %s:%d error: %s\n", - purple_buddy_get_name(pb), bb->conversation->ip, bb->port_p2pj, error ? error : "(null)"); + purple_debug_error("bonjour", "Error connecting to buddy %s at %s:%d (%s); Trying next IP address\n", + purple_buddy_get_name(pb), bb->conversation->ip, bb->port_p2pj, error); + + /* There may be multiple entries for the same IP - one per + * presence recieved (e.g. multiple interfaces). + * We need to make sure that we find the previously used entry. + */ + while (tmp && bb->conversation->ip_link != tmp->data) + tmp = g_slist_next(tmp); + if (tmp) + tmp = g_slist_next(tmp); account = purple_buddy_get_account(pb); + if (tmp != NULL) { + const gchar *ip; + PurpleProxyConnectData *connect_data; + + bb->conversation->ip_link = ip = tmp->data; + + purple_debug_info("bonjour", "Starting conversation with %s at %s:%d\n", + purple_buddy_get_name(pb), ip, bb->port_p2pj); + + connect_data = purple_proxy_connect(purple_account_get_connection(account), + account, ip, bb->port_p2pj, _connected_to_buddy, pb); + + if (connect_data != NULL) { + g_free(bb->conversation->ip); + bb->conversation->ip = g_strdup(ip); + bb->conversation->connect_data = connect_data; + + return; + } + } + + purple_debug_error("bonjour", "No more addresses for buddy %s. Aborting", purple_buddy_get_name(pb)); + conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, bb->name, account); if (conv != NULL) purple_conversation_write(conv, NULL, @@ -995,10 +1028,9 @@ { PurpleProxyConnectData *connect_data; PurpleProxyInfo *proxy_info; - /* For better or worse, use the first IP*/ - const char *ip = bb->ips->data; + const char *ip = bb->ips->data; /* Start with the first IP address. */ - purple_debug_info("bonjour", "Starting conversation with %s\n", to); + purple_debug_info("bonjour", "Starting conversation with %s at %s:%d\n", to, ip, bb->port_p2pj); /* Make sure that the account always has a proxy of "none". * This is kind of dirty, but proxy_connect_none() isn't exposed. */ @@ -1021,6 +1053,7 @@ bb->conversation = bonjour_jabber_conv_new(pb, jdata->account, ip); bb->conversation->connect_data = connect_data; + bb->conversation->ip_link = ip; /* We don't want _send_data() to register the tx_handler; * that neeeds to wait until we're actually connected. */ bb->conversation->tx_handler = 0; diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/bonjour/jabber.h --- a/libpurple/protocols/bonjour/jabber.h Thu May 05 03:40:29 2011 +0000 +++ b/libpurple/protocols/bonjour/jabber.h Mon May 09 04:26:46 2011 +0000 @@ -63,6 +63,8 @@ /* The following are only needed before attaching to a PurpleBuddy */ gchar *buddy_name; gchar *ip; + /* This points to a data entry in BonjourBuddy->ips */ + const gchar *ip_link; } BonjourJabberConversation; /** diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/gg/gg.c --- a/libpurple/protocols/gg/gg.c Thu May 05 03:40:29 2011 +0000 +++ b/libpurple/protocols/gg/gg.c Mon May 09 04:26:46 2011 +0000 @@ -818,7 +818,6 @@ static void ggp_callback_add_to_chat_ok(PurpleBuddy *buddy, PurpleRequestFields *fields) { - GGPInfo *info; PurpleConnection *conn; PurpleRequestField *field; GList *sel; @@ -827,8 +826,6 @@ g_return_if_fail(conn != NULL); - info = conn->proto_data; - field = purple_request_fields_get_field(fields, "name"); sel = purple_request_field_list_get_selected(field); @@ -1845,6 +1842,9 @@ case GG_STATE_RESOLVING: purple_debug_info("gg", "GG_STATE_RESOLVING\n"); break; + case GG_STATE_RESOLVING_GG: + purple_debug_info("gg", "GG_STATE_RESOLVING_GG\n"); + break; case GG_STATE_CONNECTING_HUB: purple_debug_info("gg", "GG_STATE_CONNECTING_HUB\n"); break; @@ -1860,6 +1860,9 @@ case GG_STATE_READING_REPLY: purple_debug_info("gg", "GG_STATE_READING_REPLY\n"); break; + case GG_STATE_TLS_NEGOTIATION: + purple_debug_info("gg", "GG_STATE_TLS_NEGOTIATION\n"); + break; default: purple_debug_error("gg", "unknown state = %d\n", info->session->state); @@ -1880,10 +1883,11 @@ purple_input_remove(gc->inpa); /** XXX I think that this shouldn't be done if ev->type is GG_EVENT_CONN_FAILED or GG_EVENT_CONN_SUCCESS -datallah */ - gc->inpa = purple_input_add(info->session->fd, - (info->session->check == 1) ? PURPLE_INPUT_WRITE - : PURPLE_INPUT_READ, - ggp_async_login_handler, gc); + if (info->session->fd >= 0) + gc->inpa = purple_input_add(info->session->fd, + (info->session->check == 1) ? PURPLE_INPUT_WRITE : + PURPLE_INPUT_READ, + ggp_async_login_handler, gc); switch (ev->type) { case GG_EVENT_NONE: @@ -2096,6 +2100,7 @@ struct gg_login_params *glp; GGPInfo *info; const char *address; + const gchar *encryption_type; if (ggp_setup_proxy(account) == -1) return; @@ -2129,11 +2134,13 @@ glp->async = 1; glp->status = ggp_to_gg_status(status, &glp->status_descr); -#if defined(USE_GNUTLS) || !defined(USE_INTERNAL_LIBGADU) - glp->tls = 1; -#else - glp->tls = 0; -#endif + + encryption_type = purple_account_get_string(account, "encryption", "none"); + purple_debug_info("gg", "Requested encryption type: %s\n", encryption_type); + if (strcmp(encryption_type, "opportunistic_tls") == 0) + glp->tls = 1; + else + glp->tls = 0; purple_debug_info("gg", "TLS enabled: %d\n", glp->tls); if (!info->status_broadcasting) @@ -2585,9 +2592,6 @@ static void ggp_register_user(PurpleAccount *account) { PurpleConnection *gc = purple_account_get_connection(account); - GGPInfo *info; - - info = gc->proto_data = g_new0(GGPInfo, 1); ggp_token_request(gc, ggp_register_user_dialog); } @@ -2780,6 +2784,7 @@ static void init_plugin(PurplePlugin *plugin) { PurpleAccountOption *option; + GList *encryption_options = NULL; option = purple_account_option_string_new(_("Nickname"), "nick", _("Gadu-Gadu User")); @@ -2791,6 +2796,26 @@ prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); +#define ADD_VALUE(list, desc, v) { \ + PurpleKeyValuePair *kvp = g_new0(PurpleKeyValuePair, 1); \ + kvp->key = g_strdup((desc)); \ + kvp->value = g_strdup((v)); \ + list = g_list_append(list, kvp); \ +} + + ADD_VALUE(encryption_options, _("Don't use encryption"), "none"); + ADD_VALUE(encryption_options, _("Use encryption if available"), + "opportunistic_tls"); +#if 0 + /* TODO */ + ADD_VALUE(encryption_options, _("Require encryption"), "require_tls"); +#endif + + option = purple_account_option_list_new(_("Connection security"), + "encryption", encryption_options); + prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, + option); + my_protocol = plugin; gg_debug_handler = purple_gg_debug_handler; diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/gg/lib/message.c --- a/libpurple/protocols/gg/lib/message.c Thu May 05 03:40:29 2011 +0000 +++ b/libpurple/protocols/gg/lib/message.c Mon May 09 04:26:46 2011 +0000 @@ -361,7 +361,7 @@ * \param src Dodawany tekst * \param len Długość dodawanego tekstu */ -static void gg_append(char *dst, int *pos, const void *src, int len) +static void gg_append(char *dst, size_t *pos, const void *src, int len) { if (dst != NULL) memcpy(&dst[*pos], src, len); @@ -394,7 +394,8 @@ int format_idx = 0; unsigned char old_attr = 0; const unsigned char *color = (const unsigned char*) "\x00\x00\x00"; - int len, i; + int i; + size_t len; const unsigned char *format_ = (const unsigned char*) format; len = 0; @@ -584,6 +585,11 @@ entity = NULL; for (src = html; *src != 0; src++) { + if (in_entity && !(isalnum(*src) || *src == '#' || *src == ';')) { + in_entity = 0; + gg_append(dst, &len, entity, src - entity); + } + if (*src == '<') { tag = src; in_tag = 1; diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/jabber/disco.c --- a/libpurple/protocols/jabber/disco.c Thu May 05 03:40:29 2011 +0000 +++ b/libpurple/protocols/jabber/disco.c Mon May 09 04:26:46 2011 +0000 @@ -480,10 +480,12 @@ js->srv_query_data = NULL; if (results > 0) { + PurpleAccount *account; purple_debug_info("jabber", "looking up IP for %s:%d\n", resp[0].hostname, resp[0].port); + account = purple_connection_get_account(js->gc); js->stun_query = - purple_dnsquery_a(resp[0].hostname, resp[0].port, + purple_dnsquery_a_account(account, resp[0].hostname, resp[0].port, jabber_disco_stun_lookup_cb, js); } } @@ -548,7 +550,9 @@ } else if (purple_network_get_stun_ip() == NULL || purple_strequal(purple_network_get_stun_ip(), "")) { js->srv_query_data = - purple_srv_resolve("stun", "udp", js->user->domain, + purple_srv_resolve_account( + purple_connection_get_account(js->gc), "stun", "udp", + js->user->domain, jabber_disco_stun_srv_resolve_cb, js); /* TODO: add TURN support later... */ } diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/jabber/google/jingleinfo.c --- a/libpurple/protocols/jabber/google/jingleinfo.c Thu May 05 03:40:29 2011 +0000 +++ b/libpurple/protocols/jabber/google/jingleinfo.c Mon May 09 04:26:46 2011 +0000 @@ -109,13 +109,15 @@ const gchar *udp = xmlnode_get_attrib(server, "udp"); if (host && udp) { + PurpleAccount *account; int port = atoi(udp); /* if there, would already be an ongoing query, cancel it */ if (js->stun_query) purple_dnsquery_destroy(js->stun_query); - js->stun_query = purple_dnsquery_a(host, port, + account = purple_connection_get_account(js->gc); + js->stun_query = purple_dnsquery_a_account(account, host, port, jabber_google_stun_lookup_cb, js); } } diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/jabber/jabber.c --- a/libpurple/protocols/jabber/jabber.c Thu May 05 03:40:29 2011 +0000 +++ b/libpurple/protocols/jabber/jabber.c Mon May 09 04:26:46 2011 +0000 @@ -813,7 +813,8 @@ try_srv_connect(js); } else { purple_debug_info("jabber","Couldn't connect directly to %s. Trying to find alternative connection methods, like BOSH.\n", js->user->domain); - js->srv_query_data = purple_txt_resolve("_xmppconnect", + js->srv_query_data = purple_txt_resolve_account( + purple_connection_get_account(gc), "_xmppconnect", js->user->domain, txt_resolved_cb, js); } return; @@ -1072,7 +1073,7 @@ jabber_login_connect(js, js->user->domain, connect_server, purple_account_get_int(account, "port", 5222), TRUE); } else { - js->srv_query_data = purple_srv_resolve("xmpp-client", + js->srv_query_data = purple_srv_resolve_account(account, "xmpp-client", "tcp", js->user->domain, srv_resolved_cb, js); } } diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/jabber/presence.c --- a/libpurple/protocols/jabber/presence.c Thu May 05 03:40:29 2011 +0000 +++ b/libpurple/protocols/jabber/presence.c Mon May 09 04:26:46 2011 +0000 @@ -450,21 +450,23 @@ g_free(nickname); } - if ((photo = xmlnode_get_child(vcard, "PHOTO")) && - (binval = xmlnode_get_child(photo, "BINVAL")) && - (text = xmlnode_get_data(binval))) { - guchar *data; - gsize size; + if ((photo = xmlnode_get_child(vcard, "PHOTO"))) { + guchar *data = NULL; + gchar *hash = NULL; + gsize size = 0; - data = purple_base64_decode(text, &size); - if (data) { - gchar *hash = jabber_calculate_data_hash(data, size, "sha1"); - purple_buddy_icons_set_for_user(js->gc->account, from, data, - size, hash); - g_free(hash); + if ((binval = xmlnode_get_child(photo, "BINVAL")) && + (text = xmlnode_get_data(binval))) { + data = purple_base64_decode(text, &size); + g_free(text); + + if (data) + hash = jabber_calculate_data_hash(data, size, "sha1"); } - g_free(text); + purple_buddy_icons_set_for_user(js->gc->account, from, data, size, hash); + + g_free(hash); } } } @@ -840,20 +842,22 @@ } } - if(b && presence->vcard_avatar_hash) { - const char *avatar_hash2 = purple_buddy_icons_get_checksum_for_user(b); - if(!avatar_hash2 || strcmp(presence->vcard_avatar_hash, avatar_hash2)) { - JabberIq *iq; - xmlnode *vcard; - + if (b && presence->vcard_avatar_hash) { + const char *ah = presence->vcard_avatar_hash[0] != '\0' ? + presence->vcard_avatar_hash : NULL; + const char *ah2 = purple_buddy_icons_get_checksum_for_user(b); + if (!purple_strequal(ah, ah2)) { /* XXX this is a crappy way of trying to prevent * someone from spamming us with presence packets * and causing us to DoS ourselves...what we really * need is a queue system that can throttle itself, * but i'm too tired to write that right now */ if(!g_slist_find(js->pending_avatar_requests, presence->jb)) { + JabberIq *iq; + xmlnode *vcard; - js->pending_avatar_requests = g_slist_prepend(js->pending_avatar_requests, presence->jb); + js->pending_avatar_requests = + g_slist_prepend(js->pending_avatar_requests, presence->jb); iq = jabber_iq_new(js, JABBER_IQ_GET); xmlnode_set_attrib(iq->node, "to", buddy_name); @@ -1206,9 +1210,12 @@ parse_vcard_avatar(JabberStream *js, JabberPresence *presence, xmlnode *x) { xmlnode *photo = xmlnode_get_child(x, "photo"); + if (photo) { + char *hash_tmp = xmlnode_get_data(photo); g_free(presence->vcard_avatar_hash); - presence->vcard_avatar_hash = xmlnode_get_data(photo); + presence->vcard_avatar_hash = + hash_tmp ? hash_tmp : g_strdup(""); } } diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/jabber/si.c --- a/libpurple/protocols/jabber/si.c Thu May 05 03:40:29 2011 +0000 +++ b/libpurple/protocols/jabber/si.c Mon May 09 04:26:46 2011 +0000 @@ -277,6 +277,7 @@ if(dstjid != NULL && streamhost->host && streamhost->port > 0) { char *dstaddr, *hash; + PurpleAccount *account; jsx->gpi = purple_proxy_info_new(); purple_proxy_info_set_type(jsx->gpi, PURPLE_PROXY_SOCKS5); purple_proxy_info_set_host(jsx->gpi, streamhost->host); @@ -293,8 +294,9 @@ /* Per XEP-0065, the 'host' must be SHA1(SID + from JID + to JID) */ hash = jabber_calculate_data_hash(dstaddr, strlen(dstaddr), "sha1"); - jsx->connect_data = purple_proxy_connect_socks5(NULL, jsx->gpi, - hash, 0, + account = purple_connection_get_account(jsx->js->gc); + jsx->connect_data = purple_proxy_connect_socks5_account(NULL, account, + jsx->gpi, hash, 0, jabber_si_bytestreams_connect_cb, xfer); g_free(hash); g_free(dstaddr); @@ -963,15 +965,23 @@ jabber_si_xfer_bytestreams_send_init(PurpleXfer *xfer) { JabberSIXfer *jsx; + PurpleProxyType proxy_type; purple_xfer_ref(xfer); jsx = xfer->data; - /* TODO: Should there be an option to not use the local host as a ft proxy? - * (to prevent revealing IP address, etc.) */ - jsx->listen_data = purple_network_listen_range(0, 0, SOCK_STREAM, + /* TODO: This should probably be done with an account option instead of + * piggy-backing on the TOR proxy type. */ + proxy_type = purple_proxy_info_get_type( + purple_proxy_get_setup(purple_connection_get_account(jsx->js->gc))); + if (proxy_type == PURPLE_PROXY_TOR) { + purple_debug_info("jabber", "Skipping attempting local streamhost.\n"); + jsx->listen_data = NULL; + } else + jsx->listen_data = purple_network_listen_range(0, 0, SOCK_STREAM, jabber_si_xfer_bytestreams_listen_cb, xfer); + if (jsx->listen_data == NULL) { /* We couldn't open a local port. Perhaps we can use a proxy. */ jabber_si_xfer_bytestreams_listen_cb(-1, xfer); @@ -1681,7 +1691,10 @@ { JabberSIXfer *jsx; PurpleXfer *xfer; - xmlnode *file, *feature, *x, *field, *option, *value, *thumbnail; + xmlnode *file, *feature, *x, *field, *option, *value; +#if ENABLE_FT_THUMBNAILS + xmlnode *thumbnail; +#endif const char *stream_id, *filename, *filesize_c, *profile; guint64 filesize_64 = 0; size_t filesize = 0; @@ -1785,16 +1798,12 @@ if (cid) { jabber_data_request(js, cid, purple_xfer_get_remote_user(xfer), NULL, TRUE, jabber_si_thumbnail_cb, xfer); - } else { - purple_xfer_request(xfer); + return; } - } else { - purple_xfer_request(xfer); } -#else - thumbnail = NULL; /* Silence warning */ +#endif + purple_xfer_request(xfer); -#endif } void diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/msn/p2p.c --- a/libpurple/protocols/msn/p2p.c Thu May 05 03:40:29 2011 +0000 +++ b/libpurple/protocols/msn/p2p.c Mon May 09 04:26:46 2011 +0000 @@ -204,41 +204,43 @@ case MSN_P2P_VERSION_TWO: { MsnP2Pv2Header *header = &info->header.v2; + char *header_wire = NULL; + char *data_header_wire = NULL; if (header->header_tlv != NULL) - header->header_len = msn_tlvlist_size(header->header_tlv) + 8; + header_wire = msn_tlvlist_write(header->header_tlv, (size_t *)&header->header_len); else - header->header_len = 8; + header->header_len = 0; if (header->data_tlv != NULL) - header->data_header_len = msn_tlvlist_size(header->data_tlv) + 8; + data_header_wire = msn_tlvlist_write(header->data_tlv, (size_t *)&header->data_header_len); else - header->data_header_len = 8; + header->data_header_len = 0; - tmp = wire = g_new(char, header->header_len + header->data_header_len); + tmp = wire = g_new(char, 16 + header->header_len + header->data_header_len); - msn_push8(tmp, header->header_len); + msn_push8(tmp, header->header_len + 8); msn_push8(tmp, header->opcode); - msn_push16be(tmp, header->data_header_len + header->message_len); + msn_push16be(tmp, header->data_header_len + 8 + header->message_len); msn_push32be(tmp, header->base_id); - if (header->header_tlv != NULL) { - msn_tlvlist_write(tmp, header->header_len - 8, header->header_tlv); - tmp += header->header_len - 8; + if (header_wire != NULL) { + memcpy(tmp, header_wire, header->header_len); + tmp += header->header_len; } - msn_push8(tmp, header->data_header_len); + msn_push8(tmp, header->data_header_len + 8); msn_push8(tmp, header->data_tf); msn_push16be(tmp, header->package_number); msn_push32be(tmp, header->session_id); - if (header->data_tlv != NULL) { - msn_tlvlist_write(tmp, header->data_header_len - 8, header->data_tlv); - tmp += header->data_header_len - 8; + if (data_header_wire != NULL) { + memcpy(tmp, data_header_wire, header->data_header_len); + tmp += header->data_header_len; } if (len) - *len = header->header_len + header->data_header_len; + *len = header->header_len + header->data_header_len + 16; break; } @@ -248,7 +250,6 @@ } return wire; - } size_t @@ -312,11 +313,28 @@ } gboolean -msn_p2p_msg_is_data(const MsnP2PHeaderFlag flags) +msn_p2p_msg_is_data(const MsnP2PInfo *info) { - return (flags == P2P_MSN_OBJ_DATA || - flags == (P2P_WLM2009_COMP | P2P_MSN_OBJ_DATA) || - flags == P2P_FILE_DATA); + gboolean data = FALSE; + + switch (info->version) { + case MSN_P2P_VERSION_ONE: { + guint32 flags = info->header.v1.flags; + data = (flags == P2P_MSN_OBJ_DATA || + flags == (P2P_WLM2009_COMP | P2P_MSN_OBJ_DATA) || + flags == P2P_FILE_DATA); + break; + } + + case MSN_P2P_VERSION_TWO: + data = info->header.v2.message_len > 0; + break; + + default: + purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version); + } + + return data; } gboolean @@ -361,6 +379,116 @@ return final; } +void +msn_p2p_info_create_ack(MsnP2PInfo *old_info, MsnP2PInfo *new_info) +{ + switch (old_info->version) { + case MSN_P2P_VERSION_ONE: { + MsnP2PHeader *old = &old_info->header.v1; + MsnP2PHeader *new = &new_info->header.v1; + + new->session_id = old->session_id; + new->flags = P2P_ACK; + new->ack_id = old->id; + new->ack_sub_id = old->ack_id; + new->ack_size = old->total_size; + break; + } + + case MSN_P2P_VERSION_TWO: { + MsnP2Pv2Header *old = &old_info->header.v2; + MsnP2Pv2Header *new = &new_info->header.v2; + + msn_tlvlist_add_32(&new->header_tlv, P2P_TLV_TYPE_ACK, old->base_id + old->message_len); + new->opcode = P2P_OPCODE_NONE; + + if (old->message_len > 0) { + if (!msn_tlv_gettlv(old->header_tlv, P2P_TLV_TYPE_ACK, 1)) { + if (old->opcode & P2P_OPCODE_SYN) { + msn_tlv_t *ack_tlv; + new->opcode |= P2P_OPCODE_RAK; + + ack_tlv = msn_tlv_gettlv(old->header_tlv, P2P_TLV_TYPE_PEER_INFO, 1); + if (ack_tlv) { + msn_tlvlist_add_tlv(&new->header_tlv, ack_tlv); + new->opcode |= P2P_OPCODE_SYN; + } + } + } + } + break; + } + + default: + purple_debug_error("msn", "Invalid P2P Info version: %d\n", old_info->version); + } +} + +gboolean +msn_p2p_info_require_ack(MsnP2PInfo *info) +{ + gboolean ret = FALSE; + + switch (info->version) { + case MSN_P2P_VERSION_ONE: { + guint32 flags = msn_p2p_info_get_flags(info); + + ret = flags == P2P_NO_FLAG || flags == P2P_WLM2009_COMP || + msn_p2p_msg_is_data(info); + break; + } + + case MSN_P2P_VERSION_TWO: + ret = (info->header.v2.opcode & P2P_OPCODE_RAK) > 0; + break; + + default: + purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version); + } + + return ret; +} + +gboolean +msn_p2p_info_is_ack(MsnP2PInfo *info) +{ + gboolean ret = FALSE; + + switch (info->version) { + case MSN_P2P_VERSION_ONE: { + ret = msn_p2p_info_get_flags(info) == P2P_ACK; + break; + } + + case MSN_P2P_VERSION_TWO: + ret = msn_tlv_gettlv(info->header.v2.header_tlv, P2P_TLV_TYPE_ACK, 1) != NULL; + break; + + default: + purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version); + } + + return ret; +} + +void +msn_p2p_info_init_first(MsnP2PInfo *info, MsnP2PInfo *old_info) +{ + switch (info->version) { + case MSN_P2P_VERSION_ONE: + info->header.v1.session_id = old_info->header.v1.session_id; + info->header.v1.flags = old_info->header.v1.flags; + break; + + case MSN_P2P_VERSION_TWO: + info->header.v2.data_tf = TF_FIRST; + break; + + default: + purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version); + } +} + guint32 msn_p2p_info_get_session_id(MsnP2PInfo *info) { @@ -372,7 +500,7 @@ break; case MSN_P2P_VERSION_TWO: - /* Nothing to do! */ + session_id = info->header.v2.session_id; break; default: @@ -393,7 +521,7 @@ break; case MSN_P2P_VERSION_TWO: - /* Nothing to do! */ + id = info->header.v2.base_id; break; default: @@ -477,7 +605,7 @@ break; case MSN_P2P_VERSION_TWO: - /* Nothing to do! */ + flags = info->header.v2.data_tf; break; default: @@ -565,7 +693,7 @@ break; case MSN_P2P_VERSION_TWO: - /* Nothing to do! */ + info->header.v2.session_id = session_id; break; default: @@ -583,7 +711,7 @@ break; case MSN_P2P_VERSION_TWO: - /* Nothing to do! */ + info->header.v2.base_id = id; break; default: @@ -652,7 +780,7 @@ break; case MSN_P2P_VERSION_TWO: - /* Nothing to do! */ + info->header.v2.data_tf = flags; break; default: diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/msn/p2p.h --- a/libpurple/protocols/msn/p2p.h Thu May 05 03:40:29 2011 +0000 +++ b/libpurple/protocols/msn/p2p.h Mon May 09 04:26:46 2011 +0000 @@ -59,6 +59,47 @@ /* guint8 body[1]; */ } MsnP2Pv2Header; +typedef struct { + guint16 protocol_version; + guint16 implementation_id; + guint16 version; + guint16 reserved; + guint32 caps; +} P2PPeerInfo; + +typedef enum +{ + TF_FIRST = 0x01, /**< The first package. */ + TF_MSNOBJ = 0x04, /**< Payload contains binary data for MsnObject. */ + TF_FILE = 0x06 /**< Payload contains binary data. */ +} TF; + +typedef enum +{ + P2P_TLV_TYPE_PEER_INFO = 0x01, /**< Client peer info */ + P2P_TLV_TYPE_ACK = 0x02, /**< ACK */ + P2P_TLV_TYPE_NAK = 0x03 /**< NAK */ +} P2PTLVType; + +typedef enum +{ + P2P_TLV_LEN_PEER_INFO = 12, + P2P_TLV_LEN_ACK = 4, + P2P_TLV_LEN_NAK = 4 +} P2PTLVLength; + +typedef enum +{ + P2P_PI_PVER = 0x0200, + P2P_PI_IMP_ID = 0, + P2P_PI_VER = 0x0e00, + P2P_PI_RES = 0, + P2P_PI_CAPS = 0x0000010f +} P2PPeerInfoVal; + +#define DLP_REMAINING 0x01; /**< Indicates the remaining data to transfer.*/ +#define DLP_REMAINING_LEN 8 + typedef struct { guint32 value; @@ -142,7 +183,7 @@ msn_p2p_info_to_string(MsnP2PInfo *info, GString *str); gboolean -msn_p2p_msg_is_data(const MsnP2PHeaderFlag flags); +msn_p2p_msg_is_data(const MsnP2PInfo *info); gboolean msn_p2p_info_is_valid(MsnP2PInfo *info); @@ -150,6 +191,18 @@ gboolean msn_p2p_info_is_final(MsnP2PInfo *info); +void +msn_p2p_info_create_ack(MsnP2PInfo *old_info, MsnP2PInfo *new_info); + +gboolean +msn_p2p_info_require_ack(MsnP2PInfo *info); + +gboolean +msn_p2p_info_is_ack(MsnP2PInfo *info); + +void +msn_p2p_info_init_first(MsnP2PInfo *new_info, MsnP2PInfo *old_info); + guint32 msn_p2p_info_get_session_id(MsnP2PInfo *info); @@ -211,4 +264,3 @@ msn_p2p_info_set_app_id(MsnP2PInfo *info, guint32 app_id); #endif /* MSN_P2P_H */ - diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/msn/slpcall.c --- a/libpurple/protocols/msn/slpcall.c Thu May 05 03:40:29 2011 +0000 +++ b/libpurple/protocols/msn/slpcall.c Mon May 09 04:26:46 2011 +0000 @@ -1130,7 +1130,7 @@ } g_free(body_str); } - else if (msn_p2p_msg_is_data(flags)) + else if (msn_p2p_msg_is_data(slpmsg->p2p_info)) { slpcall = msn_slplink_find_slp_call_with_session_id(slplink, session_id); @@ -1147,7 +1147,7 @@ slpcall->wasted = TRUE; } } - else if (flags == P2P_ACK) + else if (msn_p2p_info_is_ack(slpmsg->p2p_info)) { /* Acknowledgement of previous message. Don't do anything currently. */ } diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/msn/slplink.c --- a/libpurple/protocols/msn/slplink.c Thu May 05 03:40:29 2011 +0000 +++ b/libpurple/protocols/msn/slplink.c Mon May 09 04:26:46 2011 +0000 @@ -292,7 +292,7 @@ part = msn_slpmsgpart_new(msn_p2p_info_dup(info)); part->ack_data = slpmsg; - real_size = (msn_p2p_info_get_flags(info) == P2P_ACK) ? 0 : slpmsg->size; + real_size = msn_p2p_info_is_ack(info) ? 0 : slpmsg->size; offset = msn_p2p_info_get_offset(info); if (offset < real_size) @@ -330,8 +330,7 @@ msn_slplink_send_part(slplink, part); - if (msn_p2p_msg_is_data(msn_p2p_info_get_flags(info)) && - (slpmsg->slpcall != NULL)) + if (msn_p2p_msg_is_data(info) && slpmsg->slpcall != NULL) { slpmsg->slpcall->progress = TRUE; @@ -358,7 +357,7 @@ { msn_p2p_info_set_ack_id(info, rand() % 0xFFFFFF00); } - else if (msn_p2p_msg_is_data(flags)) + else if (msn_p2p_msg_is_data(info)) { MsnSlpCall *slpcall; slpcall = slpmsg->slpcall; @@ -447,22 +446,19 @@ { MsnSlpMessage *slpmsg; guint32 session_id; - guint32 flags; slpmsg = msn_slpmsg_new(slplink); slpmsg->id = msn_p2p_info_get_id(info); session_id = msn_p2p_info_get_session_id(info); - msn_p2p_info_set_session_id(slpmsg->p2p_info, session_id); slpmsg->size = msn_p2p_info_get_total_size(info); - flags = msn_p2p_info_get_flags(info); - msn_p2p_info_set_flags(slpmsg->p2p_info, flags); + msn_p2p_info_init_first(slpmsg->p2p_info, info); if (session_id) { slpmsg->slpcall = msn_slplink_find_slp_call_with_session_id(slplink, session_id); if (slpmsg->slpcall != NULL) { - if (msn_p2p_msg_is_data(flags)) + if (msn_p2p_msg_is_data(info)) { PurpleXfer *xfer = slpmsg->slpcall->xfer; if (xfer != NULL) @@ -502,7 +498,6 @@ process_complete_msg(MsnSlpLink *slplink, MsnSlpMessage *slpmsg, MsnP2PInfo *info) { MsnSlpCall *slpcall; - guint32 flags; slpcall = msn_slp_process_msg(slplink, slpmsg); @@ -513,10 +508,7 @@ purple_debug_info("msn", "msn_slplink_process_msg: slpmsg complete\n"); - flags = msn_p2p_info_get_flags(slpmsg->p2p_info); - - if (flags == P2P_NO_FLAG || flags == P2P_WLM2009_COMP || - msn_p2p_msg_is_data(flags)) + if (msn_p2p_info_require_ack(slpmsg->p2p_info)) { /* Release all the messages and send the ACK */ @@ -605,8 +597,7 @@ slpmsg_add_part(slpmsg, part); - if (msn_p2p_msg_is_data(msn_p2p_info_get_flags(slpmsg->p2p_info)) && - (slpmsg->slpcall != NULL)) + if (msn_p2p_msg_is_data(slpmsg->p2p_info) && slpmsg->slpcall != NULL) { slpmsg->slpcall->progress = TRUE; diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/msn/slpmsg.c --- a/libpurple/protocols/msn/slpmsg.c Thu May 05 03:40:29 2011 +0000 +++ b/libpurple/protocols/msn/slpmsg.c Mon May 09 04:26:46 2011 +0000 @@ -206,12 +206,8 @@ slpmsg = msn_slpmsg_new(NULL); new_info = slpmsg->p2p_info; - msn_p2p_info_set_session_id(new_info, msn_p2p_info_get_session_id(ack_info)); + msn_p2p_info_create_ack(ack_info, new_info); slpmsg->size = msn_p2p_info_get_total_size(ack_info); - msn_p2p_info_set_flags(new_info, P2P_ACK); - msn_p2p_info_set_ack_id(new_info, msn_p2p_info_get_id(ack_info)); - msn_p2p_info_set_ack_sub_id(new_info, msn_p2p_info_get_ack_id(ack_info)); - msn_p2p_info_set_ack_size(new_info, msn_p2p_info_get_total_size(ack_info)); slpmsg->info = "SLP ACK"; return slpmsg; diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/msn/slpmsg_part.c --- a/libpurple/protocols/msn/slpmsg_part.c Thu May 05 03:40:29 2011 +0000 +++ b/libpurple/protocols/msn/slpmsg_part.c Mon May 09 04:26:46 2011 +0000 @@ -175,7 +175,7 @@ slpmsg = data; - real_size = (msn_p2p_info_get_flags(slpmsg->p2p_info) == P2P_ACK) ? 0 : slpmsg->size; + real_size = msn_p2p_info_is_ack(slpmsg->p2p_info) ? 0 : slpmsg->size; offset = msn_p2p_info_get_offset(slpmsg->p2p_info); offset += msn_p2p_info_get_length(part->info); @@ -197,7 +197,7 @@ else { /* The whole message has been sent */ - if (msn_p2p_msg_is_data(msn_p2p_info_get_flags(slpmsg->p2p_info))) + if (msn_p2p_msg_is_data(slpmsg->p2p_info)) { if (slpmsg->slpcall != NULL) { diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/msn/switchboard.c --- a/libpurple/protocols/msn/switchboard.c Thu May 05 03:40:29 2011 +0000 +++ b/libpurple/protocols/msn/switchboard.c Mon May 09 04:26:46 2011 +0000 @@ -643,10 +643,8 @@ static void iro_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) { - PurpleAccount *account; MsnSwitchBoard *swboard; - account = cmdproc->session->account; swboard = cmdproc->data; swboard->total_users = atoi(cmd->params[2]); @@ -658,14 +656,12 @@ joi_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) { MsnSession *session; - PurpleAccount *account; MsnSwitchBoard *swboard; const char *passport; passport = cmd->params[0]; session = cmdproc->session; - account = session->account; swboard = cmdproc->data; msn_switchboard_add_user(swboard, passport); diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/msn/tlv.c --- a/libpurple/protocols/msn/tlv.c Thu May 05 03:40:29 2011 +0000 +++ b/libpurple/protocols/msn/tlv.c Mon May 09 04:26:46 2011 +0000 @@ -45,51 +45,62 @@ g_free(oldtlv); } -static GSList * -msn_tlv_read(GSList *list, const char *bs, size_t *bs_len) -{ - guint8 type, length; - msn_tlv_t *tlv; - - type = msn_read8(bs); - length = msn_read8(bs); - *bs_len -= 2; - - if (length > *bs_len) { - msn_tlvlist_free(list); - return NULL; - } - - tlv = createtlv(type, length, NULL); - if (length > 0) { - tlv->value = g_memdup(bs, length); - if (!tlv->value) { - freetlv(tlv); - msn_tlvlist_free(list); - return NULL; - } - } - - *bs_len -= length; - - return g_slist_prepend(list, tlv); -} - GSList * msn_tlvlist_read(const char *bs, size_t bs_len) { GSList *list = NULL; while (bs_len > 0) { - list = msn_tlv_read(list, bs, &bs_len); - if (list == NULL) + guint8 type, length; + msn_tlv_t *tlv; + + if (bs_len == 3 && *bs == 0) { + /* Padding to multiple of 4 */ + break; + } else if (bs_len == 2 && *bs == 0) { + /* Padding to multiple of 4 */ + break; + } else if (bs_len == 1) { + if (*bs == 0) { + /* Padding to multiple of 4 */ + break; + } else { + /* TLV is not small enough to fit here */ + msn_tlvlist_free(list); + return NULL; + } + } + + type = msn_pop8(bs); + length = msn_pop8(bs); + bs_len -= 2; + + if (length > bs_len) { + msn_tlvlist_free(list); return NULL; + } + + tlv = createtlv(type, length, NULL); + if (length > 0) { + tlv->value = g_memdup(bs, length); + if (!tlv->value) { + freetlv(tlv); + msn_tlvlist_free(list); + return NULL; + } + } + + bs_len -= length; + bs += length; + + list = g_slist_prepend(list, tlv); } return g_slist_reverse(list); } -GSList *msn_tlvlist_copy(GSList *orig) +GSList * +msn_tlvlist_copy(GSList *orig) { GSList *new = NULL; msn_tlv_t *tlv; @@ -158,7 +169,7 @@ } int -msn_tlvlist_add_raw(GSList **list, const guint16 type, const guint16 length, const char *value) +msn_tlvlist_add_raw(GSList **list, const guint8 type, const guint8 length, const char *value) { msn_tlv_t *tlv; @@ -175,7 +186,7 @@ } int -msn_tlvlist_add_8(GSList **list, const guint16 type, const guint8 value) +msn_tlvlist_add_8(GSList **list, const guint8 type, const guint8 value) { char v8[1]; @@ -185,7 +196,7 @@ } int -msn_tlvlist_add_16(GSList **list, const guint16 type, const guint16 value) +msn_tlvlist_add_16(GSList **list, const guint8 type, const guint16 value) { char v16[2]; @@ -195,7 +206,7 @@ } int -msn_tlvlist_add_32(GSList **list, const guint16 type, const guint32 value) +msn_tlvlist_add_32(GSList **list, const guint8 type, const guint32 value) { char v32[4]; @@ -205,19 +216,25 @@ } int -msn_tlvlist_add_str(GSList **list, const guint16 type, const char *value) +msn_tlvlist_add_str(GSList **list, const guint8 type, const char *value) { return msn_tlvlist_add_raw(list, type, strlen(value), value); } int -msn_tlvlist_add_empty(GSList **list, const guint16 type) +msn_tlvlist_add_empty(GSList **list, const guint8 type) { return msn_tlvlist_add_raw(list, type, 0, NULL); } int -msn_tlvlist_replace_raw(GSList **list, const guint16 type, const guint16 length, const char *value) +msn_tlvlist_add_tlv(GSList **list, const msn_tlv_t *tlv) +{ + return msn_tlvlist_add_raw(list, tlv->type, tlv->length, (const char *)tlv->value); +} + +int +msn_tlvlist_replace_raw(GSList **list, const guint8 type, const guint8 length, const char *value) { GSList *cur; msn_tlv_t *tlv; @@ -246,19 +263,19 @@ } int -msn_tlvlist_replace_str(GSList **list, const guint16 type, const char *str) +msn_tlvlist_replace_str(GSList **list, const guint8 type, const char *str) { return msn_tlvlist_replace_raw(list, type, strlen(str), str); } int -msn_tlvlist_replace_empty(GSList **list, const guint16 type) +msn_tlvlist_replace_empty(GSList **list, const guint8 type) { return msn_tlvlist_replace_raw(list, type, 0, NULL); } int -msn_tlvlist_replace_8(GSList **list, const guint16 type, const guint8 value) +msn_tlvlist_replace_8(GSList **list, const guint8 type, const guint8 value) { char v8[1]; @@ -268,7 +285,7 @@ } int -msn_tlvlist_replace_32(GSList **list, const guint16 type, const guint32 value) +msn_tlvlist_replace_32(GSList **list, const guint8 type, const guint32 value) { char v32[4]; @@ -277,8 +294,14 @@ return msn_tlvlist_replace_raw(list, type, 4, v32); } +int +msn_tlvlist_replace_tlv(GSList **list, const msn_tlv_t *tlv) +{ + return msn_tlvlist_replace_raw(list, tlv->type, tlv->length, (const char *)tlv->value); +} + void -msn_tlvlist_remove(GSList **list, const guint16 type) +msn_tlvlist_remove(GSList **list, const guint8 type) { GSList *cur, *next; msn_tlv_t *tlv; @@ -302,35 +325,50 @@ } } -int -msn_tlvlist_write(char *bs, size_t bs_len, GSList *list) +char * +msn_tlvlist_write(GSList *list, size_t *out_len) { -#if 0 - int goodbuflen; - GSList *cur; - msn_tlv_t *tlv; + char *buf; + char *tmp; + size_t bytes_left; + size_t total_len; - /* do an initial run to test total length */ - goodbuflen = msn_tlvlist_size(*list); + tmp = buf = g_malloc(256); + bytes_left = total_len = 256; + + for (; list; list = g_slist_next(list)) { + msn_tlv_t *tlv = (msn_tlv_t *)list->data; - if (goodbuflen > byte_stream_bytes_left(bs)) - return 0; /* not enough buffer */ + if (G_UNLIKELY(tlv->length + 2 > bytes_left)) { + buf = g_realloc(buf, total_len + 256); + bytes_left += 256; + total_len += 256; + tmp = buf + (total_len - bytes_left); + } - /* do the real write-out */ - for (cur = *list; cur; cur = cur->next) { - tlv = cur->data; - byte_stream_put16(bs, tlv->type); - byte_stream_put16(bs, tlv->length); - if (tlv->length > 0) - byte_stream_putraw(bs, tlv->value, tlv->length); + msn_push8(tmp, tlv->type); + msn_push8(tmp, tlv->length); + memcpy(tmp, tlv->value, tlv->length); + tmp += tlv->length; + + bytes_left -= (tlv->length + 2); } -#endif - return 0; /* TODO: This is a nonsensical return */ + /* Align length to multiple of 4 */ + total_len = total_len - bytes_left; + bytes_left = 4 - total_len % 4; + if (bytes_left != 4) + memset(tmp, 0, bytes_left); + else + bytes_left = 0; + + *out_len = total_len + bytes_left; + + return buf; } msn_tlv_t * -msn_tlv_gettlv(GSList *list, const guint16 type, const int nth) +msn_tlv_gettlv(GSList *list, const guint8 type, const int nth) { msn_tlv_t *tlv; int i; @@ -347,7 +385,7 @@ } int -msn_tlv_getlength(GSList *list, const guint16 type, const int nth) +msn_tlv_getlength(GSList *list, const guint8 type, const int nth) { msn_tlv_t *tlv; @@ -371,7 +409,7 @@ } char * -msn_tlv_getstr(GSList *list, const guint16 type, const int nth) +msn_tlv_getstr(GSList *list, const guint8 type, const int nth) { msn_tlv_t *tlv; @@ -383,7 +421,7 @@ } guint8 -msn_tlv_get8(GSList *list, const guint16 type, const int nth) +msn_tlv_get8(GSList *list, const guint8 type, const int nth) { msn_tlv_t *tlv; @@ -395,7 +433,7 @@ } guint16 -msn_tlv_get16(GSList *list, const guint16 type, const int nth) +msn_tlv_get16(GSList *list, const guint8 type, const int nth) { msn_tlv_t *tlv; @@ -407,7 +445,7 @@ } guint32 -msn_tlv_get32(GSList *list, const guint16 type, const int nth) +msn_tlv_get32(GSList *list, const guint8 type, const int nth) { msn_tlv_t *tlv; diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/msn/tlv.h --- a/libpurple/protocols/msn/tlv.h Thu May 05 03:40:29 2011 +0000 +++ b/libpurple/protocols/msn/tlv.h Mon May 09 04:26:46 2011 +0000 @@ -38,12 +38,12 @@ /* TLV handling functions */ char *msn_tlv_getvalue_as_string(msn_tlv_t *tlv); -msn_tlv_t *msn_tlv_gettlv(GSList *list, const guint16 type, const int nth); -int msn_tlv_getlength(GSList *list, const guint16 type, const int nth); -char *msn_tlv_getstr(GSList *list, const guint16 type, const int nth); -guint8 msn_tlv_get8(GSList *list, const guint16 type, const int nth); -guint16 msn_tlv_get16(GSList *list, const guint16 type, const int nth); -guint32 msn_tlv_get32(GSList *list, const guint16 type, const int nth); +msn_tlv_t *msn_tlv_gettlv(GSList *list, const guint8 type, const int nth); +int msn_tlv_getlength(GSList *list, const guint8 type, const int nth); +char *msn_tlv_getstr(GSList *list, const guint8 type, const int nth); +guint8 msn_tlv_get8(GSList *list, const guint8 type, const int nth); +guint16 msn_tlv_get16(GSList *list, const guint8 type, const int nth); +guint32 msn_tlv_get32(GSList *list, const guint8 type, const int nth); /* TLV list handling functions */ GSList *msn_tlvlist_read(const char *bs, size_t bs_len); @@ -52,24 +52,26 @@ int msn_tlvlist_count(GSList *list); size_t msn_tlvlist_size(GSList *list); gboolean msn_tlvlist_equal(GSList *one, GSList *two); -int msn_tlvlist_write(char *bs, size_t bs_len, GSList *list); +char *msn_tlvlist_write(GSList *list, size_t *out_len); void msn_tlvlist_free(GSList *list); -int msn_tlvlist_add_raw(GSList **list, const guint16 type, const guint16 length, const char *value); -int msn_tlvlist_add_empty(GSList **list, const guint16 type); -int msn_tlvlist_add_8(GSList **list, const guint16 type, const guint8 value); -int msn_tlvlist_add_16(GSList **list, const guint16 type, const guint16 value); -int msn_tlvlist_add_32(GSList **list, const guint16 type, const guint32 value); -int msn_tlvlist_add_str(GSList **list, const guint16 type, const char *value); +int msn_tlvlist_add_raw(GSList **list, const guint8 type, const guint8 length, const char *value); +int msn_tlvlist_add_empty(GSList **list, const guint8 type); +int msn_tlvlist_add_8(GSList **list, const guint8 type, const guint8 value); +int msn_tlvlist_add_16(GSList **list, const guint8 type, const guint16 value); +int msn_tlvlist_add_32(GSList **list, const guint8 type, const guint32 value); +int msn_tlvlist_add_str(GSList **list, const guint8 type, const char *value); +int msn_tlvlist_add_tlv(GSList **list, const msn_tlv_t *tlv); -int msn_tlvlist_replace_raw(GSList **list, const guint16 type, const guint16 lenth, const char *value); -int msn_tlvlist_replace_str(GSList **list, const guint16 type, const char *str); -int msn_tlvlist_replace_empty(GSList **list, const guint16 type); -int msn_tlvlist_replace_8(GSList **list, const guint16 type, const guint8 value); -int msn_tlvlist_replace_16(GSList **list, const guint16 type, const guint16 value); -int msn_tlvlist_replace_32(GSList **list, const guint16 type, const guint32 value); +int msn_tlvlist_replace_raw(GSList **list, const guint8 type, const guint8 lenth, const char *value); +int msn_tlvlist_replace_str(GSList **list, const guint8 type, const char *str); +int msn_tlvlist_replace_empty(GSList **list, const guint8 type); +int msn_tlvlist_replace_8(GSList **list, const guint8 type, const guint8 value); +int msn_tlvlist_replace_16(GSList **list, const guint8 type, const guint16 value); +int msn_tlvlist_replace_32(GSList **list, const guint8 type, const guint32 value); +int msn_tlvlist_replace_tlv(GSList **list, const msn_tlv_t *tlv); -void msn_tlvlist_remove(GSList **list, const guint16 type); +void msn_tlvlist_remove(GSList **list, const guint8 type); #endif /* MSN_TLV_H */ diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/mxit/actions.c --- a/libpurple/protocols/mxit/actions.c Thu May 05 03:40:29 2011 +0000 +++ b/libpurple/protocols/mxit/actions.c Mon May 09 04:26:46 2011 +0000 @@ -41,48 +41,21 @@ * @param gc The connection object * @param fields The fields from the request pop-up */ -static void mxit_cb_set_profile( PurpleConnection* gc, PurpleRequestFields* fields ) +static void mxit_profile_cb( PurpleConnection* gc, PurpleRequestFields* fields ) { struct MXitSession* session = (struct MXitSession*) gc->proto_data; PurpleRequestField* field = NULL; - const char* pin = NULL; - const char* pin2 = NULL; const char* name = NULL; const char* bday = NULL; const char* err = NULL; - int len; - int i; - purple_debug_info( MXIT_PLUGIN_ID, "mxit_cb_set_profile\n" ); + purple_debug_info( MXIT_PLUGIN_ID, "mxit_profile_cb\n" ); if ( !PURPLE_CONNECTION_IS_VALID( gc ) ) { purple_debug_error( MXIT_PLUGIN_ID, "Unable to update profile; account offline.\n" ); return; } - /* validate pin */ - pin = purple_request_fields_get_string( fields, "pin" ); - if ( !pin ) { - err = _( "The PIN you entered is invalid." ); - goto out; - } - len = strlen( pin ); - if ( ( len < 4 ) || ( len > 10 ) ) { - err = _( "The PIN you entered has an invalid length [4-10]." ); - goto out; - } - for ( i = 0; i < len; i++ ) { - if ( !g_ascii_isdigit( pin[i] ) ) { - err = _( "The PIN is invalid. It should only consist of digits [0-9]." ); - goto out; - } - } - pin2 = purple_request_fields_get_string( fields, "pin2" ); - if ( ( !pin2 ) || ( strcmp( pin, pin2 ) != 0 ) ) { - err = _( "The two PINs you entered do not match." ); - goto out; - } - /* validate name */ name = purple_request_fields_get_string( fields, "name" ); if ( ( !name ) || ( strlen( name ) < 3 ) ) { @@ -104,12 +77,6 @@ char attrib[512]; unsigned int acount = 0; - /* all good, so we can now update the profile */ - - /* update pin */ - purple_account_set_password( session->acc, pin ); - g_free( session->encpwd ); - session->encpwd = mxit_encrypt_password( session ); /* update name */ g_strlcpy( profile->nickname, name, sizeof( profile->nickname ) ); @@ -117,12 +84,12 @@ g_string_append( attributes, attrib ); acount++; - /* update hidden */ - field = purple_request_fields_get_field( fields, "hidden" ); - profile->hidden = purple_request_field_bool_get_value( field ); - g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_HIDENUMBER, CP_PROFILE_TYPE_BOOL, ( profile->hidden ) ? "1" : "0" ); - g_string_append( attributes, attrib ); - acount++; + /* force hidden if disabled */ + if ( profile->hidden == FALSE ) { + g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_HIDENUMBER, CP_PROFILE_TYPE_BOOL, "1" ); + g_string_append( attributes, attrib ); + acount++; + } /* update birthday */ g_strlcpy( profile->birthday, bday, sizeof( profile->birthday ) ); @@ -186,8 +153,43 @@ g_string_append( attributes, attrib ); acount++; + /* update about me */ + name = purple_request_fields_get_string( fields, "aboutme" ); + if ( !name ) + profile->aboutme[0] = '\0'; + else + g_strlcpy( profile->aboutme, name, sizeof( profile->aboutme ) ); + g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_ABOUTME, CP_PROFILE_TYPE_UTF8, profile->aboutme ); + g_string_append( attributes, attrib ); + acount++; + + /* update where am i */ + name = purple_request_fields_get_string( fields, "whereami" ); + if ( !name) + profile->whereami[0] = '\0'; + else + g_strlcpy( profile->whereami, name, sizeof( profile->whereami ) ); + g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_WHEREAMI, CP_PROFILE_TYPE_UTF8, profile->whereami ); + g_string_append( attributes, attrib ); + acount++; + + /* update flags */ + field = purple_request_fields_get_field( fields, "searchable" ); + if ( purple_request_field_bool_get_value( field ) ) /* is searchable -> clear not-searchable flag */ + profile->flags &= ~CP_PROF_NOT_SEARCHABLE; + else + profile->flags |= CP_PROF_NOT_SEARCHABLE; + field = purple_request_fields_get_field( fields, "suggestable" ); + if ( purple_request_field_bool_get_value( field ) ) /* is suggestable -> clear not-suggestable flag */ + profile->flags &= ~CP_PROF_NOT_SUGGESTABLE; + else + profile->flags |= CP_PROF_NOT_SUGGESTABLE; + g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%i", CP_PROFILE_FLAGS, CP_PROFILE_TYPE_LONG, profile->flags); + g_string_append( attributes, attrib ); + acount++; + /* send the profile update to MXit */ - mxit_send_extprofile_update( session, session->encpwd, acount, attributes->str ); + mxit_send_extprofile_update( session, NULL, acount, attributes->str ); g_string_free( attributes, TRUE ); } else { @@ -202,17 +204,16 @@ * * @param action The action object */ -static void mxit_cb_action_profile( PurplePluginAction* action ) +static void mxit_profile_action( PurplePluginAction* action ) { PurpleConnection* gc = (PurpleConnection*) action->context; struct MXitSession* session = (struct MXitSession*) gc->proto_data; struct MXitProfile* profile = session->profile; PurpleRequestFields* fields = NULL; - PurpleRequestFieldGroup* group = NULL; PurpleRequestField* field = NULL; - purple_debug_info( MXIT_PLUGIN_ID, "mxit_cb_action_profile\n" ); + purple_debug_info( MXIT_PLUGIN_ID, "mxit_profile_action\n" ); /* ensure that we actually have the user's profile information */ if ( !profile ) { @@ -222,69 +223,174 @@ } fields = purple_request_fields_new(); - group = purple_request_field_group_new( NULL ); - purple_request_fields_add_group( fields, group ); + + /* Public information - what other users can see */ + { + PurpleRequestFieldGroup* public_group = purple_request_field_group_new( "Public information" ); + + /* display name */ + field = purple_request_field_string_new( "name", _( "Display Name" ), profile->nickname, FALSE ); + purple_request_field_group_add_field( public_group, field ); + + /* birthday */ + field = purple_request_field_string_new( "bday", _( "Birthday" ), profile->birthday, FALSE ); + purple_request_field_group_add_field( public_group, field ); + if ( profile->flags & CP_PROF_DOBLOCKED ) + purple_request_field_string_set_editable( field, FALSE ); + + /* gender */ + field = purple_request_field_choice_new( "male", _( "Gender" ), ( profile->male ) ? 1 : 0 ); + purple_request_field_choice_add( field, _( "Female" ) ); /* 0 */ + purple_request_field_choice_add( field, _( "Male" ) ); /* 1 */ + purple_request_field_group_add_field( public_group, field ); + + /* first name */ + field = purple_request_field_string_new( "firstname", _( "First Name" ), profile->firstname, FALSE ); + purple_request_field_group_add_field( public_group, field ); + + /* last name */ + field = purple_request_field_string_new( "lastname", _( "Last Name" ), profile->lastname, FALSE ); + purple_request_field_group_add_field( public_group, field ); + + /* about me */ + field = purple_request_field_string_new( "aboutme", _( "About Me" ), profile->aboutme, FALSE); + purple_request_field_group_add_field( public_group, field ); + + /* where I live */ + field = purple_request_field_string_new( "whereami", _( "Where I Live" ), profile->whereami, FALSE); + purple_request_field_group_add_field( public_group, field ); + + purple_request_fields_add_group( fields, public_group ); + } + + /* Private information - what only MXit can see */ + { + PurpleRequestFieldGroup* private_group = purple_request_field_group_new( "Private information" ); + + /* title */ + field = purple_request_field_string_new( "title", _( "Title" ), profile->title, FALSE ); + purple_request_field_group_add_field( private_group, field ); + + /* email */ + field = purple_request_field_string_new( "email", _( "Email" ), profile->email, FALSE ); + purple_request_field_group_add_field( private_group, field ); + + /* mobile number */ + field = purple_request_field_string_new( "mobilenumber", _( "Mobile Number" ), profile->mobilenr, FALSE ); + purple_request_field_group_add_field( private_group, field ); + + /* is searchable */ + field = purple_request_field_bool_new( "searchable", _( "Can be searched" ), ( ( profile->flags & CP_PROF_NOT_SEARCHABLE ) == 0) ); + purple_request_field_group_add_field( private_group, field ); + + /* is suggestable */ + field = purple_request_field_bool_new( "suggestable", _( "Can be suggested" ), ( ( profile->flags & CP_PROF_NOT_SUGGESTABLE ) == 0 ) ); + purple_request_field_group_add_field( private_group, field ); + + purple_request_fields_add_group( fields, private_group ); + } + + /* (reference: "libpurple/request.h") */ + purple_request_fields( gc, _( "Profile" ), _( "Update your MXit Profile" ), NULL, fields, _( "Set" ), + G_CALLBACK( mxit_profile_cb ), _( "Cancel" ), NULL, purple_connection_get_account( gc ), NULL, NULL, gc ); +} + -#if 0 - /* UID (read-only) */ - if ( session->uid ) { - field = purple_request_field_string_new( "mxitid", _( "Your UID" ), session->uid, FALSE ); - purple_request_field_string_set_editable( field, FALSE ); - purple_request_field_group_add_field( group, field ); +/*------------------------------------------------------------------------ + * The user has selected to change their PIN. + * + * @param gc The connection object + * @param fields The fields from the request pop-up + */ +static void mxit_change_pin_cb( PurpleConnection* gc, PurpleRequestFields* fields ) +{ + struct MXitSession* session = (struct MXitSession*) gc->proto_data; + const char* pin = NULL; + const char* pin2 = NULL; + const char* err = NULL; + int len; + int i; + + if ( !PURPLE_CONNECTION_IS_VALID( gc ) ) { + purple_debug_error( MXIT_PLUGIN_ID, "Unable to update PIN; account offline.\n" ); + return; + } + + /* validate pin */ + pin = purple_request_fields_get_string( fields, "pin" ); + if ( !pin ) { + err = _( "The PIN you entered is invalid." ); + goto out; + } + len = strlen( pin ); + if ( ( len < 4 ) || ( len > 10 ) ) { + err = _( "The PIN you entered has an invalid length [4-10]." ); + goto out; + } + for ( i = 0; i < len; i++ ) { + if ( !g_ascii_isdigit( pin[i] ) ) { + err = _( "The PIN is invalid. It should only consist of digits [0-9]." ); + goto out; + } } -#endif + pin2 = purple_request_fields_get_string( fields, "pin2" ); + if ( ( !pin2 ) || ( strcmp( pin, pin2 ) != 0 ) ) { + err = _( "The two PINs you entered do not match." ); + goto out; + } + +out: + if ( !err ) { + /* update PIN in account */ + purple_account_set_password( session->acc, pin ); + + /* update session object */ + g_free( session->encpwd ); + session->encpwd = mxit_encrypt_password( session ); + + /* send the update request to MXit */ + mxit_send_extprofile_update( session, session->encpwd, 0, NULL ); + } + else { + /* show error to user */ + mxit_popup( PURPLE_NOTIFY_MSG_ERROR, _( "PIN Update Error" ), err ); + } +} + + +/*------------------------------------------------------------------------ + * Enable the user to change their PIN. + * + * @param action The action object + */ +static void mxit_change_pin_action( PurplePluginAction* action ) +{ + PurpleConnection* gc = (PurpleConnection*) action->context; + struct MXitSession* session = (struct MXitSession*) gc->proto_data; + + PurpleRequestFields* fields = NULL; + PurpleRequestFieldGroup* group = NULL; + PurpleRequestField* field = NULL; + + purple_debug_info( MXIT_PLUGIN_ID, "mxit_change_pin_action\n" ); + + fields = purple_request_fields_new(); + group = purple_request_field_group_new(NULL); + purple_request_fields_add_group(fields, group); /* pin */ field = purple_request_field_string_new( "pin", _( "PIN" ), session->acc->password, FALSE ); purple_request_field_string_set_masked( field, TRUE ); purple_request_field_group_add_field( group, field ); + + /* verify pin */ field = purple_request_field_string_new( "pin2", _( "Verify PIN" ), session->acc->password, FALSE ); purple_request_field_string_set_masked( field, TRUE ); purple_request_field_group_add_field( group, field ); - /* display name */ - field = purple_request_field_string_new( "name", _( "Display Name" ), profile->nickname, FALSE ); - purple_request_field_group_add_field( group, field ); - - /* birthday */ - field = purple_request_field_string_new( "bday", _( "Birthday" ), profile->birthday, FALSE ); - purple_request_field_group_add_field( group, field ); - if ( profile->flags & CP_PROF_DOBLOCKED ) - purple_request_field_string_set_editable( field, FALSE ); - - /* gender */ - field = purple_request_field_choice_new( "male", _( "Gender" ), ( profile->male ) ? 1 : 0 ); - purple_request_field_choice_add( field, _( "Female" ) ); /* 0 */ - purple_request_field_choice_add( field, _( "Male" ) ); /* 1 */ - purple_request_field_group_add_field( group, field ); - - /* hidden */ - field = purple_request_field_bool_new( "hidden", _( "Hide my number" ), profile->hidden ); - purple_request_field_group_add_field( group, field ); - - /* title */ - field = purple_request_field_string_new( "title", _( "Title" ), profile->title, FALSE ); - purple_request_field_group_add_field( group, field ); - - /* first name */ - field = purple_request_field_string_new( "firstname", _( "First Name" ), profile->firstname, FALSE ); - purple_request_field_group_add_field( group, field ); - - /* last name */ - field = purple_request_field_string_new( "lastname", _( "Last Name" ), profile->lastname, FALSE ); - purple_request_field_group_add_field( group, field ); - - /* email */ - field = purple_request_field_string_new( "email", _( "Email" ), profile->email, FALSE ); - purple_request_field_group_add_field( group, field ); - - /* mobile number */ - field = purple_request_field_string_new( "mobilenumber", _( "Mobile Number" ), profile->mobilenr, FALSE ); - purple_request_field_group_add_field( group, field ); - /* (reference: "libpurple/request.h") */ - purple_request_fields( gc, _( "Profile" ), _( "Update your Profile" ), _( "Here you can update your MXit profile" ), fields, _( "Set" ), - G_CALLBACK( mxit_cb_set_profile ), _( "Cancel" ), NULL, purple_connection_get_account( gc ), NULL, NULL, gc ); + purple_request_fields( gc, _( "Change PIN" ), _( "Change MXit PIN" ), NULL, fields, _( "Set" ), + G_CALLBACK( mxit_change_pin_cb ), _( "Cancel" ), NULL, purple_connection_get_account( gc ), NULL, NULL, gc ); } @@ -293,7 +399,7 @@ * * @param action The action object */ -static void mxit_cb_action_splash( PurplePluginAction* action ) +static void mxit_splash_action( PurplePluginAction* action ) { PurpleConnection* gc = (PurpleConnection*) action->context; struct MXitSession* session = (struct MXitSession*) gc->proto_data; @@ -310,11 +416,11 @@ * * @param action The action object */ -static void mxit_cb_action_about( PurplePluginAction* action ) +static void mxit_about_action( PurplePluginAction* action ) { char version[256]; - g_snprintf( version, sizeof( version ), + g_snprintf( version, sizeof( version ), "MXit Client Protocol v%i.%i\n\n" "Author:\nPieter Loubser\n\n" "Contributors:\nAndrew Victor\n\n" @@ -326,6 +432,61 @@ /*------------------------------------------------------------------------ + * Request list of suggested friends. + * + * @param action The action object + */ +static void mxit_suggested_friends_action( PurplePluginAction* action ) +{ + PurpleConnection* gc = (PurpleConnection*) action->context; + struct MXitSession* session = (struct MXitSession*) gc->proto_data; + const char* profilelist[] = { + CP_PROFILE_BIRTHDATE, CP_PROFILE_GENDER, CP_PROFILE_FULLNAME, CP_PROFILE_FIRSTNAME, + CP_PROFILE_LASTNAME, CP_PROFILE_REGCOUNTRY, CP_PROFILE_STATUS, CP_PROFILE_AVATAR, + CP_PROFILE_WHEREAMI, CP_PROFILE_ABOUTME }; + + mxit_send_suggest_friends( session, MXIT_SEARCHRESULTS_MAX, ARRAY_SIZE( profilelist ), profilelist ); +} + + +/*------------------------------------------------------------------------ + * Perform contact search. + * + * @param action The action object + */ +static void mxit_user_search_cb( PurpleConnection *gc, const char *input ) +{ + struct MXitSession* session = (struct MXitSession*) gc->proto_data; + const char* profilelist[] = { + CP_PROFILE_BIRTHDATE, CP_PROFILE_GENDER, CP_PROFILE_FULLNAME, CP_PROFILE_FIRSTNAME, + CP_PROFILE_LASTNAME, CP_PROFILE_REGCOUNTRY, CP_PROFILE_STATUS, CP_PROFILE_AVATAR, + CP_PROFILE_WHEREAMI, CP_PROFILE_ABOUTME }; + + mxit_send_suggest_search( session, MXIT_SEARCHRESULTS_MAX, input, ARRAY_SIZE( profilelist ), profilelist ); +} + + +/*------------------------------------------------------------------------ + * Display the search input form. + * + * @param action The action object + */ +static void mxit_user_search_action( PurplePluginAction* action ) +{ + PurpleConnection* gc = (PurpleConnection*) action->context; + + purple_request_input( gc, _( "Search for user" ), + _( "Search for a MXit contact" ), + _( "Type search information" ), + NULL, FALSE, FALSE, NULL, + _("_Search"), G_CALLBACK( mxit_user_search_cb ), + _("_Cancel"), NULL, + purple_connection_get_account( gc ), NULL, NULL, + gc); +} + + +/*------------------------------------------------------------------------ * Associate actions with the MXit plugin. * * @param plugin The MXit protocol plugin @@ -338,17 +499,28 @@ GList* m = NULL; /* display / change profile */ - action = purple_plugin_action_new( _( "Change Profile..." ), mxit_cb_action_profile ); + action = purple_plugin_action_new( _( "Change Profile..." ), mxit_profile_action ); + m = g_list_append( m, action ); + + /* change PIN */ + action = purple_plugin_action_new( _( "Change PIN..." ), mxit_change_pin_action ); + m = g_list_append( m, action ); + + /* suggested friends */ + action = purple_plugin_action_new( _( "Suggested friends..." ), mxit_suggested_friends_action ); + m = g_list_append( m, action ); + + /* search for contacts */ + action = purple_plugin_action_new( _( "Search for contacts..." ), mxit_user_search_action ); m = g_list_append( m, action ); /* display splash-screen */ - action = purple_plugin_action_new( _( "View Splash..." ), mxit_cb_action_splash ); + action = purple_plugin_action_new( _( "View Splash..." ), mxit_splash_action ); m = g_list_append( m, action ); /* display plugin version */ - action = purple_plugin_action_new( _( "About..." ), mxit_cb_action_about ); + action = purple_plugin_action_new( _( "About..." ), mxit_about_action ); m = g_list_append( m, action ); return m; } - diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/mxit/chunk.c --- a/libpurple/protocols/mxit/chunk.c Thu May 05 03:40:29 2011 +0000 +++ b/libpurple/protocols/mxit/chunk.c Mon May 09 04:26:46 2011 +0000 @@ -224,6 +224,7 @@ * * @param chunkdata The chunked-data buffer * @param str A pointer to extracted string. Must be g_free()'d. + * @param maxstrlen Maximum size of destination buffer. * @return The number of bytes consumed */ static int get_utf8_string( const char* chunkdata, char* str, int maxstrlen ) @@ -465,10 +466,10 @@ pos += get_int32( &chunkdata[pos], &(offer->filesize) ); /* filename [UTF-8] */ - pos += get_utf8_string( &chunkdata[pos], offer->filename, sizeof( offer->filename) ); + pos += get_utf8_string( &chunkdata[pos], offer->filename, sizeof( offer->filename ) ); /* mime type [UTF-8] */ - /* not used by libPurple */ + pos += get_utf8_string( &chunkdata[pos], offer->mimetype, sizeof( offer->mimetype ) ); /* timestamp [8 bytes] */ /* not used by libPurple */ @@ -606,6 +607,37 @@ /*------------------------------------------------------------------------ + * Parse a received "send file direct" response chunk. (Chunk 10) + * + * @param chunkdata Chunked data buffer + * @param datalen The length of the chunked data + * @param sendfile Decoded sendfile information + */ +void mxit_chunk_parse_sendfile( char* chunkdata, int datalen, struct sendfile_chunk* sendfile ) +{ + int pos = 0; + short entries = 0; + + purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_sendfile (%i bytes)\n", datalen ); + + /* number of entries [2 bytes] */ + pos += get_int16( &chunkdata[pos], &entries ); + + if ( entries < 1 ) /* no data */ + return; + + /* contactAddress [UTF-8 string] */ + pos += get_utf8_string( &chunkdata[pos], sendfile->username, sizeof( sendfile->username ) ); + + /* status [4 bytes] */ + pos += get_int32( &chunkdata[pos], &(sendfile->status) ); + + /* status message [UTF-8 string] */ + pos += get_utf8_string( &chunkdata[pos], sendfile->statusmsg, sizeof( sendfile->statusmsg ) ); +} + + +/*------------------------------------------------------------------------ * Parse a received "get avatar" response chunk. (Chunk 14) * * @param chunkdata Chunked data buffer diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/mxit/chunk.h --- a/libpurple/protocols/mxit/chunk.h Thu May 05 03:40:29 2011 +0000 +++ b/libpurple/protocols/mxit/chunk.h Mon May 09 04:26:46 2011 +0000 @@ -99,14 +99,20 @@ return &chunkheader[MXIT_CHUNK_HEADER_SIZE]; } - +/* + * Offer File chunk (6). + */ struct offerfile_chunk { char fileid[MXIT_CHUNK_FILEID_LEN]; char username[MXIT_CP_MAX_JID_LEN + 1]; int filesize; char filename[FILENAME_MAX]; + char mimetype[64]; }; +/* + * Get File chunk (8) response. + */ struct getfile_chunk { char fileid[MXIT_CHUNK_FILEID_LEN]; int offset; @@ -115,6 +121,9 @@ char* data; }; +/* + * Custom Resource chunk (1). + */ struct cr_chunk { char id[64]; char handle[64]; @@ -122,6 +131,9 @@ GList* resources; }; +/* + * Splash Image chunk (2) + */ struct splash_chunk { char anchor; char showtime; @@ -130,10 +142,16 @@ int datalen; }; +/* + * Splash Click Through chunk (3) + */ struct splash_click_chunk { char reserved[1]; }; +/* + * Get Avatar chunk (14) response. + */ struct getavatar_chunk { char mxitid[50]; char avatarid[64]; @@ -146,6 +164,15 @@ char* data; }; +/* + * Send File Direct chunk (10) response. + */ +struct sendfile_chunk { + char username[MXIT_CP_MAX_JID_LEN + 1]; + int status; + char statusmsg[1024]; +}; + /* Encode chunk */ int mxit_chunk_create_senddirect( char* chunkdata, const char* username, const char* filename, const unsigned char* data, int datalen ); int mxit_chunk_create_reject( char* chunkdata, const char* fileid ); @@ -158,6 +185,7 @@ void mxit_chunk_parse_offer( char* chunkdata, int datalen, struct offerfile_chunk* offer ); void mxit_chunk_parse_get( char* chunkdata, int datalen, struct getfile_chunk* getfile ); void mxit_chunk_parse_cr( char* chunkdata, int datalen, struct cr_chunk* cr ); +void mxit_chunk_parse_sendfile( char* chunkdata, int datalen, struct sendfile_chunk* sendfile ); void mxit_chunk_parse_get_avatar( char* chunkdata, int datalen, struct getavatar_chunk* avatar ); #endif /* _MXIT_CHUNK_H_ */ diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/mxit/formcmds.c --- a/libpurple/protocols/mxit/formcmds.c Thu May 05 03:40:29 2011 +0000 +++ b/libpurple/protocols/mxit/formcmds.c Mon May 09 04:26:46 2011 +0000 @@ -54,6 +54,15 @@ MXIT_CMD_TABLE /* Table (tbl) */ } MXitCommandType; +/* Chat-screen behaviours (bhvr) */ +#define SCREEN_NO_HEADINGS 0x01 +#define SCREEN_FULLSCREEN 0x02 +#define SCREEN_AUTOCLEAR 0x04 +#define SCREEN_NO_AUDIO 0x08 +#define SCREEN_NO_MSGPREFIX 0x10 +#define SCREEN_NOTIFY 0x20 +#define SCREEN_PROGRESSBAR 0x40 + /* * object for an inline image request with an URL @@ -238,9 +247,7 @@ clearmsgscreen = g_hash_table_lookup(hash, "clearmsgscreen"); if ( (clearmsgscreen) && (strcmp(clearmsgscreen, "true") == 0) ) { /* this is a command to clear the chat screen */ - purple_debug_info(MXIT_PLUGIN_ID, "Clear the screen\n"); - - purple_conversation_clear_message_history(conv); // TODO: This doesn't actually clear the screen. + purple_conversation_clear_message_history(conv); } } @@ -283,6 +290,7 @@ /*------------------------------------------------------------------------ * Process a PlatformRequest MXit command. + * [::op=cmd|type=platreq|selmsg=Upgrade MXit|dest=http%3a//m.mxit.com|id=12345:] * * @param hash The MXit command map * @param msg The message to display (as generated so far) @@ -371,6 +379,173 @@ /*------------------------------------------------------------------------ + * Process an Imagestrip MXit command. + * [::op=is|nm=status|dat=iVBORw0KGgoAAAA%3d%3d|v=63398792426788|fw=8|fh=8|layer=0:] + * + * @param from The sender of the message. + * @param hash The MXit command map + */ +static void command_imagestrip(struct MXitSession* session, const char* from, GHashTable* hash) +{ + const char* name; + const char* validator; + const char* tmp; + int width, height, layer; + + purple_debug_info(MXIT_PLUGIN_ID, "ImageStrip received from %s\n", from); + + /* image strip name */ + name = g_hash_table_lookup(hash, "nm"); + + /* validator */ + validator = g_hash_table_lookup(hash, "v"); + + /* image data */ + tmp = g_hash_table_lookup(hash, "dat"); + if (tmp) { + guchar* rawimg; + gsize rawimglen; + char* dir; + char* filename; + + /* base64 decode the image data */ + rawimg = purple_base64_decode(tmp, &rawimglen); + + /* save it to a file */ + dir = g_strdup_printf("%s/mxit/imagestrips", purple_user_dir()); + purple_build_dir(dir, S_IRUSR | S_IWUSR | S_IXUSR); /* ensure directory exists */ + + filename = g_strdup_printf("%s/%s-%s-%s.png", dir, from, name, validator); + purple_util_write_data_to_file_absolute(filename, (char*) rawimg, rawimglen); + + g_free(dir); + g_free(filename); + } + + tmp = g_hash_table_lookup(hash, "fw"); + width = atoi(tmp); + + tmp = g_hash_table_lookup(hash, "fh"); + height = atoi(tmp); + + tmp = g_hash_table_lookup(hash, "layer"); + layer = atoi(tmp); + + purple_debug_info(MXIT_PLUGIN_ID, "ImageStrip %s from %s: [w=%i h=%i l=%i validator=%s]\n", name, from, width, height, layer, validator); +} + + +/*------------------------------------------------------------------------ + * Process a Chat-Screen-Info MXit command. + * [::op=csi:] + * + * @param session The MXit session object + * @param from The sender of the message. + */ +static void command_screeninfo(struct MXitSession* session, const char* from) +{ + char* response; + + purple_debug_info(MXIT_PLUGIN_ID, "Chat Screen Info received from %s\n", from); + + // TODO: Determine width, height, colors of chat-screen. + + response = g_strdup_printf("::type=csi|res=bhvr,0;w,%i;h,%i;col,0.ffffffff,29.ff000000:", 300, 400); + + /* send response back to MXit */ + mxit_send_message( session, from, response, FALSE, TRUE ); + + g_free(response); +} + + +/*------------------------------------------------------------------------ + * Process a Chat-Screen-Configure MXit command. + * [::op=csc|bhvr=|menu=|col=:] + * where: + * menu ::= { ";" } + * menuitem ::= { type "," "," "," } + * colors ::= { ";" } + * color ::= "," + * + * @param session The MXit session object + * @param from The sender of the message. + * @param hash The MXit command map + */ +static void command_screenconfig(struct MXitSession* session, const char* from, GHashTable* hash) +{ + const char* tmp; + + purple_debug_info(MXIT_PLUGIN_ID, "Chat Screen Configure received from %s\n", from); + + /* Behaviour */ + tmp = g_hash_table_lookup(hash, "bhvr"); + if (tmp) { + purple_debug_info(MXIT_PLUGIN_ID, " behaviour = %s\n", tmp); + // TODO: Re-configure conversation screen. + } + + /* Menu */ + tmp = g_hash_table_lookup(hash, "menu"); + if (tmp) { + purple_debug_info(MXIT_PLUGIN_ID, " menu = %s\n", tmp); + // TODO: Implement conversation-specific sub-menu. + } + + /* Colours */ + tmp = g_hash_table_lookup(hash, "col"); + if (tmp) { + purple_debug_info(MXIT_PLUGIN_ID, " colours = %s\n", tmp); + // TODO: Re-configuration conversation colors. + } +} + + +/*------------------------------------------------------------------------ + * Process a Table Markup MXit command. + * + * @param mx The received message data object + * @param hash The MXit command map + */ +static void command_table(struct RXMsgData* mx, GHashTable* hash) +{ + const char* tmp; + const char* name; + int mode; + int nr_columns = 0, nr_rows = 0; + gchar** coldata; + int i, j; + + /* table name */ + name = g_hash_table_lookup(hash, "nm"); + + /* number of columns */ + tmp = g_hash_table_lookup(hash, "col"); + nr_columns = atoi(tmp); + + /* number of rows */ + tmp = g_hash_table_lookup(hash, "row"); + nr_rows = atoi(tmp); + + /* mode */ + tmp = g_hash_table_lookup(hash, "mode"); + mode = atoi(tmp); + + /* table data */ + tmp = g_hash_table_lookup(hash, "d"); + coldata = g_strsplit(tmp, "~", 0); /* split into entries for each row & column */ + + purple_debug_info(MXIT_PLUGIN_ID, "Table %s from %s: [cols=%i rows=%i mode=%i]\n", name, mx->from, nr_columns, nr_rows, mode); + + for (i = 0; i < nr_rows; i++) { + for (j = 0; j < nr_columns; j++) { + purple_debug_info(MXIT_PLUGIN_ID, " Row %i Column %i = %s\n", i, j, coldata[i*nr_columns + j]); + } + } +} + + +/*------------------------------------------------------------------------ * Process a received MXit Command message. * * @param mx The received message data object @@ -412,6 +587,18 @@ case MXIT_CMD_IMAGE : command_image(mx, hash, mx->msg); break; + case MXIT_CMD_SCREENCONFIG : + command_screenconfig(mx->session, mx->from, hash); + break; + case MXIT_CMD_SCREENINFO : + command_screeninfo(mx->session, mx->from); + break; + case MXIT_CMD_IMAGESTRIP : + command_imagestrip(mx->session, mx->from, hash); + break; + case MXIT_CMD_TABLE : + command_table(mx, hash); + break; default : /* command unknown, or not currently supported */ break; diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/mxit/login.c --- a/libpurple/protocols/mxit/login.c Thu May 05 03:40:29 2011 +0000 +++ b/libpurple/protocols/mxit/login.c Mon May 09 04:26:46 2011 +0000 @@ -141,9 +141,9 @@ } /* This timer might already exist if we're registering a new account */ - if ( session->q_timer == 0 ) { + if ( session->q_slow_timer_id == 0 ) { /* start the tx queue manager timer */ - session->q_timer = purple_timeout_add_seconds( 2, mxit_manage_queue_slow, session ); + session->q_slow_timer_id = purple_timeout_add_seconds( 2, mxit_manage_queue_slow, session ); } } diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/mxit/markup.c --- a/libpurple/protocols/mxit/markup.c Thu May 05 03:40:29 2011 +0000 +++ b/libpurple/protocols/mxit/markup.c Mon May 09 04:26:46 2011 +0000 @@ -235,7 +235,6 @@ */ static void mxit_show_split_message( struct RXMsgData* mx ) { - const char* cont = "continuing...\n"; GString* msg = NULL; char* ch = NULL; int pos = 0; @@ -245,7 +244,6 @@ int l_gt = 0; int stop = 0; int tags = 0; - int segs = 0; gboolean intag = FALSE; /* @@ -319,21 +317,20 @@ stop--; } - /* build the string */ - if ( segs ) - g_string_prepend( msg, cont ); - /* push message to pidgin */ serv_got_im( mx->session->con, mx->from, msg->str, mx->flags, mx->timestamp ); g_string_free( msg, TRUE ); msg = NULL; + /* next part need this flag set */ + mx->flags |= PURPLE_MESSAGE_RAW; + tags = 0; - segs++; start = stop + 1; + pos = start; } - - pos++; + else + pos++; } if ( start != pos ) { @@ -343,8 +340,6 @@ ch[pos] = '\0'; msg = g_string_new( &ch[start] ); ch[pos] = '\n'; - if ( segs ) - g_string_prepend( msg, cont ); /* push message to pidgin */ serv_got_im( mx->session->con, mx->from, msg->str, mx->flags, mx->timestamp ); @@ -1095,10 +1090,15 @@ } else if ( purple_str_has_prefix( &message[i], "roomname, session->acc); - if (convo == NULL) { - purple_debug_error(MXIT_PLUGIN_ID, "Conversation '%s' not found\n", multimx->roomname); - return; - } - purple_conv_chat_add_user(PURPLE_CONV_CHAT(convo), nickname, NULL, PURPLE_CBFLAGS_NONE, TRUE); } @@ -200,79 +191,61 @@ /*------------------------------------------------------------------------ * Another user has left the GroupChat, remove them from the member-list. * - * @param session The MXit session object - * @param multimx The MultiMX room object + * @param convo The Conversation object * @param nickname The nickname of the user who left the room */ -static void member_removed(struct MXitSession* session, struct multimx* multimx, const char* nickname) +static void member_removed(PurpleConversation* convo, const char* nickname) { - PurpleConversation *convo; - purple_debug_info(MXIT_PLUGIN_ID, "member_removed: '%s'\n", nickname); - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, multimx->roomname, session->acc); - if (convo == NULL) { - purple_debug_error(MXIT_PLUGIN_ID, "Conversation '%s' not found\n", multimx->roomname); - return; - } - purple_conv_chat_remove_user(PURPLE_CONV_CHAT(convo), nickname, NULL); } /*------------------------------------------------------------------------ - * A user was kicked from the GroupChat. + * A user was kicked from the GroupChat, remove them from the member-list. * - * @param session The MXit session object - * @param multimx The MultiMX room object + * @param convo The Conversation object * @param nickname The nickname of the user who was kicked */ -static void member_kicked(struct MXitSession* session, struct multimx* multimx, const char* nickname) +static void member_kicked(PurpleConversation* convo, const char* nickname) { - PurpleConversation *convo; - purple_debug_info(MXIT_PLUGIN_ID, "member_kicked: '%s'\n", nickname); - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, multimx->roomname, session->acc); - if (convo == NULL) { - purple_debug_error(MXIT_PLUGIN_ID, "Conversation '%s' not found\n", multimx->roomname); - return; - } + purple_conv_chat_remove_user(PURPLE_CONV_CHAT(convo), nickname, _("was kicked")); +} + - /* who was kicked? - compare to our original nickname */ - if (purple_utf8_strcasecmp(nickname, multimx->nickname) == 0) - { - /* you were kicked */ - purple_conv_chat_write(PURPLE_CONV_CHAT(convo), "MXit", _("You have been kicked from this MultiMX."), PURPLE_MESSAGE_SYSTEM, time(NULL)); - purple_conv_chat_clear_users(PURPLE_CONV_CHAT(convo)); - serv_got_chat_left(session->con, multimx->chatid); - } - else - purple_conv_chat_remove_user(PURPLE_CONV_CHAT(convo), nickname, _("was kicked")); +/*------------------------------------------------------------------------ + * You were kicked from the GroupChat. + * + * @param convo The Conversation object + * @param session The MXit session object + * @param multimx The MultiMX room object + */ +static void you_kicked(PurpleConversation* convo, struct MXitSession* session, struct multimx* multimx) +{ + purple_debug_info(MXIT_PLUGIN_ID, "you_kicked\n"); + + purple_conv_chat_write(PURPLE_CONV_CHAT(convo), "MXit", _("You have been kicked from this MultiMX."), PURPLE_MESSAGE_SYSTEM, time(NULL)); + purple_conv_chat_clear_users(PURPLE_CONV_CHAT(convo)); + serv_got_chat_left(session->con, multimx->chatid); } /*------------------------------------------------------------------------ * Update the full GroupChat member list. * - * @param session The MXit session object - * @param multimx The MultiMX room object + * @param convo The Conversation object * @param data The nicknames of the users in the room (separated by \n) */ -static void member_update(struct MXitSession* session, struct multimx* multimx, char* data) +static void member_update(PurpleConversation* convo, char* data) { - PurpleConversation *convo; gchar** userlist; int i = 0; purple_debug_info(MXIT_PLUGIN_ID, "member_update: '%s'\n", data); - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, multimx->roomname, session->acc); - if (convo == NULL) { - purple_debug_error(MXIT_PLUGIN_ID, "Conversation '%s' not found\n", multimx->roomname); - return; - } - /* Clear list */ purple_conv_chat_clear_users(PURPLE_CONV_CHAT(convo)); @@ -402,27 +375,38 @@ /* Must be a service message */ char* ofs; + PurpleConversation* convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, multimx->roomname, mx->session->acc); + if (convo == NULL) { + purple_debug_error(MXIT_PLUGIN_ID, "Conversation '%s' not found\n", multimx->roomname); + return; + } + /* Determine if somebody has joined or left - update member-list */ if ((ofs = strstr(msg, " has joined")) != NULL) { /* Somebody has joined */ *ofs = '\0'; - member_added(mx->session, multimx, msg); + member_added(convo, msg); mx->processed = TRUE; } else if ((ofs = strstr(msg, " has left")) != NULL) { /* Somebody has left */ *ofs = '\0'; - member_removed(mx->session, multimx, msg); + member_removed(convo, msg); mx->processed = TRUE; } else if ((ofs = strstr(msg, " has been kicked")) != NULL) { /* Somebody has been kicked */ *ofs = '\0'; - member_kicked(mx->session, multimx, msg); + member_kicked(convo, msg); + mx->processed = TRUE; + } + else if (strcmp(msg, "You have been kicked.") == 0) { + /* You have been kicked */ + you_kicked(convo, mx->session, multimx); mx->processed = TRUE; } else if (g_str_has_prefix(msg, "The following users are in this MultiMx:") == TRUE) { - member_update(mx->session, multimx, msg + strlen("The following users are in this MultiMx:") + 1); + member_update(convo, msg + strlen("The following users are in this MultiMx:") + 1); mx->processed = TRUE; } else { diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/mxit/mxit.c --- a/libpurple/protocols/mxit/mxit.c Thu May 05 03:40:29 2011 +0000 +++ b/libpurple/protocols/mxit/mxit.c Mon May 09 04:26:46 2011 +0000 @@ -565,25 +565,23 @@ struct MXitSession* session = (struct MXitSession*) gc->proto_data; const char* profilelist[] = { CP_PROFILE_BIRTHDATE, CP_PROFILE_GENDER, CP_PROFILE_FULLNAME, CP_PROFILE_FIRSTNAME, CP_PROFILE_LASTNAME, CP_PROFILE_REGCOUNTRY, CP_PROFILE_LASTSEEN, - CP_PROFILE_STATUS, CP_PROFILE_AVATAR }; + CP_PROFILE_STATUS, CP_PROFILE_AVATAR, CP_PROFILE_WHEREAMI, CP_PROFILE_ABOUTME }; purple_debug_info( MXIT_PLUGIN_ID, "mxit_get_info: '%s'\n", who ); /* find the buddy information for this contact (reference: "libpurple/blist.h") */ buddy = purple_find_buddy( session->acc, who ); - if ( !buddy ) { - purple_debug_warning( MXIT_PLUGIN_ID, "mxit_get_info: unable to find the buddy '%s'\n", who ); - return; - } + if ( buddy ) { + /* user is in our contact-list, so it's not an invite */ + contact = purple_buddy_get_protocol_data( buddy ); + if ( !contact ) + return; - contact = purple_buddy_get_protocol_data( buddy ); - if ( !contact ) - return; - - /* only MXit users have profiles */ - if ( contact->type != MXIT_TYPE_MXIT ) { - mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "No profile available" ), _( "This contact does not have a profile." ) ); - return; + /* only MXit users have profiles */ + if ( contact->type != MXIT_TYPE_MXIT ) { + mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "No profile available" ), _( "This contact does not have a profile." ) ); + return; + } } /* send profile request */ @@ -628,7 +626,7 @@ return; /* send a new invite */ - mxit_send_invite( session, contact->username, contact->alias, contact->groupname ); + mxit_send_invite( session, contact->username, TRUE, contact->alias, contact->groupname, NULL ); } @@ -664,7 +662,7 @@ /*========================================================================================================================*/ static PurplePluginProtocolInfo proto_info = { - OPT_PROTO_REGISTER_NOSCREENNAME | OPT_PROTO_UNIQUE_CHATNAME | OPT_PROTO_IM_IMAGE, /* options */ + OPT_PROTO_REGISTER_NOSCREENNAME | OPT_PROTO_UNIQUE_CHATNAME | OPT_PROTO_IM_IMAGE | OPT_PROTO_INVITE_MESSAGE, /* options */ NULL, /* user_splits */ NULL, /* protocol_options */ { /* icon_spec */ @@ -692,7 +690,7 @@ mxit_set_status, /* set_status */ NULL, /* set_idle */ NULL, /* change_passwd */ - mxit_add_buddy, /* add_buddy [roster.c] */ + NULL, /* add_buddy [roster.c] */ NULL, /* add_buddies */ mxit_remove_buddy, /* remove_buddy [roster.c] */ NULL, /* remove_buddies */ @@ -743,7 +741,7 @@ mxit_get_moods, /* get_moods */ NULL, /* set_public_alias */ NULL, /* get_public_alias */ - NULL, /* add_buddy_with_invite */ + mxit_add_buddy, /* add_buddy_with_invite */ NULL /* add_buddies_with_invite */ }; diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/mxit/mxit.h --- a/libpurple/protocols/mxit/mxit.h Thu May 05 03:40:29 2011 +0000 +++ b/libpurple/protocols/mxit/mxit.h Mon May 09 04:26:46 2011 +0000 @@ -107,6 +107,10 @@ #define MXIT_FLAG_FIRSTROSTER 0x04 /* set to true once the first roster update has been received and processed */ +/* Maximum number of search results */ +#define MXIT_SEARCHRESULTS_MAX 30 + + /* define this to enable the link clicking support */ #define MXIT_LINK_CLICK @@ -162,7 +166,8 @@ struct tx_queue queue; /* transmit packet queue (FIFO mode) */ gint64 last_tx; /* timestamp of last packet sent */ int outack; /* outstanding ack packet */ - guint q_timer; /* timer handler for managing queue */ + guint q_slow_timer_id; /* timer handle for slow tx queue */ + guint q_fast_timer_id; /* timer handle for fast tx queue */ /* receive */ char rx_lbuf[16]; /* receive byte buffer (socket packet length) */ @@ -172,6 +177,7 @@ char rx_state; /* current receiver state */ gint64 last_rx; /* timestamp of last packet received */ GList* active_chats; /* list of all our contacts we received messages from (active chats) */ + GList* invites; /* list of all the invites that we have received */ /* groupchat */ GList* rooms; /* active groupchat rooms */ diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/mxit/profile.c --- a/libpurple/protocols/mxit/profile.c Thu May 05 03:40:29 2011 +0000 +++ b/libpurple/protocols/mxit/profile.c Mon May 09 04:26:46 2011 +0000 @@ -23,6 +23,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ +#define _XOPEN_SOURCE +#include + #include "internal.h" #include "purple.h" @@ -34,7 +37,7 @@ /*------------------------------------------------------------------------ * Returns true if it is a valid date. * - * @param bday Date-of-Birth string + * @param bday Date-of-Birth string (YYYY-MM-DD) * @return TRUE if valid, else FALSE */ gboolean validateDate( const char* bday ) @@ -101,6 +104,40 @@ /*------------------------------------------------------------------------ + * Calculate an Age from the date-of-birth. + * + * @param date Date-of-Birth string (YYYY-MM-DD) + * @return The age + */ +static int calculateAge( const char* date ) +{ + time_t t; + struct tm now, bdate; + int age; + + if ( ( !date ) || ( strlen( date ) == 0 ) ) + return 0; + + /* current time */ + t = time(NULL); + localtime_r( &t, &now ); + + /* decode hdate */ + memset( &bdate, 0, sizeof( struct tm ) ); + purple_str_to_time(date, FALSE, &bdate, NULL, NULL); + + /* calculate difference */ + age = now.tm_year - bdate.tm_year; + if ( now.tm_mon < bdate.tm_mon ) /* is before month of birth */ + age--; + else if ( (now.tm_mon == bdate.tm_mon ) && ( now.tm_mday < bdate.tm_mday ) ) /* before birthday in current month */ + age--; + + return age; +} + + +/*------------------------------------------------------------------------ * Returns timestamp field in date & time format (DD-MM-YYYY HH:MM:SS) * * @param msecs The timestamps (milliseconds since epoch) @@ -120,9 +157,9 @@ /*------------------------------------------------------------------------ * Display the profile information. * - * @param session The MXit session object - * @param username The username who's profile information this is - * @param profile The profile + * @param session The MXit session object + * @param username The username who's profile information this is + * @param profile The profile */ void mxit_show_profile( struct MXitSession* session, const char* username, struct MXitProfile* profile ) { @@ -146,6 +183,11 @@ purple_notify_user_info_add_pair( info, _( "Last Name" ), profile->lastname ); purple_notify_user_info_add_pair( info, _( "Country" ), profile->regcountry ); + if ( strlen( profile->aboutme ) > 0 ) + purple_notify_user_info_add_pair( info, _( "About Me" ), profile->aboutme ); + if ( strlen( profile->whereami ) > 0 ) + purple_notify_user_info_add_pair( info, _( "Where I Live" ), profile->whereami ); + purple_notify_user_info_add_section_break( info ); if ( contact ) { @@ -172,7 +214,105 @@ /* hidden number */ purple_notify_user_info_add_pair( info, _( "Hidden Number" ), ( contact->flags & MXIT_CFLAG_HIDDEN ) ? _( "Yes" ) : _( "No" ) ); } + else { + /* this is an invite */ + contact = get_mxit_invite_contact( session, username ); + if ( contact ) { + /* invite found */ + + if ( contact->msg ) + purple_notify_user_info_add_pair( info, _( "Invite Message" ), contact->msg ); + + if ( contact->imgid ) { + /* this invite has a avatar */ + char* img_text; + img_text = g_strdup_printf( "", contact->imgid ); + purple_notify_user_info_add_pair( info, _( "Photo" ), img_text ); + } + + if ( contact->statusMsg ) + purple_notify_user_info_add_pair( info, _( "Status Message" ), contact->statusMsg ); + } + } purple_notify_userinfo( session->con, username, info, NULL, NULL ); purple_notify_user_info_destroy( info ); } + + +/*------------------------------------------------------------------------ + * Display the profiles of search results. + * + * @param gc The connection object + * @param row The selected row from search-results + * @param user_data NULL (unused) + */ +static void mxit_search_results_add_cb( PurpleConnection *gc, GList *row, gpointer user_data ) +{ + /* display add buddy dialog */ + purple_blist_request_add_buddy( purple_connection_get_account( gc ), g_list_nth_data( row, 0 ), NULL, g_list_nth_data( row, 1 ) ); +} + + +/*------------------------------------------------------------------------ + * Display the profiles of search results. + * + * @param session The MXit session object + * @param searchType The type of search (CP_SUGGEST_*) + * @param maxResults The maximum number of results + * @param entries The list of profile entries + */ +void mxit_show_search_results( struct MXitSession* session, int searchType, int maxResults, GList* entries ) +{ + PurpleNotifySearchResults* results; + PurpleNotifySearchColumn* column; + gchar* text; + + if ( !entries ) { + mxit_popup( PURPLE_NOTIFY_MSG_INFO, _( "No results" ), _( "No contacts found." ) ); + return; + } + + results = purple_notify_searchresults_new(); + if ( !results ) + return; + + /* define columns */ + column = purple_notify_searchresults_column_new( _( "UserId" ) ); + purple_notify_searchresults_column_add( results, column ); + column = purple_notify_searchresults_column_new( _( "Display Name" ) ); + purple_notify_searchresults_column_add( results, column ); + column = purple_notify_searchresults_column_new( _( "Gender" ) ); + purple_notify_searchresults_column_add( results, column ); + column = purple_notify_searchresults_column_new( _( "Age" ) ); + purple_notify_searchresults_column_add( results, column ); + column = purple_notify_searchresults_column_new( _( "Where I live" ) ); + purple_notify_searchresults_column_add( results, column ); + + while (entries != NULL) { + struct MXitProfile* profile = ( struct MXitProfile *) entries->data; + GList* row; + + /* column values */ + row = g_list_append( NULL, g_strdup( profile->userid ) ); + row = g_list_append( row, g_strdup( profile->nickname ) ); + row = g_list_append( row, g_strdup( profile->male ? "Male" : "Female" ) ); + row = g_list_append( row, g_strdup_printf( "%i", calculateAge( profile->birthday ) ) ); + row = g_list_append( row, g_strdup( profile->whereami ) ); + + purple_notify_searchresults_row_add( results, row ); + entries = g_list_next( entries ); + } + + /* button */ + purple_notify_searchresults_button_add( results, PURPLE_NOTIFY_BUTTON_INVITE, mxit_search_results_add_cb ); + + if ( searchType == CP_SUGGEST_FRIENDS ) + text = g_strdup_printf( _( "You have %i suggested friends." ), maxResults ); + else + text = g_strdup_printf( _( "We found %i contacts that match your search." ), maxResults ); + + purple_notify_searchresults( session->con, NULL, text, NULL, results, NULL, NULL ); + + g_free( text); +} diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/mxit/profile.h --- a/libpurple/protocols/mxit/profile.h Thu May 05 03:40:29 2011 +0000 +++ b/libpurple/protocols/mxit/profile.h Mon May 09 04:26:46 2011 +0000 @@ -32,26 +32,30 @@ struct MXitProfile { /* required */ char loginname[64]; /* name user uses to log into MXit with (aka 'mxitid') */ - char nickname[64]; /* user's own display name (aka 'nickname', aka 'fullname', aka 'alias') in MXit */ + char userid[51]; /* internal UserId (only in search results) */ + char nickname[101]; /* user's own display name (aka 'display name', aka 'fullname', aka 'alias') in MXit */ char birthday[16]; /* user's birthday "YYYY-MM-DD" */ gboolean male; /* true if the user's gender is male (otherwise female) */ char pin[16]; /* user's password */ /* optional */ - char title[32]; /* user's title */ - char firstname[64]; /* user's first name */ - char lastname[64]; /* user's last name (aka 'surname') */ - char email[64]; /* user's email address */ + char title[21]; /* user's title */ + char firstname[51]; /* user's first name */ + char lastname[51]; /* user's last name (aka 'surname') */ + char email[201]; /* user's email address */ char mobilenr[21]; /* user's mobile number */ char regcountry[3]; /* user's registered country code */ - gint64 flags; /* user's profile flags */ + char whereami[51]; /* where am I / where I live */ + char aboutme[513]; /* about me */ + + int flags; /* user's profile flags */ gint64 lastonline; /* user's last-online timestamp */ - - gboolean hidden; /* set if the user's msisdn should remain hidden */ + gboolean hidden; /* set if the user's mxitid should remain hidden */ }; struct MXitSession; void mxit_show_profile( struct MXitSession* session, const char* username, struct MXitProfile* profile ); +void mxit_show_search_results( struct MXitSession* session, int searchType, int maxResults, GList* entries ); gboolean validateDate( const char* bday ); diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/mxit/protocol.c --- a/libpurple/protocols/mxit/protocol.c Thu May 05 03:40:29 2011 +0000 +++ b/libpurple/protocols/mxit/protocol.c Mon May 09 04:26:46 2011 +0000 @@ -535,28 +535,31 @@ return; } - /* + /* * the mxit server has flood detection and it prevents you from sending messages to fast. * this is a self defense mechanism, a very annoying feature. so the client must ensure that * it does not send messages too fast otherwise mxit will ignore the user for 30 seconds. * this is what we are trying to avoid here.. */ - if ( session->last_tx > ( now - MXIT_TX_DELAY ) ) { - /* we need to wait a little before sending the next packet, so schedule a wakeup call */ - gint64 tdiff = now - ( session->last_tx ); - guint delay = ( MXIT_TX_DELAY - tdiff ) + 9; - if ( delay <= 0 ) - delay = MXIT_TX_DELAY; - purple_timeout_add( delay, mxit_manage_queue_fast, session ); - } - else { - /* get the next packet from the queue to send */ - packet = pop_tx_packet( session ); - if ( packet != NULL ) { - /* there was a packet waiting to be sent to the server, now is the time to do something about it */ - - /* send the packet to MXit server */ - mxit_send_packet( session, packet ); + if ( session->q_fast_timer_id == 0 ) { + /* the fast timer has not been set yet */ + if ( session->last_tx > ( now - MXIT_TX_DELAY ) ) { + /* we need to wait a little before sending the next packet, so schedule a wakeup call */ + gint64 tdiff = now - ( session->last_tx ); + guint delay = ( MXIT_TX_DELAY - tdiff ) + 9; + if ( delay <= 0 ) + delay = MXIT_TX_DELAY; + session->q_fast_timer_id = purple_timeout_add( delay, mxit_manage_queue_fast, session ); + } + else { + /* get the next packet from the queue to send */ + packet = pop_tx_packet( session ); + if ( packet != NULL ) { + /* there was a packet waiting to be sent to the server, now is the time to do something about it */ + + /* send the packet to MXit server */ + mxit_send_packet( session, packet ); + } } } } @@ -587,6 +590,7 @@ { struct MXitSession* session = (struct MXitSession*) user_data; + session->q_fast_timer_id = 0; mxit_manage_queue( session ); /* stop running */ @@ -713,7 +717,7 @@ "ms=%s%c%s%c%i%c%s%c" /* "ms"=password\1version\1maxreplyLen\1name\1 */ "%s%c%i%c%s%c%s%c" /* dateOfBirth\1gender\1location\1capabilities\1 */ "%s%c%i%c%s%c%s" /* dc\1features\1dialingcode\1locale */ - "%c%i%c%i", /* \1protocolVer\1lastRosterUpdate */ + "%c%i%c%i", /* \1protocolVer\1lastRosterUpdate */ session->encpwd, CP_FLD_TERM, clientVersion, CP_FLD_TERM, CP_MAX_FILESIZE, CP_FLD_TERM, profile->nickname, CP_FLD_TERM, profile->birthday, CP_FLD_TERM, ( profile->male ) ? 1 : 0, CP_FLD_TERM, MXIT_DEFAULT_LOC, CP_FLD_TERM, MXIT_CP_CAP, CP_FLD_TERM, session->distcode, CP_FLD_TERM, features, CP_FLD_TERM, session->dialcode, CP_FLD_TERM, locale, @@ -844,16 +848,17 @@ * @param session The MXit session object * @param password The new password to be used for logging in (optional) * @param nr_attrib The number of attributes - * @param attributes String containing the attributes and settings seperated by '0x01' + * @param attributes String containing the attribute-name, attribute-type and value (seperated by '\01') */ void mxit_send_extprofile_update( struct MXitSession* session, const char* password, unsigned int nr_attrib, const char* attributes ) { char data[CP_MAX_PACKET]; - gchar** parts; + gchar** parts = NULL; int datalen; unsigned int i; - parts = g_strsplit( attributes, "\01", ( MXIT_MAX_ATTRIBS * 3 ) ); + if ( attributes ) + parts = g_strsplit( attributes, "\01", 1 + ( nr_attrib * 3 ) ); /* convert the packet to a byte stream */ datalen = snprintf( data, sizeof( data ), @@ -880,7 +885,7 @@ * @param session The MXit session object * @param max Maximum number of results to return * @param nr_attribs Number of attributes being requested - * @param attribute The names of the attributes + * @param attribute The names of the attributes */ void mxit_send_suggest_friends( struct MXitSession* session, int max, unsigned int nr_attrib, const char* attribute[] ) { @@ -890,8 +895,8 @@ /* convert the packet to a byte stream */ datalen = snprintf( data, sizeof( data ), - "ms=%i%c%s%c%i%c%i", /* inputType \1 input \ 1 maxSuggestions \1 numAttributes \1 name0 ... \1 nameN */ - CP_SUGGEST_FRIENDS, CP_FLD_TERM, "", CP_FLD_TERM, max, CP_FLD_TERM, nr_attrib ); + "ms=%i%c%s%c%i%c%i%c%i", /* inputType \1 input \1 maxSuggestions \1 startIndex \1 numAttributes \1 name0 \1 name1 ... \1 nameN */ + CP_SUGGEST_FRIENDS, CP_FLD_TERM, "", CP_FLD_TERM, max, CP_FLD_TERM, 0, CP_FLD_TERM, nr_attrib ); /* add attributes */ for ( i = 0; i < nr_attrib; i++ ) @@ -919,8 +924,8 @@ /* convert the packet to a byte stream */ datalen = snprintf( data, sizeof( data ), - "ms=%i%c%s%c%i%c%i", /* inputType \1 input \ 1 maxSuggestions \1 numAttributes \1 name0 ... \1 nameN */ - CP_SUGGEST_SEARCH, CP_FLD_TERM, text, CP_FLD_TERM, max, CP_FLD_TERM, nr_attrib ); + "ms=%i%c%s%c%i%c%i%c%i", /* inputType \1 input \1 maxSuggestions \1 startIndex \1 numAttributes \1 name0 \1 name1 ... \1 nameN */ + CP_SUGGEST_SEARCH, CP_FLD_TERM, text, CP_FLD_TERM, max, CP_FLD_TERM, 0, CP_FLD_TERM, nr_attrib ); /* add attributes */ for ( i = 0; i < nr_attrib; i++ ) @@ -985,19 +990,23 @@ * * @param session The MXit session object * @param username The username of the contact being invited + * @param mxitid Indicates the username is a MXitId. * @param alias Our alias for the contact * @param groupname Group in which contact should be stored. + * @param message Invite message */ -void mxit_send_invite( struct MXitSession* session, const char* username, const char* alias, const char* groupname ) +void mxit_send_invite( struct MXitSession* session, const char* username, gboolean mxitid, const char* alias, const char* groupname, const char* message ) { char data[CP_MAX_PACKET]; int datalen; /* convert the packet to a byte stream */ datalen = snprintf( data, sizeof( data ), - "ms=%s%c%s%c%s%c%i%c%s", /* "ms"=group\1username\1alias\1type\1msg */ + "ms=%s%c%s%c%s%c%i%c%s%c%i", /* "ms"=group \1 username \1 alias \1 type \1 msg \1 isuserid */ groupname, CP_FLD_TERM, username, CP_FLD_TERM, alias, - CP_FLD_TERM, MXIT_TYPE_MXIT, CP_FLD_TERM, "" + CP_FLD_TERM, MXIT_TYPE_MXIT, CP_FLD_TERM, + ( message ? message : "" ), CP_FLD_TERM, + ( mxitid ? 0 : 1 ) ); /* queue packet for transmission */ @@ -1441,7 +1450,7 @@ const char* statusmsg; const char* profilelist[] = { CP_PROFILE_BIRTHDATE, CP_PROFILE_GENDER, CP_PROFILE_HIDENUMBER, CP_PROFILE_FULLNAME, CP_PROFILE_TITLE, CP_PROFILE_FIRSTNAME, CP_PROFILE_LASTNAME, CP_PROFILE_EMAIL, - CP_PROFILE_MOBILENR, CP_PROFILE_FLAGS }; + CP_PROFILE_MOBILENR, CP_PROFILE_WHEREAMI, CP_PROFILE_ABOUTME, CP_PROFILE_FLAGS }; purple_account_set_int( session->acc, MXIT_CONFIG_STATE, MXIT_STATE_LOGIN ); @@ -1459,7 +1468,7 @@ session->http_sesid = atoi( records[0]->fields[0]->data ); } - /* extract MXitId (from protocol 5.9) */ + /* extract UserId (from protocol 5.9) */ if ( records[1]->fcount >= 9 ) session->uid = g_strdup( records[1]->fields[8]->data ); @@ -1624,10 +1633,9 @@ if ( rec->fcount >= 5 ) { /* there is a personal invite message attached */ - contact->msg = strdup( rec->fields[4]->data ); + if ( ( rec->fields[4]->data ) && ( strlen( rec->fields[4]->data ) > 0 ) ) + contact->msg = strdup( rec->fields[4]->data ); } - else - contact->msg = NULL; /* handle the subscription */ if ( contact-> type == MXIT_TYPE_MULTIMX ) { /* subscription to a MultiMX room */ @@ -1850,6 +1858,14 @@ /* last seen online */ profile->lastonline = strtoll( fvalue, NULL, 10 ); } + else if ( strcmp( CP_PROFILE_WHEREAMI, fname ) == 0 ) { + /* where am I */ + g_strlcpy( profile->whereami, fvalue, sizeof( profile->whereami ) ); + } + else if ( strcmp( CP_PROFILE_ABOUTME, fname ) == 0) { + /* about me */ + g_strlcpy( profile->aboutme, fvalue, sizeof( profile->aboutme ) ); + } else { /* invalid profile attribute */ purple_debug_error( MXIT_PLUGIN_ID, "Invalid profile attribute received '%s' \n", fname ); @@ -1857,18 +1873,127 @@ } if ( profile != session->profile ) { - /* update avatar (if necessary) */ - if ( avatarId ) - mxit_update_buddy_avatar( session, mxitId, avatarId ); - - /* if this is not our profile, just display it */ - mxit_show_profile( session, mxitId, profile ); - g_free( profile ); + /* not our own profile */ + struct contact* contact = NULL; + + contact = get_mxit_invite_contact( session, mxitId ); + if ( contact ) { + /* this is an invite, so update its profile info */ + if ( ( statusMsg ) && ( strlen( statusMsg ) > 0 ) ) { + /* update the status message */ + if ( contact->statusMsg ) + g_free( contact->statusMsg ); + contact->statusMsg = strdup( statusMsg ); + } + else + contact->statusMsg = NULL; + if ( contact->profile ) + g_free( contact->profile ); + contact->profile = profile; + if ( ( avatarId ) && ( strlen( avatarId ) > 0 ) ) { + /* avatar must be requested for this invite before we can display it */ + mxit_get_avatar( session, mxitId, avatarId ); + if ( contact->avatarId ) + g_free( contact->avatarId ); + contact->avatarId = strdup( avatarId ); + } + else { + /* display what we have */ + contact->avatarId = NULL; + mxit_show_profile( session, mxitId, profile ); + } + } + else { + /* this is a contact */ + if ( avatarId ) + mxit_update_buddy_avatar( session, mxitId, avatarId ); + mxit_show_profile( session, mxitId, profile ); + g_free( profile ); + } } } /*------------------------------------------------------------------------ + * Process a received suggest-contacts packet. + * + * @param session The MXit session object + * @param records The packet's data records + * @param rcount The number of data records + */ +static void mxit_parse_cmd_suggestcontacts( struct MXitSession* session, struct record** records, int rcount ) +{ + GList* entries = NULL; + int searchType; + int maxResults; + int count; + int i; + + /* + * searchType \1 numSuggestions \1 total \1 numAttributes \1 name0 \1 name1 \1 ... \1 nameN \0 + * userid \1 contactType \1 value0 \1 value1 ... valueN \0 + * ... + * userid \1 contactType \1 value0 \1 value1 ... valueN + */ + + /* the type of results */ + searchType = atoi( records[0]->fields[0]->data ); + + /* the maximum number of results */ + maxResults = atoi( records[0]->fields[2]->data ); + + /* set the count for attributes */ + count = atoi( records[0]->fields[3]->data ); + + for ( i = 1; i < rcount; i ++ ) { + struct record* rec = records[i]; + struct MXitProfile* profile = g_new0( struct MXitProfile, 1 ); + int j; + + g_strlcpy( profile->userid, rec->fields[0]->data, sizeof( profile->userid ) ); + // TODO: ContactType - User or Service + + for ( j = 0; j < count; j++ ) { + char* fname; + char* fvalue = ""; + + fname = records[0]->fields[4 + j]->data; /* field name */ + if ( records[i]->fcount > ( 2 + j ) ) + fvalue = records[i]->fields[2 + j]->data; /* field value */ + + purple_debug_info( MXIT_PLUGIN_ID, " %s: field='%s' value='%s'\n", profile->userid, fname, fvalue ); + + if ( strcmp( CP_PROFILE_BIRTHDATE, fname ) == 0 ) { + /* birthdate */ + g_strlcpy( profile->birthday, fvalue, sizeof( profile->birthday ) ); + } + else if ( strcmp( CP_PROFILE_GENDER, fname ) == 0 ) { + /* gender */ + profile->male = ( fvalue[0] == '1' ); + } + else if ( strcmp( CP_PROFILE_FULLNAME, fname ) == 0 ) { + /* nickname */ + g_strlcpy( profile->nickname, fvalue, sizeof( profile->nickname ) ); + } + else if ( strcmp( CP_PROFILE_WHEREAMI, fname ) == 0 ) { + /* where am I */ + g_strlcpy( profile->whereami, fvalue, sizeof( profile->whereami ) ); + } + /* ignore other attibutes */ + } + + entries = g_list_append( entries, profile ); + } + + /* display */ + mxit_show_search_results( session, searchType, maxResults, entries ); + + /* cleanup */ + g_list_foreach( entries, (GFunc)g_free, NULL ); +} + + +/*------------------------------------------------------------------------ * Return the length of a multimedia chunk * * @return The actual chunk data length in bytes @@ -1960,17 +2085,27 @@ case CP_CHUNK_GET_AVATAR : /* get avatars */ { struct getavatar_chunk chunk; + struct contact* contact = NULL; /* decode the chunked data */ - memset( &chunk, 0, sizeof ( struct getavatar_chunk ) ); + memset( &chunk, 0, sizeof( struct getavatar_chunk ) ); mxit_chunk_parse_get_avatar( &records[0]->fields[0]->data[sizeof( char ) + sizeof( int )], records[0]->fields[0]->len, &chunk ); /* update avatar image */ if ( chunk.data ) { purple_debug_info( MXIT_PLUGIN_ID, "updating avatar for contact '%s'\n", chunk.mxitid ); - purple_buddy_icons_set_for_user( session->acc, chunk.mxitid, g_memdup( chunk.data, chunk.length), chunk.length, chunk.avatarid ); + + contact = get_mxit_invite_contact( session, chunk.mxitid ); + if ( contact ) { + /* this is an invite (add image to the internal image store) */ + contact->imgid = purple_imgstore_add_with_id( chunk.data, chunk.length, NULL ); + mxit_show_profile( session, chunk.mxitid, contact->profile ); + } + else { + /* this is a contact's avatar, so update it */ + purple_buddy_icons_set_for_user( session->acc, chunk.mxitid, g_memdup( chunk.data, chunk.length), chunk.length, chunk.avatarid ); + } } - } break; @@ -1979,7 +2114,18 @@ break; case CP_CHUNK_DIRECT_SND : - /* this is a ack for a file send. no action is required */ + /* this is a ack for a file send. */ + { + struct sendfile_chunk chunk; + + memset( &chunk, 0, sizeof( struct sendfile_chunk ) ); + mxit_chunk_parse_sendfile( &records[0]->fields[0]->data[sizeof( char ) + sizeof( int )], records[0]->fields[0]->len, &chunk ); + + purple_debug_info( MXIT_PLUGIN_ID, "file-send send to '%s' [status=%i message='%s']\n", chunk.username, chunk.status, chunk.statusmsg ); + + if ( chunk.status != 0 ) /* not success */ + mxit_popup( PURPLE_NOTIFY_MSG_ERROR, _( "File Send Failed" ), chunk.statusmsg ); + } break; case CP_CHUNK_RECEIVED : @@ -2119,6 +2265,11 @@ mxit_parse_cmd_extprofile( session, &packet->records[2], packet->rcount - 2 ); break; + case CP_CMD_SUGGESTCONTACTS : + /* suggest contacts */ + mxit_parse_cmd_suggestcontacts( session, &packet->records[2], packet->rcount - 2 ); + break; + case CP_CMD_MOOD : /* mood update */ case CP_CMD_UPDATE : @@ -2145,6 +2296,7 @@ /* HTTP poll reply */ case CP_CMD_EXTPROFILE_SET : /* profile update */ + // TODO: Protocol 6.2 indicates status for each attribute, and current value. case CP_CMD_SPLASHCLICK : /* splash-screen clickthrough */ case CP_CMD_MSGEVENT : @@ -2637,9 +2789,13 @@ if ( session->http_timer_id > 0 ) purple_timeout_remove( session->http_timer_id ); - /* remove queue manager timer */ - if ( session->q_timer > 0 ) - purple_timeout_remove( session->q_timer ); + /* remove slow queue manager timer */ + if ( session->q_slow_timer_id > 0 ) + purple_timeout_remove( session->q_slow_timer_id ); + + /* remove fast queue manager timer */ + if ( session->q_fast_timer_id > 0 ) + purple_timeout_remove( session->q_fast_timer_id ); /* remove all groupchat rooms */ while ( session->rooms != NULL ) { @@ -2663,6 +2819,23 @@ g_list_free( session->active_chats ); session->active_chats = NULL; + /* clear the internal invites */ + while ( session->invites != NULL ) { + struct contact* contact = (struct contact*) session->invites->data; + + session->invites = g_list_remove( session->invites, contact ); + + if ( contact->msg ) + g_free( contact->msg ); + if ( contact->statusMsg ) + g_free( contact->statusMsg ); + if ( contact->profile ) + g_free( contact->profile ); + g_free( contact ); + } + g_list_free( session->invites ); + session->invites = NULL; + /* free profile information */ if ( session->profile ) free( session->profile ); diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/mxit/protocol.h --- a/libpurple/protocols/mxit/protocol.h Thu May 05 03:40:29 2011 +0000 +++ b/libpurple/protocols/mxit/protocol.h Mon May 09 04:26:46 2011 +0000 @@ -91,7 +91,7 @@ #define MXIT_CP_ARCH "Y" /* client architecture series (Y not for Yoda but for PC-client) */ #define MXIT_CLIENT_ID "LP" /* client ID as specified by MXit */ #define MXIT_CP_PLATFORM "PURPLE" /* client platform */ -#define MXIT_CP_PROTO_VESION 60 /* client protocol version */ +#define MXIT_CP_PROTO_VESION 63 /* client protocol version */ /* set operating system name */ #if defined( __APPLE__ ) @@ -110,7 +110,6 @@ /* Client settings */ #define MAX_QUEUE_SIZE ( 1 << 5 ) /* tx queue size (32 packets) */ #define MXIT_POPUP_WIN_NAME "MXit Notification" /* popup window name */ -#define MXIT_MAX_ATTRIBS 10 /* maximum profile attributes supported */ #define MXIT_DEFAULT_LOCALE "en" /* default locale setting */ #define MXIT_DEFAULT_LOC "planetpurple" /* the default location for registration */ @@ -194,14 +193,19 @@ #define CP_PROFILE_REGCOUNTRY "registeredcountry" /* Registered Country Code (UTF8 String) */ #define CP_PROFILE_FLAGS "flags" /* Profile flags (Bitset) */ #define CP_PROFILE_LASTSEEN "lastseen" /* Last-Online timestamp */ +#define CP_PROFILE_WHEREAMI "whereami" /* Where am I / Where I live */ +#define CP_PROFILE_ABOUTME "aboutme" /* About me */ /* extended profile field types */ -#define CP_PROFILE_TYPE_BOOL 0x02 /* boolean profile attribute type */ -#define CP_PROFILE_TYPE_INT 0x05 /* integer profile attribute type */ -#define CP_PROFILE_TYPE_UTF8 0x0A /* UTF8 string profile attribute type */ -#define CP_PROFILE_TYPE_DATE 0x0B /* date-time profile attribute type */ +#define CP_PROFILE_TYPE_BOOL 0x02 /* boolean (0 or 1) */ +#define CP_PROFILE_TYPE_INT 0x05 /* integer (32-bit) */ +#define CP_PROFILE_TYPE_LONG 0x06 /* long (64-bit) */ +#define CP_PROFILE_TYPE_UTF8 0x0A /* UTF8 string */ +#define CP_PROFILE_TYPE_DATE 0x0B /* date-time (ISO 8601 format) */ /* profile flags */ +#define CP_PROF_NOT_SEARCHABLE 0x02 /* user cannot be searched for */ +#define CP_PROF_NOT_SUGGESTABLE 0x08 /* user cannot be suggested as friend */ #define CP_PROF_DOBLOCKED 0x40 /* date-of-birth cannot be changed */ /* suggestion types */ @@ -305,7 +309,7 @@ void mxit_send_suggest_friends( struct MXitSession* session, int max, unsigned int nr_attrib, const char* attribute[] ); void mxit_send_suggest_search( struct MXitSession* session, int max, const char* text, unsigned int nr_attrib, const char* attribute[] ); -void mxit_send_invite( struct MXitSession* session, const char* username, const char* alias, const char* groupname ); +void mxit_send_invite( struct MXitSession* session, const char* username, gboolean mxitid, const char* alias, const char* groupname, const char* message ); void mxit_send_remove( struct MXitSession* session, const char* username ); void mxit_send_allow_sub( struct MXitSession* session, const char* username, const char* alias ); void mxit_send_deny_sub( struct MXitSession* session, const char* username ); diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/mxit/roster.c --- a/libpurple/protocols/mxit/roster.c Thu May 05 03:40:29 2011 +0000 +++ b/libpurple/protocols/mxit/roster.c Mon May 09 04:26:46 2011 +0000 @@ -564,8 +564,8 @@ buddy = g_slist_nth_data( list, i ); if ( !purple_buddy_get_protocol_data( buddy ) ) { - const gchar *alias = purple_buddy_get_alias( buddy ); - const gchar *name = purple_buddy_get_name( buddy ); + const gchar* alias = purple_buddy_get_alias( buddy ); + const gchar* name = purple_buddy_get_name( buddy ); /* this buddy should be removed, because we did not receive him in our roster update from MXit */ purple_debug_info( MXIT_PLUGIN_ID, "Removed 'old' buddy from the blist '%s' (%s)\n", alias, name ); @@ -592,9 +592,16 @@ /* send a allow subscription packet to MXit */ mxit_send_allow_sub( invite->session, invite->contact->username, invite->contact->alias ); + /* remove the invite from our internal invites list */ + invite->session->invites = g_list_remove( invite->session->invites, invite->contact ); + /* freeup invite object */ if ( invite->contact->msg ) g_free( invite->contact->msg ); + if ( invite->contact->statusMsg ) + g_free( invite->contact->statusMsg ); + if ( invite->contact->profile ) + g_free( invite->contact->profile ); g_free( invite->contact ); g_free( invite ); } @@ -614,9 +621,16 @@ /* send a deny subscription packet to MXit */ mxit_send_deny_sub( invite->session, invite->contact->username ); + /* remove the invite from our internal invites list */ + invite->session->invites = g_list_remove( invite->session->invites, invite->contact ); + /* freeup invite object */ if ( invite->contact->msg ) g_free( invite->contact->msg ); + if ( invite->contact->statusMsg ) + g_free( invite->contact->statusMsg ); + if ( invite->contact->profile ) + g_free( invite->contact->profile ); g_free( invite->contact ); g_free( invite ); } @@ -639,12 +653,42 @@ invite->session = session; invite->contact = contact; + /* add the invite to our internal invites list */ + invite->session->invites = g_list_append( invite->session->invites, invite->contact ); + /* (reference: "libpurple/account.h") */ purple_account_request_authorization( session->acc, contact->username, NULL, contact->alias, contact->msg, FALSE, mxit_cb_buddy_auth, mxit_cb_buddy_deny, invite ); } /*------------------------------------------------------------------------ + * Return the contact object for a mxit invite + * + * @param session The MXit session object + * @param username The username of the contact + * @return The contact object for the inviting user + */ +struct contact* get_mxit_invite_contact( struct MXitSession* session, const char* username ) +{ + struct contact* con = NULL; + struct contact* match = NULL; + int i; + + /* run through all the invites and try and find the match */ + for ( i = 0; i < g_list_length( session->invites ); i++ ) { + con = g_list_nth_data( session->invites, i ); + if ( strcmp( con->username, username ) == 0 ) { + /* invite found */ + match = con; + break; + } + } + + return match; +} + + +/*------------------------------------------------------------------------ * Return TRUE if this is a MXit Chatroom contact. * * @param session The MXit session object @@ -680,8 +724,9 @@ * @param gc The connection object * @param buddy The new buddy * @param group The group of the new buddy + * @param message The invite message */ -void mxit_add_buddy( PurpleConnection* gc, PurpleBuddy* buddy, PurpleGroup* group ) +void mxit_add_buddy( PurpleConnection* gc, PurpleBuddy* buddy, PurpleGroup* group, const char* message ) { struct MXitSession* session = (struct MXitSession*) gc->proto_data; GSList* list = NULL; @@ -702,7 +747,7 @@ * you accept an invite. so in that case the user is already * in our blist and ready to be chatted to. */ - mxit_send_invite( session, buddy_name, buddy_alias, group_name ); + mxit_send_invite( session, buddy_name, TRUE, buddy_alias, group_name, message ); } else { purple_debug_info( MXIT_PLUGIN_ID, "mxit_add_buddy (scenario 2) (list:%i)\n", g_slist_length( list ) ); diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/mxit/roster.h --- a/libpurple/protocols/mxit/roster.h Thu May 05 03:40:29 2011 +0000 +++ b/libpurple/protocols/mxit/roster.h Mon May 09 04:26:46 2011 +0000 @@ -121,6 +121,10 @@ char customMood[16]; /* custom mood */ char* statusMsg; /* status message */ char* avatarId; /* avatarId */ + + /* invites only */ + void* profile; /* user's profile (if available) */ + int imgid; /* avatar image id in the imgstore */ }; /* Presence / Status */ @@ -140,9 +144,10 @@ void mxit_new_subscription( struct MXitSession* session, struct contact* contact ); void mxit_update_blist( struct MXitSession* session ); gboolean is_mxit_chatroom_contact( struct MXitSession* session, const char* username ); +struct contact* get_mxit_invite_contact( struct MXitSession* session, const char* username ); /* libPurple callbacks */ -void mxit_add_buddy( PurpleConnection* gc, PurpleBuddy* buddy, PurpleGroup* group ); +void mxit_add_buddy( PurpleConnection* gc, PurpleBuddy* buddy, PurpleGroup* group, const char* message ); void mxit_remove_buddy( PurpleConnection* gc, PurpleBuddy* buddy, PurpleGroup* group ); void mxit_buddy_alias( PurpleConnection* gc, const char* who, const char* alias ); void mxit_buddy_group( PurpleConnection* gc, const char* who, const char* old_group, const char* new_group ); diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/myspace/myspace.c --- a/libpurple/protocols/myspace/myspace.c Thu May 05 03:40:29 2011 +0000 +++ b/libpurple/protocols/myspace/myspace.c Mon May 09 04:26:46 2011 +0000 @@ -377,19 +377,13 @@ static char * msim_status_text(PurpleBuddy *buddy) { - MsimSession *session; MsimUser *user; - const gchar *display_name, *headline; + const gchar *display_name = NULL, *headline = NULL; PurpleAccount *account; - PurpleConnection *gc; g_return_val_if_fail(buddy != NULL, NULL); account = purple_buddy_get_account(buddy); - gc = purple_account_get_connection(account); - session = (MsimSession *)gc->proto_data; - - display_name = headline = NULL; user = msim_get_user_from_buddy(buddy, FALSE); if (user != NULL) { @@ -859,7 +853,6 @@ msim_check_inbox_cb(MsimSession *session, const MsimMessage *reply, gpointer data) { MsimMessage *body; - guint old_inbox_status; guint i, n; /* Information for each new inbox message type. */ static struct @@ -896,8 +889,6 @@ if (body == NULL) return; - old_inbox_status = session->inbox_status; - n = 0; for (i = 0; i < G_N_ELEMENTS(message_types); ++i) { @@ -1357,7 +1348,6 @@ static gboolean msim_incoming_status(MsimSession *session, MsimMessage *msg) { - PurpleBuddyList *blist; MsimUser *user; GList *list; gchar *status_headline, *status_headline_escaped; @@ -1391,8 +1381,6 @@ 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. * TODO: Could this be responsible for #3444? */ user = msim_find_user(session, username); @@ -2026,7 +2014,6 @@ msim_input_cb(gpointer gc_uncasted, gint source, PurpleInputCondition cond) { PurpleConnection *gc; - PurpleAccount *account; MsimSession *session; gchar *end; int n; @@ -2035,7 +2022,6 @@ 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 */ @@ -3187,14 +3173,11 @@ * Actions menu for account. */ static GList * -msim_actions(PurplePlugin *plugin, gpointer context) +msim_actions(PurplePlugin *plugin, gpointer context /* PurpleConnection* */) { - PurpleConnection *gc; GList *menu; PurplePluginAction *act; - gc = (PurpleConnection *)context; - menu = NULL; #if 0 diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/myspace/user.c --- a/libpurple/protocols/myspace/user.c Thu May 05 03:40:29 2011 +0000 +++ b/libpurple/protocols/myspace/user.c Mon May 09 04:26:46 2011 +0000 @@ -565,7 +565,7 @@ { MsimMessage *body; gchar *field_name; - guint rid, cmd, dsn, lid; + guint rid, dsn, lid; g_return_if_fail(user != NULL); /* Callback can be null to not call anything, just lookup & store information. */ @@ -579,8 +579,6 @@ /* Send request */ - cmd = MSIM_CMD_GET; - if (msim_is_userid(user)) { field_name = "UserID"; dsn = MG_MYSPACE_INFO_BY_ID_DSN; @@ -602,7 +600,7 @@ g_return_if_fail(msim_send(session, "persist", MSIM_TYPE_INTEGER, 1, "sesskey", MSIM_TYPE_INTEGER, session->sesskey, - "cmd", MSIM_TYPE_INTEGER, 1, + "cmd", MSIM_TYPE_INTEGER, MSIM_CMD_GET, "dsn", MSIM_TYPE_INTEGER, dsn, "uid", MSIM_TYPE_INTEGER, session->userid, "lid", MSIM_TYPE_INTEGER, lid, diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/qq/AUTHORS --- a/libpurple/protocols/qq/AUTHORS Thu May 05 03:40:29 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -Code Contributors -========= -puzzlebird : original author -gfhuang(poppyer): patches for libpurple 2.0.0beta2, maintainer -Yuan Qingyun : patches for libpurple 1.5.0, maintainer -henryouly : file transfer, udp sock5 proxy and qq_show, maintainer -hzhr : maintainer -joymarquis : maintainer -arfankai : fixed bugs in char_conv.c -rakescar : provided filter for HTML tag -yyw : improved performance on PPC linux -lvxiang : provided ip to location original code -markhuetsch : OpenQ merge into libpurple, maintainer 2006-2007 -ccpaging : maintainer since 2007 -icesky : maintainer since 2007 -csyfek : faces, maintainer since 2007 - -Lovely Patch Writers -========= -gnap : message displaying, documentation -manphiz : qun processing -moo : qun processing -Coly Li : qun processing -Emil Alexiev : captcha verification on login based on LumaQQ for MAC (2007), - login, add buddy, remove buddy, message exchange and logout -Chengming Wang : buddy memo -lonicerae : chat room window bugfix, server list bugfix, buddy memo - -Acknowledgement -========= -Shufeng Tan : http://sf.net/projects/perl-oicq -Jeff Ye : http://www.sinomac.com -Hu Zheng : http://forlinux.yeah.net -yunfan : http://www.myswear.net -OpenQ Team : http://openq.linuxsir.org -LumaQQ Team : http://lumaqq.linuxsir.org -Pidgin Team : http://www.pidgin.im -Huang Guan : http://home.xxsyzx.com -OpenQ Google Group : http://groups.google.com/group/openq - -Scrupulous Testers -========= -yegle -cnzhangbx -casparant -wd -x6719620 -netelk -and more, please let me know... thank you! diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/qq/ChangeLog --- a/libpurple/protocols/qq/ChangeLog Thu May 05 03:40:29 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,382 +0,0 @@ -2010.01.23 - flos - * added an option to force incoming message in chat room to use a default font instead of the font in message itself - -2010.01.18 - flos - * added type 'UPDCLS' and 'UID' for implementing business logic layer - -2010.01.13 - ccpaging - * qq2009-1 patch from ccpaging - -2009.04.23 - flos - * Fixed a bug of updating buddy who is not in user's buddy list - -2009.02.25 - flos - * Changed text 'ZipCode' to 'Postal Code' - -2009.02.24 - flos - * NEVER forget our COPYRIGHT, ;) - -2009.02.24 - flos - * Changed update_class type from gint to guint32 - * Fixed a bug of displaying of memo when memo is nothing - -2009.02.21 - flos - * Added 'qq_strlen' and 'qq_strcmp' funtions in qq.h - * Fixed compiling problems with lower version of GTK+ - -2009.02.21 - flos - * Rewrite whole buddy memo part - * Remove 'qq_to_utf8_len' and 'utf8_to_qq_len' functions in char_conv.c - * Update ChangeLog, AUTHORS - -2009.02.09 - Chengming Wang - * Rewrite buddy_memo using qq_put/qq_get series functions - -2009.02.09 - Chengming Wang - * Added buddy 'get memo', 'remove memo', 'upload memo' functions - -2009.02.08 - flos - * Fixed showing message of chat room when message comes in - -2008.12.28 - flos - * Fixes #7908 - -2008.12.28 - flos - * References #7908 - -2008.12.25 - flos - * References #7821 - * Updated authors - -2008.12.17 - flos - * Minor fixed in buddy_info.c - -2008.12.06 - flos - * Removed version checking script in Makefiles since our developers all migrated to monotone - * Use our development revision as OPENQ_VERSION in qq.c - -2008.12.05 - flos - * Fixed a bug after propagating - -2008.11.18 - ccpaging - * Fixed: IM format suuport in IM and QUN IM - * Divide long IM message into segment and sending - * Divide long QUN IM message in to segment and sending - * Add some new function in im.c to put format when sending - * Add some new function in im.c to get format when receiving - * Need improvement: - Merge long IM message when receiving. Need a buffer to store segments of long IM message. - Send segment of long IM message one by one. Need a buffer to store segments of long IM message. - -2008.11.11 - ccpaging - * Change QQ number to unsigned long - * Change Qun ID and Qun extend ID to unsigned long - * Rewrite smiley convert function, use qsort and bsearch - * Update smiley map according EVA and pidgin theme file - * Support long IM message in private and Qun - -2008.10.27 - ccpaging - * Fixed a bug in group_join.c - -2008.10.30 - flos - * Fixed a bug which made xgettext failed in buddy_info.c - * Fixed a bug in Makefile.am and Makefile.mingw - * Updated acknowledgement in qq.c - -2008.10.28 - flos - * Updated AUTHORS - -2008.10.27 - ccpaging - * Fixed a bug in buddy_info.c - -2008.10.27 - ccpaging - * Update 'buddy_adding' protocol - -2008.10.22 - ccpaging - * 20081022 - -2008.10.20 - ccpaging - * Support incoming authorization of 'buddy_adding' protocol of QQ2007/2008 - -2008.10.14 - ccpaging - * 2007 remove buddy ok - * Removed group_search.c/h - -2008.10.10 - ccpaging - * Support part of 'buddy' protocol of QQ2007/2008 - -2008.10.10 - ccpaging - * Keep group_search.c/h for later use - * Update 'group' - -2008.10.09 - ccpaging - * 20081009-1 - -2008.10.09 - ccpaging - * Update 'group' protocol - * Functions of group_find, group_free, group_search merged into group_join and group_internal - * Removed group_find.c/h, group_free.c/h, group_search.c/h - -2008.10.08 - ccpaging - * Update 'group' protocol - -2008.10.08 - ccpaging - * 20081008-1 - -2008.10.08 - ccpaging - * Update group part - * Delete some meaningless functions and data - * Added 'change my icon' - -2008.10.08 - lonicerae - * Update Makefile.mingw - -2008.10.08 - ccpaging - * Fixed QQ_BUDDY_ICON_DIR problem - -2008.10.07 - lonicerae - * Update 'version display' - -2008.10.07 - lonicerae - * Added some defensive code for 'action' series functions of qq.c - -2008.10.07 - ccpaging - * Update buddy icon - -2008.10.07 - ccpaging - * Update qq_buddy - -2008.10.07 - ccpaging - * Update qun conversation - -2008.10.05 - lonicerae - * Bug fix in 'About OpenQ' dialog - -2008.10.05 - lonicerae - * Added 'About OpenQ' dialog - -2008.10.05 - ccpaging - * Add my uid into buddy list - * Fixed a minor bug in qq_create_buddy. Not get new buddy's info. - * There are 38 fields in protocol 2008, one more than 2005/2007. - * The packet of Modifing buddy info is changed. Need sample to fix it. - -2008.10.04 - ccpaging - * Update protocol for 2007 - * Code cleanup - -2008.10.04 - lonicerae - * fixed a bug in qq_base.c - -2008.10.03 - ccpaging - * 2007 protocol: - 1. fixed 'get room info' - 2. fixed 'get buddy level' - -2008.10.02 - ccpaging - * Added 'Captcha Display' function - * QQ2007 for openq, programed by Emil Alexiev: - 1. Most functions from patch written by Emil Alexiev merged into trunk, except 'buddy operations' - 2. 'online buddy status' and 'qun buddies' still have problems - * QQ2008 console client, programed by Shrimp: - 1. 'before login' and 'keep alive' parts merged into trunk - -2008.09.30 - ccpaging - * Successfully login using 2007/2008 protocols - -2008.09.29 - ccpaging - * 'Check Password' function for protocol 2007/2008 - -2008.09.28 - ccpaging - * The source is only for debug, not for user: - 1. Implement new QQ protocol 2007/2008, include login and change status - 2. Check 2005's login reply packet, get last 3 login time. - 3. Server's notice and news is displayed in self buddy (The new buddy created in buddy list). - 4. The notice messages when adding/removing QQ Qun's buddy displayed in char conversation. They are displayed as purple notify windows in the past. - 5. The notice messages when adding/removing buddy displayed in self buddy's conversation. They are displayed as purple notify windows in the past. - 6. Client version can be selected in account option. Now only qq2005 is working, other new version is only for debug. - -2008.09.26 - ccpaging - * Added 'Request/Add/Remove Buddy' functions - -2008.09.19 - ccpaging - * Rewrite buddy modify info, there is a ticket for this problem - * Use ship32 to trans action code between request packet and reply packet process - -2008.09.15 - csyfek - * im.pidgin.pidgin.openq branch - -2008.09.05 - ccpaging - * Filter chars 0x01-0x20 in nickname - -2008.09.05 - ccpaging - * Fixed compilation even pidgin-udp-patch not applied - * Place and analysis 'before login packet' after login. packages will be updated slowly and server may send lots of 'server command packet', while 'before login packet' is placed after 'finished update' - -2008.09.02 - ccpaging - * Bugfix: can not send message to the QUN blocked adding - * Tickets: - Fixes #6957 - -2008.09.02 - ccpaging - * Use new tactics of information update: - 1. send next package till the previous package received - 2. fix duplicated get_room_info and get_room_buddies commands - -2008.08.16 - ccpaging - * Rename group to room. If you used pidginqq before, this may create a new room with same title, you may delete old one - * Replace purple_debug with purple_debug_info, purple_debug_warning, purple_debug_error - * Add server notice and server new, and two options to turn on/off - * Minor modify for reducing transaction's debug infor - * Minor modifies for system notice and QQ news. - * Add 4 new strings need translate compare with p10. - * Tickets: - Fixes #6990 - -2008.08.10 - csyfek - * Commit to Pidgin - -2008.08.07 - ccpaging - * Support managing multi-connections according to simple.c - -2008.08.06 - ccpaging - * Rename names of variables, Group, to Room - * Functions of group_network merged into qq_network and qq_process - * Cancelled managing glist of group packet, add sub_cmdd and room_id to transaction - * Fixed error of demo group: - If 'room list' and 'room infor' are not setup, response received from server will emits 'room_id = 0' packet. - -2008.08.04 - ccpaging - * Use new crypt/decrypt functions - * Rename crypt.c/h to qq_crypt.c/h - * Clean code of decrypt functions - * Fixed decryption failure - -2008.08.04 - csyfek - * Update AUTHORS - -2008.08.03 - csyfek - * Commit lost files to Pidgin - -2008.08.02 - csyfek - * Commit to Pidgin - * Tickets: - Fixes #1861 - Fixes #1902 - References #5112 - -2008.08.02 - ccpaging - * Store all keys and md5 values of qq_data in char[QQ_KEY_LENGTH] - * Use random value in inikey - * TEA header padding in crypt.c - * Rewrite login part of qq_process - -2008.07.31 - ccpaging - * Fixed: send reply when get duplicate server command. The server may not get our reply before. - * Tag custom picture as text "(Broken)" - -2008.07.30 - ccpaging , csyfek - * Change some debug message - * Modify buddy status flag according to eva for QQ2006 - * Modify buddy status parse and correspond to eva2 - * Add getIP/putIP functions to packet_parse.c, and replace some gen_ip_str - * Replace guint32 *ip with struct in_addr, and reduce g_new/g_free operation - * Source file changed: - Merge buddy_status into buddy_list - Change login_logout to qq_base - Merge keep_alive into qq_base - New qq_process extract from qq_network - * Fixed: Byte alignment bug in crypt.c, tested in ARM PDA - * Fixed: group chat message may get in before getting group info, and so group info is empty - * Add qq_send_cmd_group_get_group_info when joined a group chat in group_im.c - * Add some new group command identify according eva but further program - * Add some new QQ client version identify - * Fixed: Identify buddy's client version by IM packet, and not by status - * Add some new info in buddy's tooltip text - * Add video falg to buddy's emblem. But those flag in buddy status may not prasing correctly - * Use new timeout function to handle send keep_alive, resend packet, update buddy status - * Add new advanced options: - The end user may change interval of keep_alive, resend packet, update buddy status to feed their need. - For example, saving network flow when use mobile phone. - Keep alive packet must be sent in 60-120 seconds whatever client rcved data of not. - The intervals of keep alive and update status should be multiple of resend's interval, - Since we use counter not time() in a single timeout function for efficiency. - * Rewrite qq_trans.c, and use one g_list to manage: - Store server packet before login, and prase all of them when get login - Store client send packet for resend scanning, confirm server reply, filter duplicate server reply - Store server packet for filter out duplicate - * Add QQ_MSG_SYS_NOTICE = 0x06 in sys_msg.c - * Rewrite qq_proc_cmd_reply and qq_proc_cmd_server: - In QQ protocol, one packet reply may need a new packet send later. - We may call it packet trigger. The triggers always is hided in every qq_process_reply. - Now we try to extract those triggers and put into a single function, - and then every trigger should be obviously and easy to manage. - -2008.07.12 - ccpaging - * Fixed: Always lost connection. Now send keep alive packet in every 30 seconds - * Minor fix for debug information - * Filter \r\n and replace with SPCAE in group notive - * Fixed a memory leak - * Tickets: - * Fixes #4024. - -2008.06.29 - csyfek - * Minor bug fix - * Add some doxygen syntax for preparing development documentation - * References #6199 - -2008.06.28 - ccpaging , moo - * Patches from moo and ccpaging. - * Tickets: - * Fixes #4956. - * Fixes #2998. - -2008.06.07 - ccpaging , csyfek - * Clean code and apply patches from QuLogic - -2008.05.19 - ccpaging , csyfek - * Reconnect server 5 time in 5000 ms, when connect failed - * Rename sendqueue.c/sendqueue.h to qq_trans.c/qq_trans.h - * Rewrite packet_process - * Rewrite qq_send_cmd - * Create server list, try to connect every server when failed - -2008.05.14 - ccpaging - * Move function for before login packets storing to sendqueue - * Use transaction data structure to store before login packets - * Rewrite tcp_pending and packet_process in qq_network.c - -2008.05.09 - ccpaging - * Remove function _create_packet_head_seq in qq_network.c - * Create new function encap in qq_netowork.c - * Clean code of qq_send_packet_request_login_token and qq_send_packet_login in login_out.c - -2008.05.09 - ccpaging - * Clean code of packet_parse.c, enable PARSER_DEBUG - * Rewrite send_queue - -2008.05.08 - ccpaging - * Rewrite qq_network - * Add srv resolve function when qq_login - * Merge function _qq_common_clean in qq_proxy.c to qq_disconnect - * Move orignal qq_disconnect to qq_close - * qq_data alloc in qq_open and release in qq_close - * Network connect of QQ is created in qq_connect, and release in qq_disconnect - -2008.05.05 - ccpaging - * Merge function _qq_common_clean in qq_proxy.c to qq_disconnect - * Move orignal qq_disconnect to qq_close - * qq_data alloc in qq_open and release in qq_close - * Network connect of QQ is created in qq_connect, and release in qq_disconnect - -2008.05.05 - ccpaging - * Add qq_hex_dump function - -2008.04.25 - ccpaging , csyfek - * Rewrite read_packet and create_packet functions, use qq_put and qq_get functions instead - * New logic in accord with protocol models to handle packets, some related functions rewritten - -2008.03.24 - ccpaging - * Remove qq_crypt function in crypt.c, use qq_crypt and qq_decrypt directly - -** since pidgin-2.4.0 *** diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/qq/Makefile.am --- a/libpurple/protocols/qq/Makefile.am Thu May 05 03:40:29 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,90 +0,0 @@ -EXTRA_DIST = \ - Makefile.mingw - -pkgdir = $(libdir)/purple-$(PURPLE_MAJOR_VERSION) - -QQSOURCES = \ - buddy_info.c \ - buddy_info.h \ - buddy_memo.c \ - buddy_memo.h \ - buddy_list.c \ - buddy_list.h \ - buddy_opt.c \ - buddy_opt.h \ - char_conv.c \ - char_conv.h \ - qq_crypt.c \ - qq_crypt.h \ - file_trans.c \ - file_trans.h \ - group.c \ - group.h \ - group_internal.c \ - group_internal.h \ - group_im.c \ - group_im.h \ - group_info.c \ - group_info.h \ - group_join.c \ - group_join.h \ - group_opt.c \ - group_opt.h \ - qq_define.c \ - qq_define.h \ - im.c \ - im.h \ - qq_process.c \ - qq_process.h \ - qq_base.c \ - qq_base.h \ - packet_parse.c \ - packet_parse.h \ - qq.c \ - qq.h \ - qq_network.c \ - qq_network.h \ - send_file.c \ - send_file.h \ - qq_trans.c \ - qq_trans.h \ - utils.c \ - utils.h - -AM_CFLAGS = $(st) - -libqq_la_LDFLAGS = -module -avoid-version - -if STATIC_QQ - -st = -DPURPLE_STATIC_PRPL -noinst_LTLIBRARIES = libqq.la -libqq_la_SOURCES = $(QQSOURCES) -libqq_la_CFLAGS = $(AM_CFLAGS) - -else - -st = -noinst_LTLIBRARIES = -pkg_LTLIBRARIES = libqq.la -libqq_la_SOURCES = $(QQSOURCES) -libqq_la_LIBADD = $(GLIB_LIBS) - -endif - -# For 'make check' -noinst_LTLIBRARIES += libqq_tmp.la -libqq_tmp_la_SOURCES = $(libqq_la_SOURCES) -libqq_tmp_la_LIBADD = $(libqq_la_LIBADD) - - -# QQ_BUDDY_ICON_DIR is the path where a bunch of stock icons can be -# places for users to choose from when setting their buddy icon. We -# don't distribute those icons ourselves because of possibly copyright -# concerns, but distributions might want to put icons here. -AM_CPPFLAGS = \ - -I$(top_srcdir)/libpurple \ - -I$(top_builddir)/libpurple \ - -DQQ_BUDDY_ICON_DIR=\"$(datadir)/pixmaps/purple/buddy_icons/qq\" \ - $(DEBUG_CFLAGS) \ - $(GLIB_CFLAGS) diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/qq/Makefile.mingw --- a/libpurple/protocols/qq/Makefile.mingw Thu May 05 03:40:29 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,101 +0,0 @@ -# -# Makefile.mingw -# -# Description: Makefile for win32 (mingw) version of the QQ prpl -# - -PIDGIN_TREE_TOP := ../../.. -include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak - -TARGET = libqq -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$(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 = \ - buddy_info.c \ - buddy_list.c \ - buddy_memo.c \ - buddy_opt.c \ - char_conv.c \ - qq_crypt.c \ - file_trans.c \ - group.c \ - group_internal.c \ - group_im.c \ - group_info.c \ - group_join.c \ - group_opt.c \ - qq_define.c \ - im.c \ - packet_parse.c \ - qq.c \ - qq_base.c \ - qq_network.c \ - qq_process.c \ - qq_trans.c \ - send_file.c \ - utils.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) - -$(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) diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/qq/buddy_info.c --- a/libpurple/protocols/qq/buddy_info.c Thu May 05 03:40:29 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,898 +0,0 @@ -/** - * @file buddy_info.c - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * 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 02111-1301 USA - */ - -#include "internal.h" -#include "debug.h" -#include "notify.h" -#include "request.h" -#include "connection.h" - -#include "utils.h" -#include "packet_parse.h" -#include "buddy_list.h" -#include "buddy_info.h" -#include "char_conv.h" -#include "im.h" -#include "qq_define.h" -#include "qq_base.h" -#include "qq_network.h" - -#define QQ_HOROSCOPE_SIZE 13 -static const gchar *horoscope_names[] = { - "-", N_("Aquarius"), N_("Pisces"), N_("Aries"), N_("Taurus"), - N_("Gemini"), N_("Cancer"), N_("Leo"), N_("Virgo"), N_("Libra"), - N_("Scorpio"), N_("Sagittarius"), N_("Capricorn") -}; - -#define QQ_ZODIAC_SIZE 13 -static const gchar *zodiac_names[] = { - "-", N_("Rat"), N_("Ox"), N_("Tiger"), N_("Rabbit"), - N_("Dragon"), N_("Snake"), N_("Horse"), N_("Goat"), N_("Monkey"), - N_("Rooster"), N_("Dog"), N_("Pig") -}; - -#define QQ_BLOOD_SIZE 6 -static const gchar *blood_types[] = { - "-", "A", "B", "O", "AB", N_("Other") -}; - -#define QQ_PUBLISH_SIZE 3 -static const gchar *publish_types[] = { - N_("Visible"), N_("Friend Only"), N_("Private") -}; - -#define QQ_GENDER_SIZE 3 -static const gchar *genders[] = { - N_("Private"), - N_("Male"), - N_("Female"), -}; - -static const gchar *genders_zh[] = { - "-", - "\xc4\xd0", - "\xc5\xae", -}; - -#define QQ_FACES 134 -#define QQ_ICON_PREFIX "qq_" -#define QQ_ICON_SUFFIX ".png" - -enum { - QQ_INFO_UID = 0, QQ_INFO_NICK, QQ_INFO_COUNTRY, QQ_INFO_PROVINCE, QQ_INFO_ZIPCODE, - QQ_INFO_ADDR, QQ_INFO_TEL, QQ_INFO_AGE, QQ_INFO_GENDER, QQ_INFO_NAME, QQ_INFO_EMAIL, - QQ_INFO_PG_SN, QQ_INFO_PG_NUM, QQ_INFO_PG_SP, QQ_INFO_PG_BASE_NUM, QQ_INFO_PG_TYPE, - QQ_INFO_OCCU, QQ_INFO_HOME_PAGE, QQ_INFO_AUTH_TYPE, QQ_INFO_UNKNOW1, QQ_INFO_UNKNOW2, - QQ_INFO_FACE, QQ_INFO_MOBILE, QQ_INFO_MOBILE_TYPE, QQ_INFO_INTRO, QQ_INFO_CITY, - QQ_INFO_UNKNOW3, QQ_INFO_UNKNOW4, QQ_INFO_UNKNOW5, - QQ_INFO_IS_PUB_MOBILE, QQ_INFO_IS_PUB_CONTACT, QQ_INFO_COLLEGE, QQ_INFO_HOROSCOPE, - QQ_INFO_ZODIAC, QQ_INFO_BLOOD, QQ_INFO_SHOW, QQ_INFO_UNKNOW6, - QQ_INFO_LAST_2007, QQ_INFO_LAST -}; - -enum { - QQ_FIELD_UNUSED = 0, QQ_FIELD_BASE, QQ_FIELD_EXT, QQ_FIELD_CONTACT, QQ_FIELD_ADDR -}; - -enum { - QQ_FIELD_LABEL = 0, QQ_FIELD_STRING, QQ_FIELD_MULTI, QQ_FIELD_BOOL, QQ_FIELD_CHOICE -}; - -typedef struct { - int iclass; - int type; - char *id; - char *text; - const gchar **choice; - int choice_size; -} QQ_FIELD_INFO; - -static const QQ_FIELD_INFO field_infos[] = { - { QQ_FIELD_BASE, QQ_FIELD_STRING, "uid", N_("QQ Number"), NULL, 0 }, - { QQ_FIELD_BASE, QQ_FIELD_STRING, "nick", N_("Nickname"), NULL, 0 }, - { QQ_FIELD_ADDR, QQ_FIELD_STRING, "country", N_("Country/Region"), NULL, 0 }, - { QQ_FIELD_ADDR, QQ_FIELD_STRING, "province", N_("Province/State"), NULL, 0 }, - { QQ_FIELD_ADDR, QQ_FIELD_STRING, "zipcode", N_("Zipcode"), NULL, 0 }, - { QQ_FIELD_ADDR, QQ_FIELD_STRING, "address", N_("Address"), NULL, 0 }, - { QQ_FIELD_CONTACT, QQ_FIELD_STRING, "tel", N_("Phone Number"), NULL, 0 }, - { QQ_FIELD_BASE, QQ_FIELD_STRING, "age", N_("Age"), NULL, 0 }, - { QQ_FIELD_BASE, QQ_FIELD_CHOICE, "gender", N_("Gender"), genders, QQ_GENDER_SIZE }, - { QQ_FIELD_BASE, QQ_FIELD_STRING, "name", N_("Name"), NULL, 0 }, - { QQ_FIELD_CONTACT, QQ_FIELD_STRING, "email", N_("Email"), NULL, 0 }, - { QQ_FIELD_UNUSED, QQ_FIELD_STRING, "pg_sn", "Pager Serial Num", NULL, 0 }, - { QQ_FIELD_UNUSED, QQ_FIELD_STRING, "pg_num", "Pager Num", NULL, 0 }, - { QQ_FIELD_UNUSED, QQ_FIELD_STRING, "pg_sp", "Pager Serivce Provider", NULL, 0 }, - { QQ_FIELD_UNUSED, QQ_FIELD_STRING, "pg_sta", "Pager Station Num", NULL, 0 }, - { QQ_FIELD_UNUSED, QQ_FIELD_STRING, "pg_type", "Pager Type", NULL, 0 }, - { QQ_FIELD_BASE, QQ_FIELD_STRING, "occupation", N_("Occupation"), NULL, 0 }, - { QQ_FIELD_CONTACT, QQ_FIELD_STRING, "homepage", N_("Homepage"), NULL, 0 }, - { QQ_FIELD_BASE, QQ_FIELD_BOOL, "auth", N_("Authorize adding"), NULL, 0 }, - { QQ_FIELD_UNUSED, QQ_FIELD_STRING, "unknow1", "Unknow1", NULL, 0 }, - { QQ_FIELD_UNUSED, QQ_FIELD_STRING, "unknow2", "Unknow2", NULL, 0 }, - { QQ_FIELD_UNUSED, QQ_FIELD_STRING, "face", "Face", NULL, 0 }, - { QQ_FIELD_CONTACT, QQ_FIELD_STRING, "mobile", N_("Cellphone Number"), NULL, 0 }, - { QQ_FIELD_UNUSED, QQ_FIELD_STRING, "mobile_type", "Cellphone Type", NULL, 0 }, - { QQ_FIELD_BASE, QQ_FIELD_MULTI, "intro", N_("Personal Introduction"), NULL, 0 }, - { QQ_FIELD_ADDR, QQ_FIELD_STRING, "city", N_("City/Area"), NULL, 0 }, - { QQ_FIELD_UNUSED, QQ_FIELD_STRING, "unknow3", "Unknow3", NULL, 0 }, - { QQ_FIELD_UNUSED, QQ_FIELD_STRING, "unknow4", "Unknow4", NULL, 0 }, - { QQ_FIELD_UNUSED, QQ_FIELD_STRING, "unknow5", "Unknow5", NULL, 0 }, - { QQ_FIELD_UNUSED, QQ_FIELD_CHOICE, "pub_mobile", N_("Publish Mobile"), publish_types, QQ_PUBLISH_SIZE }, - { QQ_FIELD_CONTACT, QQ_FIELD_CHOICE, "pub_contact", N_("Publish Contact"), publish_types, QQ_PUBLISH_SIZE }, - { QQ_FIELD_EXT, QQ_FIELD_STRING, "college", N_("College"), NULL, 0 }, - { QQ_FIELD_EXT, QQ_FIELD_CHOICE, "horoscope", N_("Horoscope"), horoscope_names, QQ_HOROSCOPE_SIZE }, - { QQ_FIELD_EXT, QQ_FIELD_CHOICE, "zodiac", N_("Zodiac"), zodiac_names, QQ_ZODIAC_SIZE }, - { QQ_FIELD_EXT, QQ_FIELD_CHOICE, "blood", N_("Blood"), blood_types, QQ_BLOOD_SIZE }, - { QQ_FIELD_UNUSED, QQ_FIELD_STRING, "qq_show", "QQ Show", NULL, 0 }, - { QQ_FIELD_UNUSED, QQ_FIELD_STRING, "unknow6", "Unknow6", NULL, 0 }, - { QQ_FIELD_UNUSED, QQ_FIELD_STRING, "LAST_2005", "LAST_2005", NULL, 0 } -}; - -typedef struct _modify_info_request { - PurpleConnection *gc; - int iclass; - gchar **segments; -} modify_info_request; - -#ifdef DEBUG -static void info_debug(gchar **segments) -{ -#if 0 - int index; - gchar *utf8_str; - for (index = 0; segments[index] != NULL && index < QQ_INFO_LAST; index++) { - if (field_infos[index].type == QQ_FIELD_STRING - || field_infos[index].type == QQ_FIELD_LABEL - || field_infos[index].type == QQ_FIELD_MULTI - || index == QQ_INFO_GENDER) { - utf8_str = qq_to_utf8(segments[index], QQ_CHARSET_DEFAULT); - purple_debug_info("QQ_BUDDY_INFO", "%s: %s\n", field_infos[index].text, utf8_str); - g_free(utf8_str); - continue; - } - purple_debug_info("QQ_BUDDY_INFO", "%s: %s\n", field_infos[index].text, segments[index]); - } -#endif -} -#endif - -static void info_display_only(PurpleConnection *gc, gchar **segments) -{ - PurpleNotifyUserInfo *user_info; - gchar *utf8_value; - int index; - int choice_num; - - user_info = purple_notify_user_info_new(); - - for (index = 1; segments[index] != NULL && index < QQ_INFO_LAST; index++) { - if (field_infos[index].iclass == QQ_FIELD_UNUSED) { - continue; - } - switch (field_infos[index].type) { - case QQ_FIELD_BOOL: - purple_notify_user_info_add_pair(user_info, _(field_infos[index].text), - strtol(segments[index], NULL, 10) ? _("True") : _("False")); - break; - case QQ_FIELD_CHOICE: - choice_num = strtol(segments[index], NULL, 10); - if (choice_num < 0 || choice_num >= field_infos[index].choice_size) { - choice_num = 0; - } - - purple_notify_user_info_add_pair(user_info, _(field_infos[index].text), field_infos[index].choice[choice_num]); - break; - case QQ_FIELD_LABEL: - case QQ_FIELD_STRING: - case QQ_FIELD_MULTI: - default: - if (strlen(segments[index]) != 0) { - utf8_value = qq_to_utf8(segments[index], QQ_CHARSET_DEFAULT); - purple_notify_user_info_add_pair(user_info, _(field_infos[index].text), utf8_value); - g_free(utf8_value); - } - break; - } - } - - purple_notify_userinfo(gc, segments[0], user_info, NULL, NULL); - - purple_notify_user_info_destroy(user_info); - g_strfreev(segments); -} - -void qq_request_buddy_info(PurpleConnection *gc, UID uid, - UPDCLS update_class, int action) -{ - gchar raw_data[16] = {0}; - - g_return_if_fail(uid != 0); - - g_snprintf(raw_data, sizeof(raw_data), "%u", uid); - qq_send_cmd_mess(gc, QQ_CMD_GET_BUDDY_INFO, (guint8 *) raw_data, strlen(raw_data), - update_class, action); -} - -/* send packet to modify personal information */ -static void request_change_info(PurpleConnection *gc, gchar **segments) -{ - gint bytes = 0; - guint8 raw_data[MAX_PACKET_SIZE - 128] = {0}; - guint8 bar; - gchar *join; - - g_return_if_fail(segments != NULL); - - bar = 0x1f; - - bytes += qq_put8(raw_data + bytes, bar); - bytes += qq_put8(raw_data + bytes, bar); - - /* important! skip the first uid entry */ - join = g_strjoinv("\x1f", segments + 1); - bytes += qq_putdata(raw_data + bytes, (guint8 *)join, strlen(join)); - g_free(join); - - bytes += qq_put8(raw_data + bytes, bar); - - /* qq_show_packet("request_modify_info", raw_data, bytes); */ - qq_send_cmd(gc, QQ_CMD_UPDATE_INFO, raw_data, bytes); -} - -static void info_modify_cancel_cb(modify_info_request *info_request) -{ - g_strfreev(info_request->segments); - g_free(info_request); -} - -/* parse fields and send info packet */ -static void info_modify_ok_cb(modify_info_request *info_request, PurpleRequestFields *fields) -{ - PurpleConnection *gc; - gchar **segments; - int index; - const char *utf8_str; - gchar *value; - int choice_num; - - gc = info_request->gc; - g_return_if_fail(gc != NULL); - segments = info_request->segments; - g_return_if_fail(segments != NULL); - - for (index = 1; segments[index] != NULL && index < QQ_INFO_LAST; index++) { - if (field_infos[index].iclass == QQ_FIELD_UNUSED) { - continue; - } - if (!purple_request_fields_exists(fields, field_infos[index].id)) { - continue; - } - switch (field_infos[index].type) { - case QQ_FIELD_BOOL: - value = purple_request_fields_get_bool(fields, field_infos[index].id) - ? g_strdup("1") : g_strdup("0"); - g_free(segments[index]); - segments[index] = value; - break; - case QQ_FIELD_CHOICE: - choice_num = purple_request_fields_get_choice(fields, field_infos[index].id); - if (choice_num < 0 || choice_num >= field_infos[index].choice_size) choice_num = 0; - - if (index == QQ_INFO_GENDER) { - /* QQ Server only recept gender in Chinese */ - value = g_strdup(genders_zh[choice_num]); - } else { - value = g_strdup_printf("%d", choice_num); - } - g_free(segments[index]); - segments[index] = value; - break; - case QQ_FIELD_LABEL: - case QQ_FIELD_STRING: - case QQ_FIELD_MULTI: - default: - utf8_str = purple_request_fields_get_string(fields, field_infos[index].id); - if (utf8_str == NULL) { - value = g_strdup("-"); - } else { - value = utf8_to_qq(utf8_str, QQ_CHARSET_DEFAULT); - if (value == NULL) value = g_strdup("-"); - } - g_free(segments[index]); - segments[index] = value; - break; - } - } - request_change_info(gc, segments); - - g_strfreev(segments); - g_free(info_request); -} - -static void field_request_new(PurpleRequestFieldGroup *group, gint index, gchar **segments) -{ - PurpleRequestField *field; - gchar *utf8_value; - int choice_num; - int i; - - g_return_if_fail(index >=0 && segments[index] != NULL && index < QQ_INFO_LAST); - - switch (field_infos[index].type) { - case QQ_FIELD_STRING: - case QQ_FIELD_MULTI: - utf8_value = qq_to_utf8(segments[index], QQ_CHARSET_DEFAULT); - if (field_infos[index].type == QQ_FIELD_STRING) { - field = purple_request_field_string_new( - field_infos[index].id, _(field_infos[index].text), utf8_value, FALSE); - } else { - field = purple_request_field_string_new( - field_infos[index].id, _(field_infos[index].text), utf8_value, TRUE); - } - purple_request_field_group_add_field(group, field); - g_free(utf8_value); - break; - case QQ_FIELD_BOOL: - field = purple_request_field_bool_new( - field_infos[index].id, _(field_infos[index].text), - strtol(segments[index], NULL, 10) ? TRUE : FALSE); - purple_request_field_group_add_field(group, field); - break; - case QQ_FIELD_CHOICE: - choice_num = strtol(segments[index], NULL, 10); - if (choice_num < 0 || choice_num >= field_infos[index].choice_size) choice_num = 0; - - if (index == QQ_INFO_GENDER && strlen(segments[index]) != 0) { - for (i = 0; i < QQ_GENDER_SIZE; i++) { - if (strcmp(segments[index], genders_zh[i]) == 0) { - choice_num = i; - } - } - } - field = purple_request_field_choice_new( - field_infos[index].id, _(field_infos[index].text), choice_num); - for (i = 0; i < field_infos[index].choice_size; i++) { - purple_request_field_choice_add(field, field_infos[index].choice[i]); - } - purple_request_field_group_add_field(group, field); - break; - case QQ_FIELD_LABEL: - default: - field = purple_request_field_label_new(field_infos[index].id, segments[index]); - purple_request_field_group_add_field(group, field); - break; - } -} - -static void info_modify_dialogue(PurpleConnection *gc, gchar **segments, int iclass) -{ - PurpleRequestFieldGroup *group; - PurpleRequestFields *fields; - modify_info_request *info_request; - gchar *utf8_title, *utf8_prim; - int index; - - /* Keep one dialog once a time */ - purple_request_close_with_handle(gc); - - fields = purple_request_fields_new(); - group = purple_request_field_group_new(NULL); - purple_request_fields_add_group(fields, group); - - for (index = 1; segments[index] != NULL && index < QQ_INFO_LAST; index++) { - if (field_infos[index].iclass != iclass) { - continue; - } - field_request_new(group, index, segments); - } - - switch (iclass) { - case QQ_FIELD_CONTACT: - utf8_title = g_strdup(_("Modify Contact")); - utf8_prim = g_strdup_printf("%s for %s", _("Modify Contact"), segments[0]); - break; - case QQ_FIELD_ADDR: - utf8_title = g_strdup(_("Modify Address")); - utf8_prim = g_strdup_printf("%s for %s", _("Modify Address"), segments[0]); - break; - case QQ_FIELD_EXT: - utf8_title = g_strdup(_("Modify Extended Information")); - utf8_prim = g_strdup_printf("%s for %s", _("Modify Extended Information"), segments[0]); - break; - case QQ_FIELD_BASE: - default: - utf8_title = g_strdup(_("Modify Information")); - utf8_prim = g_strdup_printf("%s for %s", _("Modify Information"), segments[0]); - break; - } - - info_request = g_new0(modify_info_request, 1); - info_request->gc = gc; - info_request->iclass = iclass; - info_request->segments = segments; - - purple_request_fields(gc, - utf8_title, - utf8_prim, - NULL, - fields, - _("Update"), G_CALLBACK(info_modify_ok_cb), - _("Cancel"), G_CALLBACK(info_modify_cancel_cb), - purple_connection_get_account(gc), NULL, NULL, - info_request); - - g_free(utf8_title); - g_free(utf8_prim); -} - -/* process the reply of modify_info packet */ -void qq_process_change_info(PurpleConnection *gc, guint8 *data, gint data_len) -{ - qq_data *qd; - g_return_if_fail(data != NULL && data_len != 0); - - qd = (qq_data *) gc->proto_data; - - data[data_len] = '\0'; - if (qd->uid != atoi((gchar *) data)) { /* return should be my uid */ - purple_debug_info("QQ", "Failed Updating info\n"); - qq_got_message(gc, _("Could not change buddy information.")); - } -} - -static void request_set_buddy_icon(PurpleConnection *gc, gint face_num) -{ - PurpleAccount *account = purple_connection_get_account(gc); - PurplePresence *presence = purple_account_get_presence(account); - qq_data *qd = (qq_data *) gc->proto_data; - gint offset; - - if(purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_INVISIBLE)) { - offset = 2; - } else if(purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_AWAY) - || purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_EXTENDED_AWAY)) { - offset = 1; - } else { - offset = 0; - } - - qd->my_icon = 3 * (face_num - 1) + offset; - qq_request_buddy_info(gc, qd->uid, 0, QQ_BUDDY_INFO_SET_ICON); -} - -void qq_change_icon_cb(PurpleConnection *gc, const char *filepath) -{ - gchar *basename; - size_t index; - gint face; - - g_return_if_fail(filepath != NULL); - - purple_debug_info("QQ", "Change my icon to %s\n", filepath); - - basename = g_path_get_basename(filepath); - index = strcspn(basename, "0123456789"); - face = strtol(basename + index, NULL, 10); - g_free(basename); - purple_debug_info("QQ", "Set face to %d\n", face); - - request_set_buddy_icon(gc, face); -} - -void qq_set_custom_icon(PurpleConnection *gc, PurpleStoredImage *img) -{ - PurpleAccount *account = purple_connection_get_account(gc); - const gchar *icon_path = purple_account_get_buddy_icon_path(account); - - g_return_if_fail(icon_path != NULL); - - /* Fixme: - * icon_path is always null - * purple_imgstore_get_filename is always new file - * QQ buddy may set custom icon if level is over 16 */ - purple_debug_info("QQ", "Change my icon to %s\n", icon_path); -} - -gchar *qq_get_icon_name(gint face) -{ - gint icon; - gchar *icon_name; - - icon = face / 3 + 1; - if (icon < 1 || icon > QQ_FACES) { - icon = 1; - } - - icon_name = g_strdup_printf("%s%d%s", QQ_ICON_PREFIX, icon, QQ_ICON_SUFFIX); - return icon_name; -} - -/* - * This function seems to let people set their buddy icon, but it restricts - * them to using a small list of stock icons. Wouldn't it make more sense - * to use libpurple's normal icon setting stuff? - * - * Also it would be nice to unify the icon_dir code for Windows and Linux. - */ -gchar *qq_get_icon_path(gchar *icon_name) -{ - gchar *icon_path; - const gchar *icon_dir; -#ifdef _WIN32 - static char *dir = NULL; - if (dir == NULL) { - dir = g_build_filename(wpurple_install_dir(), "pixmaps", - "purple", "buddy_icons", "qq", NULL); - } -#endif - - /* - * TODO: The QQ protocol plugin should probably call - * purple_prefs_add_string() at startup to initialize this - * preference. It is used to allow users or distributions - * to specify this directory. We don't include these icons - * with libpurple because of possible copyright concerns. - */ - icon_dir = purple_prefs_get_string("/plugins/prpl/qq/icon_dir"); - if ( icon_dir == NULL || strlen(icon_dir) == 0) { -#ifdef _WIN32 - icon_dir = dir; -#else - icon_dir = QQ_BUDDY_ICON_DIR; -#endif - } - icon_path = g_strdup_printf("%s%c%s", icon_dir, G_DIR_SEPARATOR, icon_name); - - return icon_path; -} - -void qq_update_buddy_icon(PurpleAccount *account, const gchar *who, gint face) -{ - PurpleBuddy *buddy; - const gchar *icon_name_prev = NULL; - gchar *icon_name; - gchar *icon_path; - gchar *icon_file_content; - gsize icon_file_size; - - g_return_if_fail(account != NULL && who != NULL); - - /* purple_debug_info("QQ", "Update %s icon to %d\n", who, face); */ - - icon_name = qq_get_icon_name(face); - g_return_if_fail(icon_name != NULL); - /* purple_debug_info("QQ", "icon file name is %s\n", icon_name); */ - - if ((buddy = purple_find_buddy(account, who))) { - icon_name_prev = purple_buddy_icons_get_checksum_for_user(buddy); - /* - purple_debug_info("QQ", "Previous icon is %s\n", - icon_name_prev != NULL ? icon_name_prev : "(NULL)"); - */ - } - if (icon_name_prev != NULL && !strcmp(icon_name, icon_name_prev)) { - /* purple_debug_info("QQ", "Icon is not changed\n"); */ - g_free(icon_name); - return; - } - - icon_path = qq_get_icon_path(icon_name); - if (icon_path == NULL) { - g_free(icon_name); - return; - } - - if (!g_file_get_contents(icon_path, &icon_file_content, &icon_file_size, NULL)) { - purple_debug_error("QQ", "Failed reading icon file %s\n", icon_path); - } else { - purple_debug_info("QQ", "Update %s icon to %d (%s)\n", - who, face, icon_path); - purple_buddy_icons_set_for_user(account, who, - icon_file_content, icon_file_size, icon_name); - } - g_free(icon_name); - g_free(icon_path); -} - -/* after getting info or modify myself, refresh the buddy list accordingly */ -static void update_buddy_info(PurpleConnection *gc, gchar **segments) -{ - PurpleBuddy *buddy = NULL; - qq_data *qd = NULL; - qq_buddy_data *bd = NULL; - UID uid; - gchar *who; - gchar *alias_utf8; - - PurpleAccount *account = purple_connection_get_account(gc); - qd = (qq_data *)purple_connection_get_protocol_data(gc); - - uid = strtoul(segments[QQ_INFO_UID], NULL, 10); - who = uid_to_purple_name(uid); - qq_filter_str(segments[QQ_INFO_NICK]); - alias_utf8 = qq_to_utf8(segments[QQ_INFO_NICK], QQ_CHARSET_DEFAULT); - - if (uid == qd->uid) { /* it is me */ - purple_debug_info("QQ", "Got my info\n"); - qd->my_icon = strtol(segments[QQ_INFO_FACE], NULL, 10); - if (alias_utf8 != NULL) { - purple_account_set_alias(account, alias_utf8); - } - /* add me to buddy list */ - buddy = qq_buddy_find_or_new(gc, uid); - } else { - buddy = purple_find_buddy(gc->account, who); - /* purple_debug_info("QQ", "buddy=%p\n", (void*)buddy); */ - } - - /* if the buddy is null, the api will catch it and return null here */ - bd = purple_buddy_get_protocol_data(buddy); - /* purple_debug_info("QQ", "bd=%p\n", (void*)bd); */ - - if (bd == NULL || buddy == NULL) { - g_free(who); - g_free(alias_utf8); - return; - } - - /* update buddy list (including myself, if myself is the buddy) */ - bd->age = strtol(segments[QQ_INFO_AGE], NULL, 10); - bd->gender = strtol(segments[QQ_INFO_GENDER], NULL, 10); - bd->face = strtol(segments[QQ_INFO_FACE], NULL, 10); - - if (alias_utf8 != NULL) { - if (bd->nickname) g_free(bd->nickname); - bd->nickname = g_strdup(alias_utf8); - } - bd->last_update = time(NULL); - - purple_blist_server_alias_buddy(buddy, bd->nickname); - - /* convert face num from packet (0-299) to local face (1-100) */ - qq_update_buddy_icon(gc->account, who, bd->face); - - g_free(who); - g_free(alias_utf8); -} - -/* process reply to get_info packet */ -void qq_process_get_buddy_info(guint8 *data, gint data_len, guint32 action, PurpleConnection *gc) -{ - qq_data *qd; - gchar **segments; - gint field_count; - gchar *icon_name; - - g_return_if_fail(data != NULL && data_len != 0); - - qd = (qq_data *) gc->proto_data; - - if (qd->client_version >= 2008) { - field_count = QQ_INFO_LAST; - } else { - field_count = QQ_INFO_LAST_2007; - } - if (NULL == (segments = split_data(data, data_len, "\x1e", field_count))) - return; - -#ifdef DEBUG - info_debug(segments); -#endif - - if (action == QQ_BUDDY_INFO_SET_ICON) { - if (strtol(segments[QQ_INFO_FACE], NULL, 10) != qd->my_icon) { - icon_name = g_strdup_printf("%d", qd->my_icon); - g_free(segments[QQ_INFO_FACE]); - segments[QQ_INFO_FACE] = icon_name; - - /* Update me in buddy list */ - update_buddy_info(gc, segments); - /* send new face to server */ - request_change_info(gc, segments); - } - g_strfreev(segments); - return; - } - - update_buddy_info(gc, segments); - switch (action) { - case QQ_BUDDY_INFO_DISPLAY: - info_display_only(gc, segments); - break; - case QQ_BUDDY_INFO_SET_ICON: - g_return_if_reached(); - break; - case QQ_BUDDY_INFO_MODIFY_BASE: - info_modify_dialogue(gc, segments, QQ_FIELD_BASE); - break; - case QQ_BUDDY_INFO_MODIFY_EXT: - info_modify_dialogue(gc, segments, QQ_FIELD_EXT); - break; - case QQ_BUDDY_INFO_MODIFY_ADDR: - info_modify_dialogue(gc, segments, QQ_FIELD_ADDR); - break; - case QQ_BUDDY_INFO_MODIFY_CONTACT: - info_modify_dialogue(gc, segments, QQ_FIELD_CONTACT); - break; - default: - g_strfreev(segments); - break; - } - return; -} - -void qq_request_get_level(PurpleConnection *gc, UID uid) -{ - qq_data *qd = (qq_data *) gc->proto_data; - guint8 buf[16] = {0}; - gint bytes = 0; - - if (qd->client_version >= 2007) { - bytes += qq_put8(buf + bytes, 0x02); - } else { - bytes += qq_put8(buf + bytes, 0x00); - } - bytes += qq_put32(buf + bytes, uid); - qq_send_cmd(gc, QQ_CMD_GET_LEVEL, buf, bytes); -} - -void qq_request_get_level_2007(PurpleConnection *gc, UID uid) -{ - guint8 buf[16] = {0}; - gint bytes = 0; - - bytes += qq_put8(buf + bytes, 0x08); - bytes += qq_put32(buf + bytes, uid); - bytes += qq_put8(buf + bytes, 0x00); - qq_send_cmd(gc, QQ_CMD_GET_LEVEL, buf, bytes); -} - -void qq_request_get_buddies_level(PurpleConnection *gc, UPDCLS update_class) -{ - qq_data *qd = (qq_data *) gc->proto_data; - PurpleBuddy *buddy; - qq_buddy_data *bd; - guint8 *buf; - GSList *buddies, *it; - gint bytes; - - /* server only reply levels for online buddies */ - buf = g_newa(guint8, MAX_PACKET_SIZE); - - bytes = 0; - bytes += qq_put8(buf + bytes, 0x00); - buddies = purple_find_buddies(purple_connection_get_account(gc), NULL); - for (it = buddies; it; it = it->next) { - buddy = it->data; - if (buddy == NULL) continue; - if ((bd = purple_buddy_get_protocol_data(buddy)) == NULL) continue; - if (bd->uid == 0) continue; /* keep me as end of packet*/ - if (bd->uid == qd->uid) continue; - bytes += qq_put32(buf + bytes, bd->uid); - } - bytes += qq_put32(buf + bytes, qd->uid); - qq_send_cmd_mess(gc, QQ_CMD_GET_LEVEL, buf, bytes, update_class, 0); -} - -static void process_level(PurpleConnection *gc, guint8 *data, gint data_len) -{ - gint bytes = 0; - UID uid; - guint32 onlineTime; - guint16 level, timeRemainder; - qq_buddy_data *bd; - - while (data_len - bytes >= 12) { - bytes += qq_get32(&uid, data + bytes); - bytes += qq_get32(&onlineTime, data + bytes); - bytes += qq_get16(&level, data + bytes); - bytes += qq_get16(&timeRemainder, data + bytes); - purple_debug_info("QQ", "level: %d, uid %u, tmOnline: %d, tmRemainder: %d\n", - level, uid, onlineTime, timeRemainder); - - bd = qq_buddy_data_find(gc, uid); - if (bd == NULL) { - purple_debug_error("QQ", "Got levels of %u not in my buddy list\n", uid); - continue; - } - - bd->onlineTime = onlineTime; - bd->level = level; - bd->timeRemainder = timeRemainder; - } - - if (bytes != data_len) { - purple_debug_error("QQ", - "Wrong format of Get levels. Truncate %d bytes.\n", data_len - bytes); - } -} - -static void process_level_2007(PurpleConnection *gc, guint8 *data, gint data_len) -{ - gint bytes; - UID uid; - guint32 onlineTime; - guint16 level, timeRemainder; - qq_buddy_data *bd; - guint16 str_len; - gchar *str; - gchar *str_utf8; - - bytes = 0; - bytes += qq_get32(&uid, data + bytes); - bytes += qq_get32(&onlineTime, data + bytes); - bytes += qq_get16(&level, data + bytes); - bytes += qq_get16(&timeRemainder, data + bytes); - purple_debug_info("QQ", "level: %d, uid %u, tmOnline: %d, tmRemainder: %d\n", - level, uid, onlineTime, timeRemainder); - - bd = qq_buddy_data_find(gc, uid); - if (bd == NULL) { - purple_debug_error("QQ", "Got levels of %u not in my buddy list\n", uid); - return; - } - - bd->onlineTime = onlineTime; - bd->level = level; - bd->timeRemainder = timeRemainder; - - /* extend bytes in qq2007*/ - bytes += 4; /* skip 8 bytes */ - /* qq_show_packet("Buddies level", data + bytes, data_len - bytes); */ - - do { - bytes += qq_get16(&str_len, data + bytes); - if (str_len <= 0 || bytes + str_len > data_len) { - purple_debug_error("QQ", - "Wrong format of Get levels. Truncate %d bytes.\n", data_len - bytes); - break; - } - str = g_strndup((gchar *)data + bytes, str_len); - bytes += str_len; - str_utf8 = qq_to_utf8(str, QQ_CHARSET_DEFAULT); - purple_debug_info("QQ", "%s\n", str_utf8); - g_free(str_utf8); - g_free(str); - } while (bytes < data_len); -} - -void qq_process_get_level_reply(guint8 *data, gint data_len, PurpleConnection *gc) -{ - gint bytes; - guint8 sub_cmd; - - bytes = 0; - bytes += qq_get8(&sub_cmd, data + bytes); - switch (sub_cmd) { - case 0x08: - process_level_2007(gc, data + bytes, data_len - bytes); - break; - case 0x00: - case 0x02: - default: - process_level(gc, data + bytes, data_len - bytes); - break; - } -} - diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/qq/buddy_info.h --- a/libpurple/protocols/qq/buddy_info.h Thu May 05 03:40:29 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,92 +0,0 @@ -/** - * @file buddy_info.h - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * 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 02111-1301 USA - */ - -#ifndef _QQ_BUDDY_INFO_H_ -#define _QQ_BUDDY_INFO_H_ - -#include -#include "connection.h" - -#include "buddy_opt.h" -#include "qq.h" - -/* use in qq2005 - * ext_flag: (0-7) - * bit1 => qq space - * comm_flag: (0-7) - * bit1 => member - * bit4 => TCP mode - * bit5 => open mobile QQ - * bit6 => bind to mobile - * bit7 => whether having a video -#define QQ_COMM_FLAG_QQ_MEMBER 0x02 -#define QQ_COMM_FLAG_TCP_MODE 0x10 -#define QQ_COMM_FLAG_MOBILE 0x20 -#define QQ_COMM_FLAG_BIND_MOBILE 0x40 -#define QQ_COMM_FLAG_VIDEO 0x80 - */ -/* status in eva for qq2006 -#define QQ_FRIEND_FLAG_QQ_MEMBER 0x01 -#define QQ_FRIEND_FLAG_MOBILE 0x10 -#define QQ_FRIEND_FLAG_BIND_MOBILE 0x20 -*/ -#define QQ_COMM_FLAG_QQ_VIP 0x02 -#define QQ_COMM_FLAG_QQ_MEMBER 0x04 -#define QQ_COMM_FLAG_TCP_MODE 0x10 -#define QQ_COMM_FLAG_MOBILE 0x20 -#define QQ_COMM_FLAG_BIND_MOBILE 0x40 -#define QQ_COMM_FLAG_VIDEO 0x80 - -#define QQ_EXT_FLAG_ZONE 0x02 - -#define QQ_BUDDY_GENDER_GG 0x00 -#define QQ_BUDDY_GENDER_MM 0x01 -#define QQ_BUDDY_GENDER_UNKNOWN 0xff - -enum { - QQ_BUDDY_INFO_UPDATE_ONLY = 0, - QQ_BUDDY_INFO_DISPLAY, - QQ_BUDDY_INFO_SET_ICON, - QQ_BUDDY_INFO_MODIFY_BASE, - QQ_BUDDY_INFO_MODIFY_EXT, - QQ_BUDDY_INFO_MODIFY_ADDR, - QQ_BUDDY_INFO_MODIFY_CONTACT -}; - -gchar *qq_get_icon_name(gint face); -gchar *qq_get_icon_path(gchar *icon_name); -void qq_change_icon_cb(PurpleConnection *gc, const char *filepath); - -void qq_request_buddy_info(PurpleConnection *gc, UID uid, UPDCLS update_class, int action); -void qq_set_custom_icon(PurpleConnection *gc, PurpleStoredImage *img); -void qq_process_change_info(PurpleConnection *gc, guint8 *data, gint data_len); -void qq_process_get_buddy_info(guint8 *data, gint data_len, guint32 action, PurpleConnection *gc); - -void qq_request_get_level(PurpleConnection *gc, UID uid); -void qq_request_get_level_2007(PurpleConnection *gc, UID uid); -void qq_request_get_buddies_level(PurpleConnection *gc, UPDCLS update_class); -void qq_process_get_level_reply(guint8 *buf, gint buf_len, PurpleConnection *gc); - -void qq_update_buddy_icon(PurpleAccount *account, const gchar *who, gint face); -#endif diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/qq/buddy_list.c --- a/libpurple/protocols/qq/buddy_list.c Thu May 05 03:40:29 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,693 +0,0 @@ -/** - * @file buddy_list.c - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * 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 02111-1301 USA - */ - -#include "qq.h" - -#include "debug.h" -#include "notify.h" -#include "utils.h" -#include "packet_parse.h" -#include "buddy_info.h" -#include "buddy_memo.h" -#include "buddy_list.h" -#include "buddy_opt.h" -#include "char_conv.h" -#include "qq_define.h" -#include "qq_base.h" -#include "group.h" -#include "group_internal.h" -#include "group_info.h" - -#include "qq_network.h" - -#define QQ_GET_ONLINE_BUDDY_02 0x02 -#define QQ_GET_ONLINE_BUDDY_03 0x03 /* unknown function */ - -typedef struct _qq_buddy_online { - guint16 unknown1; - guint8 ext_flag; - guint8 comm_flag; - guint16 unknown2; - guint8 ending; /* 0x00 */ -} qq_buddy_online; - -/* get a list of online_buddies */ -void qq_request_get_buddies_online(PurpleConnection *gc, guint8 position, UPDCLS update_class) -{ - guint8 *raw_data; - gint bytes = 0; - - raw_data = g_newa(guint8, 5); - - /* 000-000 get online friends cmd - * only 0x02 and 0x03 returns info from server, other valuse all return 0xff - * I can also only send the first byte (0x02, or 0x03) - * and the result is the same */ - bytes += qq_put8(raw_data + bytes, QQ_GET_ONLINE_BUDDY_02); - /* 001-001 seems it supports 255 online buddies at most */ - bytes += qq_put8(raw_data + bytes, position); - /* 002-002 */ - bytes += qq_put8(raw_data + bytes, 0x00); - /* 003-004 */ - bytes += qq_put16(raw_data + bytes, 0x0000); - - qq_send_cmd_mess(gc, QQ_CMD_GET_BUDDIES_ONLINE, raw_data, 5, update_class, 0); -} - -/* position starts with 0x0000, - * server may return a position tag if list is too long for one packet */ -void qq_request_get_buddies(PurpleConnection *gc, guint16 position, UPDCLS update_class) -{ - qq_data *qd; - guint8 raw_data[16] = {0}; - gint bytes = 0; - - qd = (qq_data *) gc->proto_data; - - /* 000-001 starting position, can manually specify */ - bytes += qq_put16(raw_data + bytes, position); - /* before Mar 18, 2004, any value can work, and we sent 00 - * I do not know what data QQ server is expecting, as QQ2003iii 0304 itself - * even can sending packets 00 and get no response. - * Now I tested that 00,00,00,00,00,01 work perfectly - * March 22, found the 00,00,00 starts to work as well */ - bytes += qq_put8(raw_data + bytes, 0x00); - if (qd->client_version >= 2007) { - bytes += qq_put16(raw_data + bytes, 0x0000); - } - - qq_send_cmd_mess(gc, QQ_CMD_GET_BUDDIES_LIST, raw_data, bytes, update_class, 0); -} - -/* get all list, buddies & Quns with groupsid support */ -void qq_request_get_buddies_and_rooms(PurpleConnection *gc, guint32 position, UPDCLS update_class) -{ - guint8 raw_data[16] = {0}; - gint bytes = 0; - - /* 0x01 download, 0x02, upload */ - bytes += qq_put8(raw_data + bytes, 0x01); - /* unknown 0x02 */ - bytes += qq_put8(raw_data + bytes, 0x02); - /* unknown 00 00 00 00 */ - bytes += qq_put32(raw_data + bytes, 0x00000000); - bytes += qq_put32(raw_data + bytes, position); - - qq_send_cmd_mess(gc, QQ_CMD_GET_BUDDIES_AND_ROOMS, raw_data, bytes, update_class, 0); -} - -/* parse the data into qq_buddy_status */ -static gint get_buddy_status(qq_buddy_status *bs, guint8 *data) -{ - gint bytes = 0; - - g_return_val_if_fail(data != NULL && bs != NULL, -1); - - /* 000-003: uid */ - bytes += qq_get32(&bs->uid, data + bytes); - /* 004-004: 0x01 */ - bytes += qq_get8(&bs->unknown1, data + bytes); - /* this is no longer the IP, it seems QQ (as of 2006) no longer sends - * the buddy's IP in this packet. all 0s */ - /* 005-008: ip */ - bytes += qq_getIP(&bs->ip, data + bytes); - /* port info is no longer here either */ - /* 009-010: port */ - bytes += qq_get16(&bs->port, data + bytes); - /* 011-011: 0x00 */ - bytes += qq_get8(&bs->unknown2, data + bytes); - /* 012-012: status */ - bytes += qq_get8(&bs->status, data + bytes); - /* 013-014: client tag */ - bytes += qq_get16(&bs->unknown3, data + bytes); - /* 015-030: unknown key */ - bytes += qq_getdata(&(bs->unknown_key[0]), QQ_KEY_LENGTH, data + bytes); - - purple_debug_info("QQ", "Status:%d, uid: %u, ip: %s:%d, U: %d - %d - %04X\n", - bs->status, bs->uid, inet_ntoa(bs->ip), bs->port, - bs->unknown1, bs->unknown2, bs->unknown3); - - return bytes; -} - -/* process the reply packet for get_buddies_online packet */ -guint8 qq_process_get_buddies_online(guint8 *data, gint data_len, PurpleConnection *gc) -{ - qq_data *qd; - gint bytes, bytes_start; - gint count; - guint8 position; - gchar *who; - PurpleBuddy *buddy; - qq_buddy_data *bd; - int entry_len = 38; - - qq_buddy_status bs; - struct { - guint16 unknown1; - guint8 ext_flag; - guint8 comm_flag; - guint16 unknown2; - guint8 ending; /* 0x00 */ - } packet; - - g_return_val_if_fail(data != NULL && data_len != 0, -1); - - qd = (qq_data *) gc->proto_data; - - /* qq_show_packet("Get buddies online reply packet", data, len); */ - if (qd->client_version >= 2007) entry_len += 4; - - bytes = 0; - bytes += qq_get8(&position, data + bytes); - - count = 0; - while (bytes < data_len) { - if (data_len - bytes < entry_len) { - purple_debug_error("QQ", "[buddies online] only %d, need %d\n", - (data_len - bytes), entry_len); - break; - } - memset(&bs, 0 ,sizeof(bs)); - memset(&packet, 0 ,sizeof(packet)); - - /* set flag */ - bytes_start = bytes; - /* based on one online buddy entry */ - /* 000-030 qq_buddy_status */ - bytes += get_buddy_status(&bs, data + bytes); - /* 031-032: */ - bytes += qq_get16(&packet.unknown1, data + bytes); - /* 033-033: ext_flag */ - bytes += qq_get8(&packet.ext_flag, data + bytes); - /* 034-034: comm_flag */ - bytes += qq_get8(&packet.comm_flag, data + bytes); - /* 035-036: */ - bytes += qq_get16(&packet.unknown2, data + bytes); - /* 037-037: */ - bytes += qq_get8(&packet.ending, data + bytes); /* 0x00 */ - /* skip 4 bytes in qq2007 */ - if (qd->client_version >= 2007) bytes += 4; - - if (bs.uid == 0 || (bytes - bytes_start) != entry_len) { - purple_debug_error("QQ", "uid=0 or entry complete len(%d) != %d\n", - (bytes - bytes_start), entry_len); - continue; - } /* check if it is a valid entry */ - - if (bs.uid == qd->uid) { - purple_debug_warning("QQ", "I am in online list %u\n", bs.uid); - } - - /* update buddy information */ - who = uid_to_purple_name(bs.uid); - buddy = purple_find_buddy(gc->account, who); - g_free(who); - if (buddy == NULL) { - /* create no-auth buddy */ - buddy = qq_buddy_new(gc, bs.uid); - } - bd = (buddy == NULL) ? NULL : (qq_buddy_data *)purple_buddy_get_protocol_data(buddy); - if (bd == NULL) { - purple_debug_error("QQ", - "Got an online buddy %u, but not in my buddy list\n", bs.uid); - continue; - } - /* - if(0 != fe->s->client_tag) - q_bud->client_tag = fe->s->client_tag; - */ - if (bd->status != bs.status || bd->comm_flag != packet.comm_flag) { - bd->status = bs.status; - bd->comm_flag = packet.comm_flag; - qq_update_buddy_status(gc, bd->uid, bd->status, bd->comm_flag); - } - bd->ip.s_addr = bs.ip.s_addr; - bd->port = bs.port; - bd->ext_flag = packet.ext_flag; - bd->last_update = time(NULL); - count++; - } - - if(bytes > data_len) { - purple_debug_error("QQ", - "qq_process_get_buddies_online: Dangerous error! maybe protocol changed, notify developers!\n"); - } - - purple_debug_info("QQ", "Received %d online buddies, nextposition=%u\n", - count, (guint) position); - return position; -} - - -/* process reply for get_buddies_list */ -guint16 qq_process_get_buddies(guint8 *data, gint data_len, PurpleConnection *gc) -{ - qq_data *qd; - qq_buddy_data bd; - gint bytes_expected, count; - gint bytes, buddy_bytes; - gint nickname_len; - guint16 position, unknown; - PurpleBuddy *buddy; - - g_return_val_if_fail(data != NULL && data_len != 0, -1); - - qd = (qq_data *) gc->proto_data; - - if (data_len <= 2) { - purple_debug_error("QQ", "empty buddies list\n"); - return -1; - } - /* qq_show_packet("QQ get buddies list", data, data_len); */ - bytes = 0; - bytes += qq_get16(&position, data + bytes); - /* the following data is buddy list in this packet */ - count = 0; - while (bytes < data_len) { - memset(&bd, 0, sizeof(bd)); - /* set flag */ - buddy_bytes = bytes; - /* 000-003: uid */ - bytes += qq_get32(&bd.uid, data + bytes); - /* 004-005: icon index (1-255) */ - bytes += qq_get16(&bd.face, data + bytes); - /* 006-006: age */ - bytes += qq_get8(&bd.age, data + bytes); - /* 007-007: gender */ - bytes += qq_get8(&bd.gender, data + bytes); - - nickname_len = qq_get_vstr(&bd.nickname, QQ_CHARSET_DEFAULT, data + bytes); - bytes += nickname_len; - qq_filter_str(bd.nickname); - - /* Fixme: merge following as 32bit flag */ - bytes += qq_get16(&unknown, data + bytes); - bytes += qq_get8(&bd.ext_flag, data + bytes); - bytes += qq_get8(&bd.comm_flag, data + bytes); - - if (qd->client_version >= 2007) { - bytes += 4; /* skip 4 bytes */ - bytes_expected = 16 + nickname_len; - } else { - bytes_expected = 12 + nickname_len; - } - - if (bd.uid == 0 || (bytes - buddy_bytes) != bytes_expected) { - purple_debug_info("QQ", - "Buddy entry, expect %d bytes, read %d bytes\n", - bytes_expected, bytes - buddy_bytes); - g_free(bd.nickname); - continue; - } else { - count++; - } - -#if 1 - purple_debug_info("QQ", "buddy [%09d]: ext_flag=0x%02x, comm_flag=0x%02x, nick=%s\n", - bd.uid, bd.ext_flag, bd.comm_flag, bd.nickname); -#endif - - buddy = qq_buddy_find_or_new(gc, bd.uid); - if (buddy == NULL || purple_buddy_get_protocol_data(buddy) == NULL) { - g_free(bd.nickname); - continue; - } - purple_blist_server_alias_buddy(buddy, bd.nickname); - bd.last_update = time(NULL); - qq_update_buddy_status(gc, bd.uid, bd.status, bd.comm_flag); - - g_memmove(purple_buddy_get_protocol_data(buddy), &bd, sizeof(qq_buddy_data)); - /* nickname has been copy to buddy_data do not free - g_free(bd.nickname); - */ - /*qq_request_buddy_memo(gc, ((qq_buddy_data*)buddy->proto_data)->uid, 0, QQ_BUDDY_MEMO_GET);*/ - qq_request_buddy_memo(gc, bd.uid, bd.uid, QQ_BUDDY_MEMO_GET); - } - - if(bytes > data_len) { - purple_debug_error("QQ", - "qq_process_get_buddies: Dangerous error! maybe protocol changed, notify developers!\n"); - } - - purple_debug_info("QQ", "Received %d buddies, nextposition=%u\n", - count, (guint) position); - return position; -} - -guint32 qq_process_get_buddies_and_rooms(guint8 *data, gint data_len, PurpleConnection *gc) -{ - gint i, j; - gint bytes; - guint8 sub_cmd, reply_code; - guint32 unknown, position; - UID uid; - guint8 type; - qq_room_data *rmd; - - g_return_val_if_fail(data != NULL && data_len != 0, -1); - - bytes = 0; - bytes += qq_get8(&sub_cmd, data + bytes); - g_return_val_if_fail(sub_cmd == 0x01, -1); - - bytes += qq_get8(&reply_code, data + bytes); - if(0 != reply_code) { - purple_debug_warning("QQ", "qq_process_get_buddies_and_rooms, %d\n", reply_code); - } - - bytes += qq_get32(&unknown, data + bytes); - bytes += qq_get32(&position, data + bytes); - /* the following data is all list in this packet */ - i = 0; - j = 0; - while (bytes < data_len) { - /* 00-03: uid */ - bytes += qq_get32(&uid, data + bytes); - /* 04: type 0x1:buddy 0x4:Qun */ - bytes += qq_get8(&type, data + bytes); - /* 05: skip unknow 0x00 */ - bytes += 1; - if (uid == 0 || (type != 0x1 && type != 0x4)) { - purple_debug_info("QQ", "Buddy entry, uid=%u, type=%d\n", uid, type); - continue; - } - if(0x1 == type) { /* a buddy */ - /* don't do anything but count - buddies are handled by - * qq_request_get_buddies */ - ++i; - } else { /* a group */ - rmd = qq_room_data_find(gc, uid); - if(rmd == NULL) { - purple_debug_info("QQ", "Unknown room id %u\n", uid); - qq_send_room_cmd_only(gc, QQ_ROOM_CMD_GET_INFO, uid); - } else { - rmd->my_role = QQ_ROOM_ROLE_YES; - } - ++j; - } - } - - if(bytes > data_len) { - purple_debug_error("QQ", - "qq_process_get_buddies_and_rooms: Dangerous error! maybe protocol changed, notify developers!\n"); - } - - purple_debug_info("QQ", "Received %d buddies and %d groups, nextposition=%u\n", i, j, (guint) position); - return position; -} - -#define QQ_MISC_STATUS_HAVING_VIIDEO 0x00000001 -#define QQ_CHANGE_ONLINE_STATUS_REPLY_OK 0x30 /* ASCII value of "0" */ - -/* TODO: figure out what's going on with the IP region. Sometimes I get valid IP addresses, - * but the port number's weird, other times I get 0s. I get these simultaneously on the same buddy, - * using different accounts to get info. */ -static guint8 get_status_from_purple(PurpleConnection *gc) -{ - qq_data *qd; - PurpleAccount *account; - PurplePresence *presence; - guint8 ret; - - qd = (qq_data *) gc->proto_data; - account = purple_connection_get_account(gc); - presence = purple_account_get_presence(account); - - if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_INVISIBLE)) { - ret = QQ_BUDDY_ONLINE_INVISIBLE; - } else if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_UNAVAILABLE)) - { - if (qd->client_version >= 2007) { - ret = QQ_BUDDY_ONLINE_BUSY; - } else { - ret = QQ_BUDDY_ONLINE_INVISIBLE; - } - } else if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_AWAY) - || purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_EXTENDED_AWAY) - || purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_UNAVAILABLE)) { - ret = QQ_BUDDY_ONLINE_AWAY; - } else { - ret = QQ_BUDDY_ONLINE_NORMAL; - } - return ret; -} - -/* send a packet to change my online status */ -void qq_request_change_status(PurpleConnection *gc, UPDCLS update_class) -{ - qq_data *qd; - guint8 raw_data[16] = {0}; - gint bytes = 0; - guint8 away_cmd; - guint32 misc_status; - gboolean fake_video; - - qd = (qq_data *) gc->proto_data; - if (!qd->is_login) - return; - - away_cmd = get_status_from_purple(gc); - - misc_status = 0x00000000; - fake_video = purple_prefs_get_bool("/plugins/prpl/qq/show_fake_video"); - if (fake_video) - misc_status |= QQ_MISC_STATUS_HAVING_VIIDEO; - - if (qd->client_version >= 2007) { - bytes = 0; - bytes += qq_put8(raw_data + bytes, away_cmd); - /* status version */ - bytes += qq_put16(raw_data + bytes, 0); - bytes += qq_put16(raw_data + bytes, 0); - bytes += qq_put32(raw_data + bytes, misc_status); - /* Fixme: custom status message, now is empty */ - bytes += qq_put16(raw_data + bytes, 0); - } else { - bytes = 0; - bytes += qq_put8(raw_data + bytes, away_cmd); - bytes += qq_put32(raw_data + bytes, misc_status); - } - qq_send_cmd_mess(gc, QQ_CMD_CHANGE_STATUS, raw_data, bytes, update_class, 0); -} - -/* parse the reply packet for change_status */ -void qq_process_change_status(guint8 *data, gint data_len, PurpleConnection *gc) -{ - qq_data *qd; - gint bytes; - guint8 reply; - qq_buddy_data *bd; - - g_return_if_fail(data != NULL && data_len != 0); - - qd = (qq_data *) gc->proto_data; - - bytes = 0; - bytes = qq_get8(&reply, data + bytes); - if (reply != QQ_CHANGE_ONLINE_STATUS_REPLY_OK) { - purple_debug_warning("QQ", "Change status fail 0x%02X\n", reply); - return; - } - - /* purple_debug_info("QQ", "Change status OK\n"); */ - bd = qq_buddy_data_find(gc, qd->uid); - if (bd != NULL) { - bd->status = get_status_from_purple(gc); - bd->last_update = time(NULL); - qq_update_buddy_status(gc, bd->uid, bd->status, bd->comm_flag); - } -} - -/* it is a server message indicating that one of my buddies has changed its status */ -void qq_process_buddy_change_status(guint8 *data, gint data_len, PurpleConnection *gc) -{ - qq_data *qd; - gint bytes; - UID my_uid; - gchar *who; - PurpleBuddy *buddy; - qq_buddy_data *bd; - qq_buddy_status bs; - - g_return_if_fail(data != NULL && data_len != 0); - - qd = (qq_data *) gc->proto_data; - - if (data_len < 35) { - purple_debug_error("QQ", "[buddy status change] only %d, need 35 bytes\n", data_len); - return; - } - - memset(&bs, 0, sizeof(bs)); - bytes = 0; - /* 000-030: qq_buddy_status */ - bytes += get_buddy_status(&bs, data + bytes); - /* 031-034: Unknow, maybe my uid */ - /* This has a value of 0 when we've changed our status to - * QQ_BUDDY_ONLINE_INVISIBLE */ - bytes += qq_get32(&my_uid, data + bytes); - - /* update buddy information */ - who = uid_to_purple_name(bs.uid); - buddy = purple_find_buddy(gc->account, who); - g_free(who); - if (buddy == NULL) { - /* create no-auth buddy */ - buddy = qq_buddy_new(gc, bs.uid); - } - bd = (buddy == NULL) ? NULL : (qq_buddy_data *)purple_buddy_get_protocol_data(buddy); - if (bd == NULL) { - purple_debug_warning("QQ", "Got status of no-auth buddy %u\n", bs.uid); - return; - } - - if(bs.ip.s_addr != 0) { - bd->ip.s_addr = bs.ip.s_addr; - bd->port = bs.port; - } - if (bd->status != bs.status) { - bd->status = bs.status; - qq_update_buddy_status(gc, bd->uid, bd->status, bd->comm_flag); - } - bd->last_update = time(NULL); - - if (bd->status == QQ_BUDDY_ONLINE_NORMAL && bd->level <= 0) { - if (qd->client_version >= 2007) { - qq_request_get_level_2007(gc, bd->uid); - } else { - qq_request_get_level(gc, bd->uid); - } - } -} - -/*TODO: maybe this should be qq_update_buddy_status() ?*/ -void qq_update_buddy_status(PurpleConnection *gc, UID uid, guint8 status, guint8 flag) -{ - gchar *who; - const gchar *status_id; - - g_return_if_fail(uid != 0); - - /* purple supports signon and idle time - * but it is not much use for QQ, I do not use them */ - /* serv_got_update(gc, name, online, 0, q_bud->signon, q_bud->idle, bud->uc); */ - switch(status) { - case QQ_BUDDY_OFFLINE: - status_id = "offline"; - break; - case QQ_BUDDY_ONLINE_NORMAL: - status_id = "available"; - break; - case QQ_BUDDY_CHANGE_TO_OFFLINE: - status_id = "offline"; - break; - case QQ_BUDDY_ONLINE_AWAY: - status_id = "away"; - break; - case QQ_BUDDY_ONLINE_INVISIBLE: - status_id = "invisible"; - break; - case QQ_BUDDY_ONLINE_BUSY: - status_id = "busy"; - break; - default: - status_id = "invisible"; - purple_debug_error("QQ", "unknown status: 0x%X\n", status); - break; - } - - purple_debug_info("QQ", "buddy %u status = %s\n", uid, status_id); - who = uid_to_purple_name(uid); - purple_prpl_got_user_status(gc->account, who, status_id, NULL); - - if (flag & QQ_COMM_FLAG_MOBILE && status != QQ_BUDDY_OFFLINE) - purple_prpl_got_user_status(gc->account, who, "mobile", NULL); - else - purple_prpl_got_user_status_deactive(gc->account, who, "mobile"); - - g_free(who); -} - -/* refresh all buddies online/offline, - * after receiving reply for get_buddies_online packet */ -void qq_update_buddyies_status(PurpleConnection *gc) -{ - qq_data *qd; - PurpleBuddy *buddy; - qq_buddy_data *bd; - GSList *buddies, *it; - time_t tm_limit = time(NULL); - - qd = (qq_data *) (gc->proto_data); - - tm_limit -= QQ_UPDATE_ONLINE_INTERVAL; - - buddies = purple_find_buddies(purple_connection_get_account(gc), NULL); - for (it = buddies; it; it = it->next) { - buddy = it->data; - if (buddy == NULL) continue; - - bd = purple_buddy_get_protocol_data(buddy); - if (bd == NULL) continue; - - if (bd->uid == 0) continue; - if (bd->uid == qd->uid) continue; /* my status is always online in my buddy list */ - if (tm_limit < bd->last_update) continue; - if (bd->status == QQ_BUDDY_ONLINE_INVISIBLE) continue; - if (bd->status == QQ_BUDDY_CHANGE_TO_OFFLINE) continue; - - bd->status = QQ_BUDDY_CHANGE_TO_OFFLINE; - bd->last_update = time(NULL); - qq_update_buddy_status(gc, bd->uid, bd->status, bd->comm_flag); - } -} - -void qq_buddy_data_free_all(PurpleConnection *gc) -{ - PurpleBuddy *buddy; - GSList *buddies, *it; - gint count = 0; - - buddies = purple_find_buddies(purple_connection_get_account(gc), NULL); - for (it = buddies; it; it = it->next) { - qq_buddy_data *qbd = NULL; - - buddy = it->data; - if (buddy == NULL) continue; - - qbd = purple_buddy_get_protocol_data(buddy); - if (qbd == NULL) continue; - - qq_buddy_data_free(qbd); - purple_buddy_set_protocol_data(buddy, NULL); - - count++; - } - - if (count > 0) { - purple_debug_info("QQ", "%d buddies' data are freed\n", count); - } -} - diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/qq/buddy_list.h --- a/libpurple/protocols/qq/buddy_list.h Thu May 05 03:40:29 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,59 +0,0 @@ -/** - * @file buddy_list.h - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * 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 02111-1301 USA - */ - -#ifndef _QQ_BUDDY_LIST_H_ -#define _QQ_BUDDY_LIST_H_ - -#include -#include "connection.h" - -#include "qq.h" -typedef struct _qq_buddy_status { - UID uid; - guint8 unknown1; - struct in_addr ip; - guint16 port; - guint8 unknown2; - guint8 status; - guint16 unknown3; - guint8 unknown_key[QQ_KEY_LENGTH]; -} qq_buddy_status; - -void qq_request_get_buddies_online(PurpleConnection *gc, guint8 position, UPDCLS update_class); -guint8 qq_process_get_buddies_online(guint8 *data, gint data_len, PurpleConnection *gc); - -void qq_request_get_buddies(PurpleConnection *gc, guint16 position, UPDCLS update_class); -guint16 qq_process_get_buddies(guint8 *data, gint data_len, PurpleConnection *gc); - -void qq_request_get_buddies_and_rooms(PurpleConnection *gc, guint32 position, UPDCLS update_class); -guint32 qq_process_get_buddies_and_rooms(guint8 *data, gint data_len, PurpleConnection *gc); - -void qq_request_change_status(PurpleConnection *gc, UPDCLS update_class); -void qq_process_change_status(guint8 *data, gint data_len, PurpleConnection *gc); -void qq_process_buddy_change_status(guint8 *data, gint data_len, PurpleConnection *gc); - -void qq_update_buddyies_status(PurpleConnection *gc); -void qq_update_buddy_status(PurpleConnection *gc, UID uid, guint8 status, guint8 flag); -void qq_buddy_data_free_all(PurpleConnection *gc); -#endif diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/qq/buddy_memo.c --- a/libpurple/protocols/qq/buddy_memo.c Thu May 05 03:40:29 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,398 +0,0 @@ -/** - * @file buddy_memo.c - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * 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 02111-1301 USA - */ - -#include "internal.h" -#include "debug.h" -#include "notify.h" -#include "request.h" - -#include "buddy_memo.h" -#include "utils.h" -#include "packet_parse.h" -#include "buddy_list.h" -#include "buddy_info.h" -#include "char_conv.h" -#include "im.h" -#include "qq_define.h" -#include "qq_base.h" -#include "qq_network.h" -#include "qq.h" - - -#include -#include -#include - -#include -#include - -/* memo index */ -enum { - QQ_MEMO_ALIAS = 0, - QQ_MEMO_MOBILD, - QQ_MEMO_TELEPHONE, - QQ_MEMO_ADDRESS, - QQ_MEMO_EMAIL, - QQ_MEMO_ZIPCODE, - QQ_MEMO_NOTE, - QQ_MEMO_SIZE -}; - -/* memo id */ -static const gchar *memo_id[] = { - "mm_alias", - "mm_mobile", - "mm_telephone", - "mm_address", - "mm_email", - "mm_zipcode", - "mm_note" -}; - -/* memo text */ -static const gchar *memo_txt[] = { - N_("Alias"), - N_("Mobile"), - N_("Telephone"), - N_("Address"), - N_("Email"), - N_("Postal Code"), - N_("Note") -}; - -typedef struct _modify_memo_request { - PurpleConnection *gc; - UID bd_uid; - gchar **segments; -} modify_memo_request; - - -static void memo_debug(gchar **segments) -{ - gint index; - g_return_if_fail(NULL != segments); - for (index = 0; index < QQ_MEMO_SIZE; index++) { - purple_debug_info("QQ","memo[%i]=%s\n", index, segments[index]); - } -} - -static void memo_free(gchar **segments) -{ - gint index; - g_return_if_fail(NULL != segments); - for (index = 0; index < QQ_MEMO_SIZE; index++) { - g_free(segments[index]); - } - purple_debug_info("QQ", "memo freed\n"); -} - -static void update_buddy_memo(PurpleConnection *gc, UID bd_uid, gchar *alias) -{ - PurpleAccount *account; - PurpleBuddy *buddy; - gchar *who; - g_return_if_fail(NULL != gc && NULL != alias); - - account = (PurpleAccount *)gc->account; - g_return_if_fail(NULL != account); - - who = uid_to_purple_name(bd_uid); - buddy = purple_find_buddy(account, who); - if (buddy == NULL || purple_buddy_get_protocol_data(buddy) == NULL) { - g_free(who); - purple_debug_info("QQ", "Error...Can NOT find %d!\n", bd_uid); - return; - } - purple_blist_alias_buddy(buddy, (const char*)alias); -} - -static void request_change_memo(PurpleConnection *gc, UID bd_uid, gchar **segments) -{ - gint bytes; - /* Attention, length of each segment must be guint8(0~255), - * so length of memo string is limited. - * convert it to guint8 first before putting data */ - guint seg_len; - gint index; - guint8 raw_data[MAX_PACKET_SIZE - 16] = {0}; - - purple_debug_info( "QQ", "request_change_memo\n" ); - g_return_if_fail(NULL != gc && NULL != segments); - - bytes = 0; - bytes += qq_put8(raw_data+bytes, QQ_BUDDY_MEMO_MODIFY); - bytes += qq_put8(raw_data+bytes, 0x00); - bytes += qq_put32(raw_data+bytes, (guint32)bd_uid); - bytes += qq_put8(raw_data+bytes, 0x00); - for (index = 0; index < QQ_MEMO_SIZE; index++) { - seg_len = strlen(segments[index]); - seg_len = seg_len & 0xff; - bytes += qq_put8(raw_data+bytes, (guint8)seg_len); - bytes += qq_putdata(raw_data+bytes, (const guint8 *)segments[index], (guint8)seg_len); - } - - /* debug */ - /* - qq_show_packet("MEMO MODIFY", raw_data, bytes); - */ - - qq_send_cmd(gc, QQ_CMD_BUDDY_MEMO, raw_data, bytes); -} - -static void memo_modify_cancle_cb(modify_memo_request *memo_request, PurpleRequestFields *fields) -{ - memo_free(memo_request->segments); - g_free(memo_request); -} - -/* prepare segments to be sent, string all convert to qq charset */ -static void memo_modify_ok_cb(modify_memo_request *memo_request, PurpleRequestFields *fields) -{ - PurpleConnection *gc; - UID bd_uid; - gchar **segments; - const gchar *utf8_str; - gchar *value = NULL; - gint index; - - g_return_if_fail(NULL != memo_request); - gc = (PurpleConnection *)memo_request->gc; - segments = (gchar **)memo_request->segments; - g_return_if_fail(NULL != gc && NULL != segments); - bd_uid = (guint32)memo_request->bd_uid; - - - for (index = 0; index < QQ_MEMO_SIZE; index++) { - utf8_str = purple_request_fields_get_string(fields, memo_id[index]); - /* update alias */ - if (QQ_MEMO_ALIAS == index) { - update_buddy_memo(gc, (UID)bd_uid, segments[QQ_MEMO_ALIAS]); - } - if (NULL == utf8_str) { - value = g_strdup(""); - } - else { - value = utf8_to_qq(utf8_str, QQ_CHARSET_DEFAULT); - /* Warnning: value will be string "(NULL)" instead of NULL */ - if (!qq_strcmp("(NULL)", value)) { - value = g_strdup(""); - } - } - g_free(segments[index]); - segments[index] = value; - } - - memo_debug(segments); - /* send segments */ - request_change_memo(gc, bd_uid, segments); - - /* free segments */ - memo_free(segments); - g_free(memo_request); -} - -/* memo modify dialogue */ -static void memo_modify_dialogue(PurpleConnection *gc, UID bd_uid, gchar **segments, guint32 action) -{ - modify_memo_request *memo_request; - PurpleRequestField *field; - PurpleRequestFields *fields; - PurpleRequestFieldGroup *group; - int index; - gchar *utf8_title; - gchar *utf8_primary; - - g_return_if_fail(NULL != gc && NULL != segments); - - switch (action) { - case QQ_BUDDY_MEMO_GET: - memo_free(segments); - break; - case QQ_BUDDY_MEMO_MODIFY: - /* keep one dialog once a time */ - purple_request_close_with_handle(gc); - /* show dialog */ - fields = purple_request_fields_new(); - group = purple_request_field_group_new(NULL); - purple_request_fields_add_group(fields, group); - - for(index = 0; index < QQ_MEMO_SIZE; index++) { - /* - purple_debug_info("QQ", "id:%s txt:%s segment:%s\n", - memo_id[index], memo_txt[index], segments[index]); - */ - field = purple_request_field_string_new(memo_id[index], memo_txt[index], - segments[index], FALSE); - purple_request_field_group_add_field(group, field); - } - - /* for upload cb */ - memo_request = g_new0(modify_memo_request, 1); - memo_request->gc = gc; - memo_request->bd_uid = bd_uid; - memo_request->segments = segments; - /* callback */ - utf8_title = g_strdup(_("Buddy Memo")); - utf8_primary = g_strdup(_("Change his/her memo as you like")); - - purple_request_fields(gc, utf8_title, utf8_primary, NULL, - fields, - _("_Modify"), G_CALLBACK(memo_modify_ok_cb), - _("_Cancel"), G_CALLBACK(memo_modify_cancle_cb), - purple_connection_get_account(gc), NULL, NULL, - memo_request); - - g_free(utf8_title); - g_free(utf8_primary); - break; - default: - purple_debug_info("QQ", "Error...unknown memo action, please tell us\n"); - break; - } -} - -static void qq_create_buddy_memo(PurpleConnection *gc, UID bd_uid, guint32 action) -{ - gchar **segments; - gint index; - g_return_if_fail(NULL != gc); - - segments = g_new0(gchar*, QQ_MEMO_SIZE); - for (index = 0; index < QQ_MEMO_SIZE; index++) { - segments[index] = g_strdup("");; - } - memo_modify_dialogue(gc, bd_uid, segments, action); -} - -/* process reply to get_memo packet - * here, update_class will be regarded as buddy's uid. because some - * memo packages returned without uid, which will make us confused */ -void qq_process_get_buddy_memo(PurpleConnection *gc, guint8* data, gint data_len, - UPDCLS update_class, guint32 action) -{ - gchar **segments; - gint bytes; - gint index; - guint8 rcv_cmd; - guint32 rcv_uid; - guint8 unk1_8; - guint8 is_success; - - g_return_if_fail(NULL != gc && NULL != data && 0 != data_len); - /* - qq_show_packet("MEMO REACH", data, data_len); - */ - purple_debug_info("QQ", "action=0x%02X\n", action); - - bytes = 0; - - /* TX looks a bit clever than before... :) */ - bytes += qq_get8(&rcv_cmd, data+bytes); - purple_debug_info("QQ", "rcv_cmd=0x%02X\n", rcv_cmd); - - /* it's possible that packet contains no buddy uid and no memo!!! - * go to next step according to previous action sent */ - if (1 == data_len) { /* only one byte */ - purple_debug_info("QQ", "memo packet contains no buddy uid and memo...\n"); - if (QQ_BUDDY_MEMO_MODIFY == action) { - UID mod_uid; - mod_uid = (UID)update_class; - qq_create_buddy_memo(gc, mod_uid, QQ_BUDDY_MEMO_MODIFY); - return; - } - return; - } - - switch (rcv_cmd) { - case QQ_BUDDY_MEMO_MODIFY: - case QQ_BUDDY_MEMO_REMOVE: - bytes += qq_get8(&is_success, data+bytes); - if (QQ_BUDDY_MEMO_REQUEST_SUCCESS == is_success) { - purple_notify_message(gc, PURPLE_NOTIFY_MSG_INFO, - _("Memo Modify"), _("Server says:"), - _("Your request was accepted."), - NULL, NULL); - purple_debug_info("QQ", "memo change succeessfully!\n"); - } - else { - purple_notify_message(gc, PURPLE_NOTIFY_MSG_INFO, - _("Memo Modify"), _("Server says:"), - _("Your request was rejected."), - NULL, NULL); - purple_debug_info("QQ", "memo change failed\n"); - } - break; - case QQ_BUDDY_MEMO_GET: - bytes += qq_get32(&rcv_uid, data+bytes); - purple_debug_info("QQ", "rcv_uid=%u\n", rcv_uid); - bytes += qq_get8(&unk1_8, data+bytes); - purple_debug_info("QQ", "unk1_8=0x%02X\n", unk1_8); - segments = g_new0(gchar*, QQ_MEMO_SIZE); - for (index = 0; index < QQ_MEMO_SIZE; index++) { - /* get utf8 string */ - bytes += qq_get_vstr(&segments[index], QQ_CHARSET_DEFAULT, data+bytes); - /* - purple_debug_info("QQ", "bytes:%d, seg:%s\n", bytes, segments[index]); - */ - } - - /* common action, update buddy memo */ - update_buddy_memo(gc, (UID)rcv_uid, segments[QQ_MEMO_ALIAS]); - - /* memo is a thing that we regard our buddy as, so we need one more buddy_uid */ - memo_modify_dialogue(gc, rcv_uid, segments, action); - break; - default: - purple_debug_info("QQ", "received an UNKNOWN memo cmd!!!\n"); - break; - } -} - -/* request buddy memo - * - * param: gc, uid, update_class, action - * here, update_class will be set to buddy's uid. because some memo - * packages returned without uid, which will make us confused */ -void qq_request_buddy_memo(PurpleConnection *gc, UID bd_uid, UPDCLS update_class, guint32 action) -{ - guint8 raw_data[16] = {0}; - gint bytes; - - purple_debug_info("QQ", "qq_request_buddy_memo, buddy uid=%u, update_class=%u\n", - bd_uid, update_class); - g_return_if_fail(NULL != gc); - /* '0' is ok - g_return_if_fail(uid != 0); - */ - bytes = 0; - bytes += qq_put8(raw_data+bytes, QQ_BUDDY_MEMO_GET); - bytes += qq_put32(raw_data+bytes, bd_uid); - /* - qq_show_packet("MEMO REQUEST", raw_data, bytes); - */ - - qq_send_cmd_mess(gc, QQ_CMD_BUDDY_MEMO, (guint8*)raw_data, bytes, update_class, action); -} - - diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/qq/buddy_memo.h --- a/libpurple/protocols/qq/buddy_memo.h Thu May 05 03:40:29 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -/** - * @file buddy_memo.h - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * 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 02111-1301 USA - */ - -#ifndef _QQ_BUDDY_MEMO_H_ -#define _QQ_BUDDY_MEMO_H_ - -#include -#include "connection.h" -#include "blist.h" -#include "qq.h" - -#define QQ_BUDDY_MEMO_REQUEST_SUCCESS 0x00 - -/* clan command for memo */ -enum -{ - QQ_BUDDY_MEMO_MODIFY = 0x01, /* upload memo */ - QQ_BUDDY_MEMO_REMOVE, /* remove memo */ - QQ_BUDDY_MEMO_GET /* get memo */ -}; - - -void qq_process_get_buddy_memo(PurpleConnection *gc, guint8* data, gint data_len, UPDCLS update_class, guint32 action); - -void qq_request_buddy_memo(PurpleConnection *gc, UID bd_uid, UPDCLS update_class, guint32 action); - -#endif - diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/qq/buddy_opt.c --- a/libpurple/protocols/qq/buddy_opt.c Thu May 05 03:40:29 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1290 +0,0 @@ -/** - * @file buddy_opt.c - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * 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 02111-1301 USA - */ - -#include "internal.h" -#include "debug.h" -#include "notify.h" -#include "request.h" -#include "privacy.h" - -#include "buddy_info.h" -#include "buddy_list.h" -#include "buddy_opt.h" -#include "char_conv.h" -#include "qq_define.h" -#include "im.h" -#include "qq_base.h" -#include "packet_parse.h" -#include "qq_network.h" -#include "utils.h" - -#define PURPLE_GROUP_QQ_FORMAT "QQ (%s)" - -#define QQ_REMOVE_SELF_REPLY_OK 0x00 - -enum { - QQ_MY_AUTH_APPROVE = 0x30, /* ASCII value of "0" */ - QQ_MY_AUTH_REJECT = 0x31, /* ASCII value of "1" */ - QQ_MY_AUTH_REQUEST = 0x32 /* ASCII value of "2" */ -}; - -typedef struct _qq_buddy_req { - PurpleConnection *gc; - UID uid; - guint8 *auth; - guint8 auth_len; -} qq_buddy_req; - -void add_buddy_authorize_input(PurpleConnection *gc, UID uid, - guint8 *auth, guint8 auth_len); - -static void buddy_req_free(qq_buddy_req *add_req) -{ - g_return_if_fail(add_req != NULL); - if (add_req->auth) g_free(add_req->auth); - g_free(add_req); -} - -static void buddy_req_cancel_cb(qq_buddy_req *add_req, const gchar *msg) -{ - g_return_if_fail(add_req != NULL); - buddy_req_free(add_req); -} - -PurpleGroup *qq_group_find_or_new(const gchar *group_name) -{ - PurpleGroup *g; - - g_return_val_if_fail(group_name != NULL, NULL); - - g = purple_find_group(group_name); - if (g == NULL) { - g = purple_group_new(group_name); - purple_blist_add_group(g, NULL); - purple_debug_warning("QQ", "Add new group: %s\n", group_name); - } - - return g; -} - -static qq_buddy_data *qq_buddy_data_new(UID uid) -{ - qq_buddy_data *bd = g_new0(qq_buddy_data, 1); - memset(bd, 0, sizeof(qq_buddy_data)); - bd->uid = uid; - bd->status = QQ_BUDDY_OFFLINE; - return bd; -} - -qq_buddy_data *qq_buddy_data_find(PurpleConnection *gc, UID uid) -{ - gchar *who; - PurpleBuddy *buddy; - qq_buddy_data *bd; - - g_return_val_if_fail(gc != NULL, NULL); - - who = uid_to_purple_name(uid); - if (who == NULL) return NULL; - buddy = purple_find_buddy(purple_connection_get_account(gc), who); - g_free(who); - - if (buddy == NULL) { - purple_debug_error("QQ", "Can not find purple buddy of %u\n", uid); - return NULL; - } - - if ((bd = purple_buddy_get_protocol_data(buddy)) == NULL) { - purple_debug_error("QQ", "Can not find buddy data of %u\n", uid); - return NULL; - } - return bd; -} - -void qq_buddy_data_free(qq_buddy_data *bd) -{ - g_return_if_fail(bd != NULL); - - if (bd->nickname) g_free(bd->nickname); - g_free(bd); -} - -/* create purple buddy without data and display with no-auth icon */ -PurpleBuddy *qq_buddy_new(PurpleConnection *gc, UID uid) -{ - PurpleBuddy *buddy; - PurpleGroup *group; - gchar *who; - gchar *group_name; - - g_return_val_if_fail(gc->account != NULL && uid != 0, NULL); - - group_name = g_strdup_printf(PURPLE_GROUP_QQ_FORMAT, - purple_account_get_username(gc->account)); - group = qq_group_find_or_new(group_name); - if (group == NULL) { - purple_debug_error("QQ", "Failed creating group %s\n", group_name); - return NULL; - } - - purple_debug_info("QQ", "Add new purple buddy: [%u]\n", uid); - who = uid_to_purple_name(uid); - buddy = purple_buddy_new(gc->account, who, NULL); /* alias is NULL */ - purple_buddy_set_protocol_data(buddy, NULL); - - g_free(who); - - purple_blist_add_buddy(buddy, NULL, group, NULL); - - g_free(group_name); - - return buddy; -} - -static void qq_buddy_free(PurpleBuddy *buddy) -{ - qq_buddy_data *bd; - - g_return_if_fail(buddy); - - if ((bd = purple_buddy_get_protocol_data(buddy)) != NULL) { - qq_buddy_data_free(bd); - } - purple_buddy_set_protocol_data(buddy, NULL); - purple_blist_remove_buddy(buddy); -} - -PurpleBuddy *qq_buddy_find(PurpleConnection *gc, UID uid) -{ - PurpleBuddy *buddy; - gchar *who; - - g_return_val_if_fail(gc->account != NULL && uid != 0, NULL); - - who = uid_to_purple_name(uid); - buddy = purple_find_buddy(gc->account, who); - g_free(who); - return buddy; -} - -PurpleBuddy *qq_buddy_find_or_new(PurpleConnection *gc, UID uid) -{ - PurpleBuddy *buddy; - qq_buddy_data *bd; - - g_return_val_if_fail(gc->account != NULL && uid != 0, NULL); - - buddy = qq_buddy_find(gc, uid); - if (buddy == NULL) { - buddy = qq_buddy_new(gc, uid); - if (buddy == NULL) { - return NULL; - } - } - - if (purple_buddy_get_protocol_data(buddy) != NULL) { - return buddy; - } - - bd = qq_buddy_data_new(uid); - purple_buddy_set_protocol_data(buddy, bd); - return buddy; -} - -/* send packet to remove a buddy from my buddy list */ -static void request_remove_buddy(PurpleConnection *gc, UID uid) -{ - gchar uid_str[11]; - gint bytes; - - g_return_if_fail(uid > 0); - - g_snprintf(uid_str, sizeof(uid_str), "%u", uid); - bytes = strlen(uid_str); - qq_send_cmd_mess(gc, QQ_CMD_REMOVE_BUDDY, (guint8 *) uid_str, bytes, 0, uid); -} - -static void request_remove_buddy_ex(PurpleConnection *gc, - UID uid, guint8 *auth, guint8 auth_len) -{ - gint bytes; - guint8 *raw_data; - gchar uid_str[16]; - - g_return_if_fail(uid != 0); - g_return_if_fail(auth != NULL && auth_len > 0); - - raw_data = g_newa(guint8, auth_len + sizeof(uid_str) ); - bytes = 0; - bytes += qq_put8(raw_data + bytes, auth_len); - bytes += qq_putdata(raw_data + bytes, auth, auth_len); - - g_snprintf(uid_str, sizeof(uid_str), "%u", uid); - bytes += qq_putdata(raw_data + bytes, (guint8 *)uid_str, strlen(uid_str)); - - qq_send_cmd_mess(gc, QQ_CMD_REMOVE_BUDDY, raw_data, bytes, 0, uid); -} - -void qq_request_auth_code(PurpleConnection *gc, guint8 cmd, guint16 sub_cmd, UID uid) -{ - guint8 raw_data[16]; - gint bytes; - - g_return_if_fail(uid > 0); - bytes = 0; - bytes += qq_put8(raw_data + bytes, cmd); - bytes += qq_put16(raw_data + bytes, sub_cmd); - bytes += qq_put32(raw_data + bytes, uid); - - qq_send_cmd_mess(gc, QQ_CMD_AUTH_CODE, raw_data, bytes, 0, uid); -} - -void qq_process_auth_code(PurpleConnection *gc, guint8 *data, gint data_len, UID uid) -{ - gint bytes; - guint8 cmd, reply; - guint16 sub_cmd; - guint8 *code = NULL; - guint16 code_len = 0; - - g_return_if_fail(data != NULL && data_len != 0); - g_return_if_fail(uid != 0); - - qq_show_packet("qq_process_auth_code", data, data_len); - bytes = 0; - bytes += qq_get8(&cmd, data + bytes); - bytes += qq_get16(&sub_cmd, data + bytes); - bytes += qq_get8(&reply, data + bytes); - g_return_if_fail(bytes + 2 <= data_len); - - bytes += qq_get16(&code_len, data + bytes); - g_return_if_fail(code_len > 0); - g_return_if_fail(bytes + code_len <= data_len); - code = g_newa(guint8, code_len); - bytes += qq_getdata(code, code_len, data + bytes); - - if (cmd == QQ_AUTH_INFO_BUDDY && sub_cmd == QQ_AUTH_INFO_REMOVE_BUDDY) { - request_remove_buddy_ex(gc, uid, code, code_len); - return; - } - if (cmd == QQ_AUTH_INFO_BUDDY && sub_cmd == QQ_AUTH_INFO_ADD_BUDDY) { - add_buddy_authorize_input(gc, uid, code, code_len); - return; - } - purple_debug_info("QQ", "Got auth info cmd 0x%x, sub 0x%x, reply 0x%x\n", - cmd, sub_cmd, reply); -} - -static void add_buddy_question_cb(qq_buddy_req *add_req, const gchar *text) -{ - g_return_if_fail(add_req != NULL); - if (add_req->gc == NULL || add_req->uid == 0) { - buddy_req_free(add_req); - return; - } - - qq_request_question(add_req->gc, QQ_QUESTION_ANSWER, add_req->uid, NULL, text); - buddy_req_free(add_req); -} - -static void add_buddy_question_input(PurpleConnection *gc, UID uid, gchar *question) -{ - gchar *who, *msg; - qq_buddy_req *add_req; - g_return_if_fail(uid != 0); - - add_req = g_new0(qq_buddy_req, 1); - add_req->gc = gc; - add_req->uid = uid; - add_req->auth = NULL; - add_req->auth_len = 0; - - who = uid_to_purple_name(uid); - msg = g_strdup_printf(_("%u requires verification: %s"), uid, question); - purple_request_input(gc, _("Add buddy question"), msg, - _("Enter answer here"), - NULL, - TRUE, FALSE, NULL, - _("Send"), G_CALLBACK(add_buddy_question_cb), - _("Cancel"), G_CALLBACK(buddy_req_cancel_cb), - purple_connection_get_account(gc), who, NULL, - add_req); - - g_free(msg); - g_free(who); -} - -void qq_request_question(PurpleConnection *gc, - guint8 cmd, UID uid, const gchar *question_utf8, const gchar *answer_utf8) -{ - guint8 raw_data[MAX_PACKET_SIZE - 16]; - gint bytes; - - g_return_if_fail(uid > 0); - bytes = 0; - bytes += qq_put8(raw_data + bytes, cmd); - if (cmd == QQ_QUESTION_GET) { - bytes += qq_put8(raw_data + bytes, 0); - qq_send_cmd_mess(gc, QQ_CMD_BUDDY_QUESTION, raw_data, bytes, 0, uid); - return; - } - if (cmd == QQ_QUESTION_SET) { - bytes += qq_put_vstr(raw_data + bytes, question_utf8, QQ_CHARSET_DEFAULT); - bytes += qq_put_vstr(raw_data + bytes, answer_utf8, QQ_CHARSET_DEFAULT); - bytes += qq_put8(raw_data + bytes, 0); - qq_send_cmd_mess(gc, QQ_CMD_BUDDY_QUESTION, raw_data, bytes, 0, uid); - return; - } - /* Unknow 2 bytes, 0x(00 01) */ - bytes += qq_put8(raw_data + bytes, 0x00); - bytes += qq_put8(raw_data + bytes, 0x01); - g_return_if_fail(uid != 0); - bytes += qq_put32(raw_data + bytes, uid); - if (cmd == QQ_QUESTION_REQUEST) { - qq_send_cmd_mess(gc, QQ_CMD_BUDDY_QUESTION, raw_data, bytes, 0, uid); - return; - } - bytes += qq_put_vstr(raw_data + bytes, answer_utf8, QQ_CHARSET_DEFAULT); - bytes += qq_put8(raw_data + bytes, 0); - qq_send_cmd_mess(gc, QQ_CMD_BUDDY_QUESTION, raw_data, bytes, 0, uid); - return; -} - -static void request_add_buddy_by_question(PurpleConnection *gc, UID uid, - guint8 *code, guint16 code_len) -{ - guint8 raw_data[MAX_PACKET_SIZE - 16]; - gint bytes = 0; - - g_return_if_fail(uid != 0 && code_len > 0); - - bytes = 0; - bytes += qq_put8(raw_data + bytes, 0x10); - bytes += qq_put32(raw_data + bytes, uid); - bytes += qq_put16(raw_data + bytes, 0); - - bytes += qq_put8(raw_data + bytes, 0); - bytes += qq_put8(raw_data + bytes, 0); /* no auth code */ - - bytes += qq_put16(raw_data + bytes, code_len); - bytes += qq_putdata(raw_data + bytes, code, code_len); - - bytes += qq_put8(raw_data + bytes, 1); /* ALLOW ADD ME FLAG */ - bytes += qq_put8(raw_data + bytes, 0); /* group number? */ - qq_send_cmd(gc, QQ_CMD_ADD_BUDDY_AUTH_EX, raw_data, bytes); -} - -void qq_process_question(PurpleConnection *gc, guint8 *data, gint data_len, UID uid) -{ - gint bytes; - guint8 cmd, reply; - gchar *question, *answer; - guint16 code_len; - guint8 *code; - - g_return_if_fail(data != NULL && data_len != 0); - - qq_show_packet("qq_process_question", data, data_len); - bytes = 0; - bytes += qq_get8(&cmd, data + bytes); - if (cmd == QQ_QUESTION_GET) { - bytes += qq_get_vstr(&question, QQ_CHARSET_DEFAULT, data + bytes); - bytes += qq_get_vstr(&answer, QQ_CHARSET_DEFAULT, data + bytes); - purple_debug_info("QQ", "Get buddy adding Q&A:\n%s\n%s\n", question, answer); - g_free(question); - g_free(answer); - return; - } - if (cmd == QQ_QUESTION_SET) { - bytes += qq_get8(&reply, data + bytes); - if (reply == 0) { - purple_debug_info("QQ", "Successed setting Q&A\n"); - } else { - purple_debug_warning("QQ", "Failed setting Q&A, reply %d\n", reply); - } - return; - } - - g_return_if_fail(uid != 0); - bytes += 2; /* skip 2 bytes, 0x(00 01)*/ - if (cmd == QQ_QUESTION_REQUEST) { - bytes += qq_get8(&reply, data + bytes); - if (reply == 0x01) { - purple_debug_warning("QQ", "Failed getting question, reply %d\n", reply); - return; - } - bytes += qq_get_vstr(&question, QQ_CHARSET_DEFAULT, data + bytes); - purple_debug_info("QQ", "Get buddy question:\n%s\n", question); - add_buddy_question_input(gc, uid, question); - g_free(question); - return; - } - - if (cmd == QQ_QUESTION_ANSWER) { - bytes += qq_get8(&reply, data + bytes); - if (reply == 0x01) { - purple_notify_error(gc, _("Add Buddy"), _("Invalid answer."), NULL); - return; - } - bytes += qq_get16(&code_len, data + bytes); - g_return_if_fail(code_len > 0); - g_return_if_fail(bytes + code_len <= data_len); - - code = g_newa(guint8, code_len); - bytes += qq_getdata(code, code_len, data + bytes); - request_add_buddy_by_question(gc, uid, code, code_len); - return; - } - - g_return_if_reached(); -} - -/* try to remove myself from someone's buddy list */ -static void request_buddy_remove_me(PurpleConnection *gc, UID uid) -{ - guint8 raw_data[16] = {0}; - gint bytes = 0; - - g_return_if_fail(uid > 0); - - bytes += qq_put32(raw_data + bytes, uid); - - qq_send_cmd_mess(gc, QQ_CMD_REMOVE_ME, raw_data, bytes, 0, uid); -} - -/* try to add a buddy without authentication */ -static void request_add_buddy_no_auth(PurpleConnection *gc, UID uid) -{ - gchar uid_str[11]; - - g_return_if_fail(uid > 0); - - /* we need to send the ascii code of this uid to qq server */ - g_snprintf(uid_str, sizeof(uid_str), "%u", uid); - qq_send_cmd_mess(gc, QQ_CMD_ADD_BUDDY_NO_AUTH, - (guint8 *) uid_str, strlen(uid_str), 0, uid); -} - -static void request_add_buddy_no_auth_ex(PurpleConnection *gc, UID uid) -{ - guint bytes; - guint8 raw_data[16]; - - g_return_if_fail(uid != 0); - - bytes = 0; - bytes += qq_put32(raw_data + bytes, uid); - qq_send_cmd_mess(gc, QQ_CMD_ADD_BUDDY_NO_AUTH_EX, raw_data, bytes, 0, uid); -} - -/* this buddy needs authentication, text conversion is done at lowest level */ -static void request_add_buddy_auth(PurpleConnection *gc, UID uid, const gchar response, const gchar *text) -{ - guint8 raw_data[MAX_PACKET_SIZE - 16]; - gint bytes; - gchar *msg, uid_str[11]; - guint8 bar; - - g_return_if_fail(uid != 0); - - g_snprintf(uid_str, sizeof(uid_str), "%u", uid); - bar = 0x1f; - - bytes = 0; - bytes += qq_putdata(raw_data + bytes, (guint8 *) uid_str, strlen(uid_str)); - bytes += qq_put8(raw_data + bytes, bar); - bytes += qq_put8(raw_data + bytes, response); - - if (text != NULL) { - msg = utf8_to_qq(text, QQ_CHARSET_DEFAULT); - bytes += qq_put8(raw_data + bytes, bar); - bytes += qq_putdata(raw_data + bytes, (guint8 *) msg, strlen(msg)); - g_free(msg); - } - - qq_send_cmd(gc, QQ_CMD_ADD_BUDDY_AUTH, raw_data, bytes); -} - -static void request_add_buddy_auth_ex(PurpleConnection *gc, UID uid, - const gchar *text, guint8 *auth, guint8 auth_len) -{ - guint8 raw_data[MAX_PACKET_SIZE - 16]; - gint bytes = 0; - - g_return_if_fail(uid != 0); - - bytes = 0; - bytes += qq_put8(raw_data + bytes, 0x02); - bytes += qq_put32(raw_data + bytes, uid); - bytes += qq_put16(raw_data + bytes, 0); - - bytes += qq_put8(raw_data + bytes, 0); - if (auth == NULL || auth_len <= 0) { - bytes += qq_put8(raw_data + bytes, 0); - } else { - bytes += qq_put8(raw_data + bytes, auth_len); - bytes += qq_putdata(raw_data + bytes, auth, auth_len); - } - bytes += qq_put8(raw_data + bytes, 1); /* ALLOW ADD ME FLAG */ - bytes += qq_put8(raw_data + bytes, 0); /* group number? */ - bytes += qq_put_vstr(raw_data + bytes, text, QQ_CHARSET_DEFAULT); - qq_send_cmd(gc, QQ_CMD_ADD_BUDDY_AUTH_EX, raw_data, bytes); -} - -void qq_process_add_buddy_auth_ex(PurpleConnection *gc, guint8 *data, gint data_len, guint32 ship32) -{ - g_return_if_fail(data != NULL && data_len != 0); - - qq_show_packet("qq_process_question", data, data_len); -} - -static void add_buddy_auth_cb(qq_buddy_req *add_req, const gchar *text) -{ - qq_data *qd; - g_return_if_fail(add_req != NULL); - if (add_req->gc == NULL || add_req->uid == 0) { - buddy_req_free(add_req); - return; - } - - qd = (qq_data *)add_req->gc->proto_data; - if (qd->client_version > 2005) { - request_add_buddy_auth_ex(add_req->gc, add_req->uid, - text, add_req->auth, add_req->auth_len); - } else { - request_add_buddy_auth(add_req->gc, add_req->uid, QQ_MY_AUTH_REQUEST, text); - } - buddy_req_free(add_req); -} - -/* the real packet to reject and request is sent from here */ -static void buddy_add_deny_reason_cb(qq_buddy_req *add_req, const gchar *reason) -{ - g_return_if_fail(add_req != NULL); - if (add_req->gc == NULL || add_req->uid == 0) { - buddy_req_free(add_req); - return; - } - - request_add_buddy_auth(add_req->gc, add_req->uid, QQ_MY_AUTH_REJECT, reason); - buddy_req_free(add_req); -} - -static void buddy_add_deny_noreason_cb(qq_buddy_req *add_req) -{ - buddy_add_deny_reason_cb(add_req, NULL); -} - -/* we approve other's request of adding me as friend */ -static void buddy_add_authorize_cb(gpointer data) -{ - qq_buddy_req *add_req = (qq_buddy_req *)data; - - g_return_if_fail(add_req != NULL); - if (add_req->gc == NULL || add_req->uid == 0) { - buddy_req_free(add_req); - return; - } - - request_add_buddy_auth(add_req->gc, add_req->uid, QQ_MY_AUTH_APPROVE, NULL); - buddy_req_free(add_req); -} - -/* we reject other's request of adding me as friend */ -static void buddy_add_deny_cb(gpointer data) -{ - qq_buddy_req *add_req = (qq_buddy_req *)data; - gchar *who = uid_to_purple_name(add_req->uid); - purple_request_input(add_req->gc, NULL, _("Authorization denied message:"), - NULL, _("Sorry, you're not my style."), TRUE, FALSE, NULL, - _("OK"), G_CALLBACK(buddy_add_deny_reason_cb), - _("Cancel"), G_CALLBACK(buddy_add_deny_noreason_cb), - purple_connection_get_account(add_req->gc), who, NULL, - add_req); - g_free(who); -} - -static void add_buddy_no_auth_cb(qq_buddy_req *add_req) -{ - qq_data *qd; - g_return_if_fail(add_req != NULL); - if (add_req->gc == NULL || add_req->uid == 0) { - buddy_req_free(add_req); - return; - } - - qd = (qq_data *) add_req->gc->proto_data; - if (qd->client_version > 2005) { - request_add_buddy_no_auth_ex(add_req->gc, add_req->uid); - } else { - request_add_buddy_no_auth(add_req->gc, add_req->uid); - } - buddy_req_free(add_req); -} - -void add_buddy_authorize_input(PurpleConnection *gc, UID uid, - guint8 *auth, guint8 auth_len) -{ - gchar *who, *msg; - qq_buddy_req *add_req; - g_return_if_fail(uid != 0); - - add_req = g_new0(qq_buddy_req, 1); - add_req->gc = gc; - add_req->uid = uid; - add_req->auth = NULL; - add_req->auth_len = 0; - if (auth != NULL && auth_len > 0) { - add_req->auth = g_new0(guint8, auth_len); - g_memmove(add_req->auth, auth, auth_len); - add_req->auth_len = auth_len; - } - - who = uid_to_purple_name(uid); - msg = g_strdup_printf(_("%u needs authorization"), uid); - purple_request_input(gc, _("Add buddy authorize"), msg, - _("Enter request here"), - _("Would you be my friend?"), - TRUE, FALSE, NULL, - _("Send"), G_CALLBACK(add_buddy_auth_cb), - _("Cancel"), G_CALLBACK(buddy_req_cancel_cb), - purple_connection_get_account(gc), who, NULL, - add_req); - - g_free(msg); - g_free(who); -} - -/* add a buddy and send packet to QQ server - * note that when purple load local cached buddy list into its blist - * it also calls this funtion, so we have to - * define qd->is_login=TRUE AFTER LOGIN */ -void qq_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group) -{ - qq_data *qd; - UID uid; - - g_return_if_fail(NULL != gc && NULL != gc->proto_data); - g_return_if_fail(buddy != NULL); - - qd = (qq_data *) gc->proto_data; - if (!qd->is_login) - return; /* IMPORTANT ! */ - - uid = purple_name_to_uid(purple_buddy_get_name(buddy)); - if (uid > 0) { - if (qd->client_version > 2005) { - request_add_buddy_no_auth_ex(gc, uid); - } else { - request_add_buddy_no_auth(gc, uid); - } - return; - } - - purple_notify_error(gc, _("QQ Buddy"), _("Add buddy"), _("Invalid QQ Number")); - if (buddy == NULL) { - return; - } - - purple_debug_info("QQ", "Remove buddy with invalid QQ number %u\n", uid); - qq_buddy_free(buddy); -} - -/* process reply to add_buddy_auth request */ -void qq_process_add_buddy_auth(guint8 *data, gint data_len, PurpleConnection *gc) -{ - gchar **segments, *msg_utf8; - - g_return_if_fail(data != NULL && data_len != 0); - - if (data[0] == '0') { - purple_debug_info("QQ", "Reply OK for sending authorize\n"); - return; - } - - if (NULL == (segments = split_data(data, data_len, "\x1f", 2))) { - purple_notify_error(gc, _("QQ Buddy"), _("Failed sending authorize"), NULL); - return; - } - msg_utf8 = qq_to_utf8(segments[1], QQ_CHARSET_DEFAULT); - purple_notify_error(gc, _("QQ Buddy"), _("Failed sending authorize"), msg_utf8); - g_free(msg_utf8); -} - -/* process the server reply for my request to remove a buddy */ -void qq_process_remove_buddy(PurpleConnection *gc, guint8 *data, gint data_len, UID uid) -{ - PurpleBuddy *buddy = NULL; - gchar *msg; - - g_return_if_fail(data != NULL && data_len != 0); - g_return_if_fail(uid != 0); - - buddy = qq_buddy_find(gc, uid); - if (data[0] != 0) { - msg = g_strdup_printf(_("Failed removing buddy %u"), uid); - purple_notify_info(gc, _("QQ Buddy"), msg, NULL); - g_free(msg); - } - - purple_debug_info("QQ", "Reply OK for removing buddy\n"); - /* remove buddy again */ - if (buddy != NULL) { - qq_buddy_free(buddy); - } -} - -/* process the server reply for my request to remove myself from a buddy */ -void qq_process_buddy_remove_me(PurpleConnection *gc, guint8 *data, gint data_len, UID uid) -{ - gchar *msg; - - g_return_if_fail(data != NULL && data_len != 0); - - if (data[0] == 0) { - purple_debug_info("QQ", "Reply OK for removing me from %u's buddy list\n", uid); - return; - } - msg = g_strdup_printf(_("Failed removing me from %d's buddy list"), uid); - purple_notify_info(gc, _("QQ Buddy"), msg, NULL); - g_free(msg); -} - -void qq_process_add_buddy_no_auth(PurpleConnection *gc, - guint8 *data, gint data_len, UID uid) -{ - qq_data *qd; - gchar **segments; - gchar *dest_uid, *reply; - PurpleBuddy *buddy; - qq_buddy_data *bd; - - g_return_if_fail(data != NULL && data_len != 0); - g_return_if_fail(uid != 0); - - qd = (qq_data *) gc->proto_data; - - purple_debug_info("QQ", "Process buddy add for id [%u]\n", uid); - qq_show_packet("buddy_add_no_auth", data, data_len); - - if (NULL == (segments = split_data(data, data_len, "\x1f", 2))) - return; - - dest_uid = segments[0]; - reply = segments[1]; - if (strtoul(dest_uid, NULL, 10) != qd->uid) { /* should not happen */ - purple_debug_error("QQ", "Add buddy reply is to [%s], not me!\n", dest_uid); - g_strfreev(segments); - return; - } - - if (strtol(reply, NULL, 10) == 0) { - /* add OK */ - qq_buddy_find_or_new(gc, uid); - - qq_request_buddy_info(gc, uid, 0, 0); - if (qd->client_version >= 2007) { - qq_request_get_level_2007(gc, uid); - } else { - qq_request_get_level(gc, uid); - } - qq_request_get_buddies_online(gc, 0, 0); - - purple_debug_info("QQ", "Successed adding into %u's buddy list\n", uid); - g_strfreev(segments); - return; - } - - /* need auth */ - purple_debug_warning("QQ", "Failed adding buddy, need authorize\n"); - - buddy = qq_buddy_find(gc, uid); - if (buddy == NULL) { - buddy = qq_buddy_new(gc, uid); - } - if (buddy != NULL && (bd = purple_buddy_get_protocol_data(buddy)) != NULL) { - /* Not authorized now, free buddy data */ - qq_buddy_data_free(bd); - purple_buddy_set_protocol_data(buddy, NULL); - } - - add_buddy_authorize_input(gc, uid, NULL, 0); - g_strfreev(segments); -} - -void qq_process_add_buddy_no_auth_ex(PurpleConnection *gc, - guint8 *data, gint data_len, UID uid) -{ - qq_data *qd; - gint bytes; - UID dest_uid; - guint8 reply; - guint8 auth_type; - - g_return_if_fail(data != NULL && data_len >= 5); - g_return_if_fail(uid != 0); - - qd = (qq_data *) gc->proto_data; - - purple_debug_info("QQ", "Process buddy add no auth for id [%u]\n", uid); - qq_show_packet("buddy_add_no_auth_ex", data, data_len); - - bytes = 0; - bytes += qq_get32(&dest_uid, data + bytes); - bytes += qq_get8(&reply, data + bytes); - - g_return_if_fail(dest_uid == uid); - - if (reply == 0x99) { - purple_debug_info("QQ", "Successfully added buddy %u\n", uid); - qq_buddy_find_or_new(gc, uid); - - qq_request_buddy_info(gc, uid, 0, 0); - if (qd->client_version >= 2007) { - qq_request_get_level_2007(gc, uid); - } else { - qq_request_get_level(gc, uid); - } - qq_request_get_buddies_online(gc, 0, 0); - return; - } - - if (reply != 0) { - purple_debug_info("QQ", "Failed adding buddy %u, Unknown reply 0x%02X\n", - uid, reply); - } - - /* need auth */ - g_return_if_fail(data_len > bytes); - bytes += qq_get8(&auth_type, data + bytes); - purple_debug_warning("QQ", "Adding buddy needs authorize 0x%02X\n", auth_type); - - switch (auth_type) { - case 0x00: /* no authorize */ - break; - case 0x01: /* authorize */ - qq_request_auth_code(gc, QQ_AUTH_INFO_BUDDY, QQ_AUTH_INFO_ADD_BUDDY, uid); - break; - case 0x02: /* disable */ - break; - case 0x03: /* answer question */ - qq_request_question(gc, QQ_QUESTION_REQUEST, uid, NULL, NULL); - break; - default: - g_return_if_reached(); - break; - } - return; -} - -/* remove a buddy and send packet to QQ server accordingly */ -void qq_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group) -{ - qq_data *qd; - qq_buddy_data *bd; - UID uid; - - g_return_if_fail(gc != NULL && gc->proto_data != NULL); - g_return_if_fail(buddy != NULL); - - qd = (qq_data *) gc->proto_data; - if (!qd->is_login) - return; - - uid = purple_name_to_uid(purple_buddy_get_name(buddy)); - if (uid > 0 && uid != qd->uid) { - if (qd->client_version > 2005) { - qq_request_auth_code(gc, QQ_AUTH_INFO_BUDDY, QQ_AUTH_INFO_REMOVE_BUDDY, uid); - } else { - request_remove_buddy(gc, uid); - request_buddy_remove_me(gc, uid); - } - } - - if ((bd = purple_buddy_get_protocol_data(buddy)) != NULL) { - qq_buddy_data_free(bd); - purple_buddy_set_protocol_data(buddy, NULL); - } else { - purple_debug_warning("QQ", "Empty buddy data of %s\n", purple_buddy_get_name(buddy)); - } - - /* Do not call purple_blist_remove_buddy, - * otherwise purple segmentation fault */ -} - -static void buddy_add_input(PurpleConnection *gc, UID uid, gchar *reason) -{ - PurpleAccount *account = purple_connection_get_account(gc); - qq_buddy_req *add_req; - gchar *who; - - g_return_if_fail(uid != 0 && reason != NULL); - - purple_debug_info("QQ", "Buddy %u request adding, msg: %s\n", uid, reason); - - add_req = g_new0(qq_buddy_req, 1); - add_req->gc = gc; - add_req->uid = uid; - - if (purple_prefs_get_bool("/plugins/prpl/qq/auto_get_authorize_info")) { - qq_request_buddy_info(gc, add_req->uid, 0, QQ_BUDDY_INFO_DISPLAY); - } - who = uid_to_purple_name(add_req->uid); - - purple_account_request_authorization(account, - who, NULL, - NULL, reason, - purple_find_buddy(account, who) != NULL, - buddy_add_authorize_cb, - buddy_add_deny_cb, - add_req); - - g_free(who); -} - -/* someone wants to add you to his buddy list */ -static void server_buddy_add_request(PurpleConnection *gc, gchar *from, gchar *to, - guint8 *data, gint data_len) -{ - UID uid; - gchar *msg, *reason; - - g_return_if_fail(from != NULL && to != NULL); - uid = strtoul(from, NULL, 10); - g_return_if_fail(uid != 0); - - if (purple_prefs_get_bool("/plugins/prpl/qq/auto_get_authorize_info")) { - qq_request_buddy_info(gc, uid, 0, QQ_BUDDY_INFO_DISPLAY); - } - - if (data_len <= 0) { - reason = g_strdup( _("No reason given") ); - } else { - msg = g_strndup((gchar *)data, data_len); - reason = qq_to_utf8(msg, QQ_CHARSET_DEFAULT); - if (reason == NULL) reason = g_strdup( _("Unknown reason") ); - g_free(msg); - } - - buddy_add_input(gc, uid, reason); - g_free(reason); -} - -void qq_process_buddy_check_code(PurpleConnection *gc, guint8 *data, gint data_len) -{ - gint bytes; - guint8 cmd; - guint8 reply; - UID uid; - guint16 flag1, flag2; - - g_return_if_fail(data != NULL && data_len >= 5); - - qq_show_packet("buddy_check_code", data, data_len); - - bytes = 0; - bytes += qq_get8(&cmd, data + bytes); /* 0x03 */ - bytes += qq_get8(&reply, data + bytes); - - if (reply == 0) { - purple_debug_info("QQ", "Failed checking code\n"); - return; - } - - bytes += qq_get32(&uid, data + bytes); - g_return_if_fail(uid != 0); - bytes += qq_get16(&flag1, data + bytes); - bytes += qq_get16(&flag2, data + bytes); - purple_debug_info("QQ", "Check code reply Ok, uid %u, flag 0x%04X-0x%04X\n", - uid, flag1, flag2); - return; -} - -static void request_buddy_check_code(PurpleConnection *gc, - gchar *from, guint8 *code, gint code_len) -{ - guint8 *raw_data; - gint bytes; - UID uid; - - g_return_if_fail(code != NULL && code_len > 0 && from != NULL); - - uid = strtoul(from, NULL, 10); - raw_data = g_newa(guint8, code_len + 16); - bytes = 0; - bytes += qq_put8(raw_data + bytes, 0x03); - bytes += qq_put8(raw_data + bytes, 0x01); - bytes += qq_put32(raw_data + bytes, uid); - bytes += qq_put16(raw_data + bytes, code_len); - bytes += qq_putdata(raw_data + bytes, code, code_len); - - qq_send_cmd(gc, QQ_CMD_BUDDY_CHECK_CODE, raw_data, bytes); -} - -static gint server_buddy_check_code(PurpleConnection *gc, - gchar *from, guint8 *data, gint data_len) -{ - gint bytes; - guint16 code_len; - guint8 *code; - - g_return_val_if_fail(data != NULL && data_len > 0, 0); - - bytes = 0; - bytes += qq_get16(&code_len, data + bytes); - if (code_len <= 0) { - purple_debug_info("QQ", "Server msg for buddy has no code\n"); - return bytes; - } - if (bytes + code_len < data_len) { - purple_debug_error("QQ", "Code len error in server msg for buddy\n"); - qq_show_packet("server_buddy_check_code", data, data_len); - code_len = data_len - bytes; - } - code = g_newa(guint8, code_len); - bytes += qq_getdata(code, code_len, data + bytes); - - request_buddy_check_code(gc, from, code, code_len); - return bytes; -} - -static void server_buddy_add_request_ex(PurpleConnection *gc, gchar *from, gchar *to, - guint8 *data, gint data_len) -{ - gint bytes; - UID uid; - gchar *msg; - guint8 allow_reverse; - - g_return_if_fail(from != NULL && to != NULL); - g_return_if_fail(data != NULL && data_len >= 3); - uid = strtoul(from, NULL, 10); - g_return_if_fail(uid != 0); - - /* qq_show_packet("server_buddy_add_request_ex", data, data_len); */ - - bytes = 0; - bytes += qq_get_vstr(&msg, QQ_CHARSET_DEFAULT, data+bytes); - bytes += qq_get8(&allow_reverse, data + bytes); /* allow_reverse = 0x01, allowed */ - server_buddy_check_code(gc, from, data + bytes, data_len - bytes); - - if (strlen(msg) <= 0) { - g_free(msg); - msg = g_strdup( _("No reason given") ); - } - buddy_add_input(gc, uid, msg); - g_free(msg); -} - -/* when you are added by a person, QQ server will send sys message */ -static void server_buddy_added(PurpleConnection *gc, gchar *from, gchar *to, - guint8 *data, gint data_len) -{ - PurpleAccount *account = purple_connection_get_account(gc); - PurpleBuddy *buddy; - UID uid; - qq_buddy_req *add_req; - gchar *who; - gchar *primary; - - g_return_if_fail(from != NULL && to != NULL); - - uid = strtoul(from, NULL, 10); - who = uid_to_purple_name(uid); - - buddy = purple_find_buddy(account, who); - if (buddy != NULL) { - purple_account_notify_added(account, from, to, NULL, NULL); - } - - add_req = g_new0(qq_buddy_req, 1); - add_req->gc = gc; - add_req->uid = uid; /* only need to get value */ - primary = g_strdup_printf(_("You have been added by %s"), from); - purple_request_action(gc, NULL, primary, - _("Would you like to add him?"), - PURPLE_DEFAULT_ACTION_NONE, - purple_connection_get_account(gc), who, NULL, - add_req, 2, - _("Add"), G_CALLBACK(add_buddy_no_auth_cb), - _("Cancel"), G_CALLBACK(buddy_req_cancel_cb)); - - g_free(who); - g_free(primary); -} - -static void server_buddy_added_ex(PurpleConnection *gc, gchar *from, gchar *to, - guint8 *data, gint data_len) -{ - gint bytes; - guint8 allow_reverse; - gchar *msg; - - g_return_if_fail(from != NULL && to != NULL); - g_return_if_fail(data != NULL && data_len >= 3); - - qq_show_packet("server_buddy_added_ex", data, data_len); - - bytes = 0; - bytes += qq_get_vstr(&msg, QQ_CHARSET_DEFAULT, data+bytes); /* always empty msg */ - purple_debug_info("QQ", "Buddy added msg: %s\n", msg); - bytes += qq_get8(&allow_reverse, data + bytes); /* allow_reverse = 0x01, allowed */ - server_buddy_check_code(gc, from, data + bytes, data_len - bytes); - - g_free(msg); -} - -static void server_buddy_adding_ex(PurpleConnection *gc, gchar *from, gchar *to, - guint8 *data, gint data_len) -{ - gint bytes; - guint8 allow_reverse; - - g_return_if_fail(from != NULL && to != NULL); - g_return_if_fail(data != NULL && data_len >= 3); - - qq_show_packet("server_buddy_adding_ex", data, data_len); - - bytes = 0; - bytes += qq_get8(&allow_reverse, data + bytes); /* allow_reverse = 0x01, allowed */ - server_buddy_check_code(gc, from, data + bytes, data_len - bytes); -} - -/* the buddy approves your request of adding him/her as your friend */ -static void server_buddy_added_me(PurpleConnection *gc, gchar *from, gchar *to, - guint8 *data, gint data_len) -{ - PurpleAccount *account = purple_connection_get_account(gc); - qq_data *qd; - UID uid; - - g_return_if_fail(from != NULL && to != NULL); - - qd = (qq_data *) gc->proto_data; - - uid = strtoul(from, NULL, 10); - g_return_if_fail(uid > 0); - - server_buddy_check_code(gc, from, data, data_len); - - qq_buddy_find_or_new(gc, uid); - qq_request_buddy_info(gc, uid, 0, 0); - qq_request_get_buddies_online(gc, 0, 0); - if (qd->client_version >= 2007) { - qq_request_get_level_2007(gc, uid); - } else { - qq_request_get_level(gc, uid); - } - - purple_account_notify_added(account, to, from, NULL, NULL); -} - -/* you are rejected by the person */ -static void server_buddy_rejected_me(PurpleConnection *gc, gchar *from, gchar *to, - guint8 *data, gint data_len) -{ - UID uid; - PurpleBuddy *buddy; - gchar *msg, *msg_utf8; - gint bytes; - gchar **segments; - gchar *primary, *secondary; - qq_buddy_data *bd; - - g_return_if_fail(from != NULL && to != NULL); - - qq_show_packet("server_buddy_rejected_me", data, data_len); - - if (data_len <= 0) { - msg = g_strdup( _("No reason given") ); - } else { - segments = g_strsplit((gchar *)data, "\x1f", 1); - if (segments != NULL && segments[0] != NULL) { - msg = g_strdup(segments[0]); - g_strfreev(segments); - bytes = strlen(msg) + 1; - if (bytes < data_len) { - server_buddy_check_code(gc, from, data + bytes, data_len - bytes); - } - } else { - msg = g_strdup( _("No reason given") ); - } - } - msg_utf8 = qq_to_utf8(msg, QQ_CHARSET_DEFAULT); - if (msg_utf8 == NULL) { - msg_utf8 = g_strdup( _("Unknown reason") ); - } - g_free(msg); - - primary = g_strdup_printf(_("Rejected by %s"), from); - secondary = g_strdup_printf(_("Message: %s"), msg_utf8); - - purple_notify_info(gc, _("QQ Buddy"), primary, secondary); - - g_free(msg_utf8); - g_free(primary); - g_free(secondary); - - uid = strtoul(from, NULL, 10); - g_return_if_fail(uid != 0); - - buddy = qq_buddy_find(gc, uid); - if (buddy != NULL && (bd = purple_buddy_get_protocol_data(buddy)) != NULL) { - /* Not authorized now, free buddy data */ - qq_buddy_data_free(bd); - purple_buddy_set_protocol_data(buddy, NULL); - } -} - -void qq_process_buddy_from_server(PurpleConnection *gc, int funct, - gchar *from, gchar *to, guint8 *data, gint data_len) -{ - switch (funct) { - case QQ_SERVER_BUDDY_ADDED: - server_buddy_added(gc, from, to, data, data_len); - break; - case QQ_SERVER_BUDDY_ADD_REQUEST: - server_buddy_add_request(gc, from, to, data, data_len); - break; - case QQ_SERVER_BUDDY_ADD_REQUEST_EX: - server_buddy_add_request_ex(gc, from, to, data, data_len); - break; - case QQ_SERVER_BUDDY_ADDED_ME: - server_buddy_added_me(gc, from, to, data, data_len); - break; - case QQ_SERVER_BUDDY_REJECTED_ME: - server_buddy_rejected_me(gc, from, to, data, data_len); - break; - case QQ_SERVER_BUDDY_ADDED_EX: - server_buddy_added_ex(gc, from, to, data, data_len); - break; - case QQ_SERVER_BUDDY_ADDING_EX: - case QQ_SERVER_BUDDY_ADDED_ANSWER: - server_buddy_adding_ex(gc, from, to, data, data_len); - break; - default: - purple_debug_warning("QQ", "Unknow buddy operate (%d) from server\n", funct); - break; - } -} diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/qq/buddy_opt.h --- a/libpurple/protocols/qq/buddy_opt.h Thu May 05 03:40:29 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,84 +0,0 @@ -/** - * @file buddy_opt.h - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * 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 02111-1301 USA - */ - -#ifndef _QQ_BUDDY_OPT_H_ -#define _QQ_BUDDY_OPT_H_ - -#include -#include "connection.h" - -#include "qq.h" - -enum { - QQ_AUTH_INFO_BUDDY = 0x01, - QQ_AUTH_INFO_ROOM = 0x02, - - QQ_AUTH_INFO_ADD_BUDDY = 0x0001, - QQ_AUTH_INFO_TEMP_SESSION = 0x0003, - QQ_AUTH_INFO_CLUSTER = 0x0002, - QQ_AUTH_INFO_REMOVE_BUDDY = 0x0006, - QQ_AUTH_INFO_UPDATE_BUDDY_INFO = 0x0007 -}; - -enum { - QQ_QUESTION_GET = 0x01, - QQ_QUESTION_SET = 0x02, - QQ_QUESTION_REQUEST = 0x03, /* get question only*/ - QQ_QUESTION_ANSWER = 0x04 -}; - -void qq_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group); -void qq_change_buddys_group(PurpleConnection *gc, const char *who, - const char *old_group, const char *new_group); -void qq_remove_buddy_and_me(PurpleBlistNode * node); -void qq_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group); - -void qq_process_remove_buddy(PurpleConnection *gc, guint8 *data, gint data_len, UID uid); -void qq_process_buddy_remove_me(PurpleConnection *gc, guint8 *data, gint data_len, UID uid); -void qq_process_add_buddy_no_auth(PurpleConnection *gc, - guint8 *data, gint data_len, UID uid); -void qq_process_add_buddy_no_auth_ex(PurpleConnection *gc, - guint8 *data, gint data_len, UID uid); -void qq_process_add_buddy_auth(guint8 *data, gint data_len, PurpleConnection *gc); -void qq_process_buddy_from_server(PurpleConnection *gc, int funct, - gchar *from, gchar *to, guint8 *data, gint data_len); - -void qq_process_buddy_check_code(PurpleConnection *gc, guint8 *data, gint data_len); - -void qq_request_auth_code(PurpleConnection *gc, guint8 cmd, guint16 sub_cmd, UID uid); -void qq_process_auth_code(PurpleConnection *gc, guint8 *data, gint data_len, UID uid); -void qq_request_question(PurpleConnection *gc, - guint8 cmd, UID uid, const gchar *question_utf8, const gchar *answer_utf8); -void qq_process_question(PurpleConnection *gc, guint8 *data, gint data_len, UID uid); - -void qq_process_add_buddy_auth_ex(PurpleConnection *gc, guint8 *data, gint data_len, guint32 ship32); - -qq_buddy_data *qq_buddy_data_find(PurpleConnection *gc, UID uid); -void qq_buddy_data_free(qq_buddy_data *bd); - -PurpleBuddy *qq_buddy_new(PurpleConnection *gc, UID uid); -PurpleBuddy *qq_buddy_find_or_new(PurpleConnection *gc, UID uid); -PurpleBuddy *qq_buddy_find(PurpleConnection *gc, UID uid); -PurpleGroup *qq_group_find_or_new(const gchar *group_name); -#endif diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/qq/char_conv.c --- a/libpurple/protocols/qq/char_conv.c Thu May 05 03:40:29 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,115 +0,0 @@ -/** - * @file char_conv.c - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * 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 02111-1301 USA - */ - -#include "internal.h" -#include "debug.h" - -#include "char_conv.h" -#include "packet_parse.h" -#include "utils.h" - -#define UTF8 "UTF-8" -#define QQ_CHARSET_ZH_CN "GB18030" -#define QQ_CHARSET_ENG "ISO-8859-1" - -#define QQ_NULL_MSG "(NULL)" /* return this if conversion fails */ - -/* convert a string from from_charset to to_charset, using g_convert */ -/* Warning: do not return NULL */ -static gchar *do_convert(const gchar *str, gssize len, guint8 *out_len, const gchar *to_charset, const gchar *from_charset) -{ - GError *error = NULL; - gchar *ret; - gsize byte_read, byte_write; - - g_return_val_if_fail(str != NULL && to_charset != NULL && from_charset != NULL, g_strdup(QQ_NULL_MSG)); - - ret = g_convert(str, len, to_charset, from_charset, &byte_read, &byte_write, &error); - - if (error == NULL) { - if (out_len) - *out_len = byte_write; - return ret; /* convert is OK */ - } - - /* convert error */ - purple_debug_error("QQ_CONVERT", "%s\n", error->message); - qq_show_packet("Dump failed text", (guint8 *) str, (len == -1) ? strlen(str) : len); - - g_error_free(error); - return g_strdup(QQ_NULL_MSG); -} - -/* - * take the input as a pascal string and return a converted c-string in UTF-8 - * returns the number of bytes read, return -1 if fatal error - * the converted UTF-8 will be saved in ret - * Return: *ret != NULL - */ -gint qq_get_vstr(gchar **ret, const gchar *from_charset, guint8 *data) -{ - gssize len; - guint8 out_len; - - g_return_val_if_fail(data != NULL && from_charset != NULL, -1); - - len = data[0]; - if (len == 0) { - *ret = g_strdup(""); - return 1; - } - *ret = do_convert((gchar *) (data + 1), len, &out_len, UTF8, from_charset); - - return out_len + 1; -} - -gint qq_put_vstr(guint8 *buf, const gchar *str_utf8, const gchar *to_charset) -{ - gchar *str; - guint8 len; - - if (str_utf8 == NULL || str_utf8[0] == '\0') { - buf[0] = 0; - return 1; - } - str = do_convert(str_utf8, -1, &len, to_charset, UTF8); - buf[0] = len; - if (len > 0) { - memcpy(buf + 1, str, len); - } - return 1 + len; -} - -/* Warning: do not return NULL */ -gchar *utf8_to_qq(const gchar *str, const gchar *to_charset) -{ - return do_convert(str, -1, NULL, to_charset, UTF8); -} - -/* Warning: do not return NULL */ -gchar *qq_to_utf8(const gchar *str, const gchar *from_charset) -{ - return do_convert(str, -1, NULL, UTF8, from_charset); -} - diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/qq/char_conv.h --- a/libpurple/protocols/qq/char_conv.h Thu May 05 03:40:29 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +0,0 @@ -/** - * @file char_conv.h - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * 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 02111-1301 USA - */ - -#ifndef _QQ_CHAR_CONV_H_ -#define _QQ_CHAR_CONV_H_ - -#include - -#define QQ_CHARSET_DEFAULT "GB18030" - -gint qq_get_vstr(gchar **ret, const gchar *from_charset, guint8 *data); -gint qq_put_vstr(guint8 *buf, const gchar *str_utf8, const gchar *to_charset); - -gchar *utf8_to_qq(const gchar *str, const gchar *to_charset); -gchar *qq_to_utf8(const gchar *str, const gchar *from_charset); - -#endif diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/qq/file_trans.c --- a/libpurple/protocols/qq/file_trans.c Thu May 05 03:40:29 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,817 +0,0 @@ -/** - * @file file_trans.c - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * 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 02111-1301 USA - */ - -#include "internal.h" - -#include "debug.h" -#include "ft.h" -#include "cipher.h" - -#include "qq_crypt.h" -#include "file_trans.h" -#include "qq_define.h" -#include "im.h" -#include "packet_parse.h" -#include "proxy.h" -#include "qq_network.h" -#include "send_file.h" -#include "utils.h" - -typedef struct _qq_file_header { - guint16 client_ver; - guint8 file_key; - UID sender_uid; - UID receiver_uid; -} qq_file_header; - -static guint32 _get_file_key(guint8 seed) -{ - guint32 key; - key = seed | (seed << 8) | (seed << 16) | (seed << 24); - return key; -} - -static guint32 _gen_file_key(void) -{ - guint8 seed; - - seed = rand() & 0xFF; - return _get_file_key(seed); -} - -static guint32 _decrypt_qq_uid(UID uid, guint32 key) -{ - return ~(uid ^ key); -} - -static guint32 _encrypt_qq_uid(UID uid, guint32 key) -{ - return (~uid) ^ key; -} - -static void _fill_file_md5(const gchar *filename, gint filelen, guint8 *md5) -{ - FILE *fp; - guint8 *buffer; - size_t wc; - - const gint QQ_MAX_FILE_MD5_LENGTH = 10002432; - - g_return_if_fail(filename != NULL && md5 != NULL); - if (filelen > QQ_MAX_FILE_MD5_LENGTH) - filelen = QQ_MAX_FILE_MD5_LENGTH; - - fp = g_fopen(filename, "rb"); - g_return_if_fail(fp != NULL); - - buffer = g_newa(guint8, filelen); - g_return_if_fail(buffer != NULL); - wc = fread(buffer, filelen, 1, fp); - fclose(fp); - if (wc != 1) { - purple_debug_error("qq", "Unable to read file: %s\n", filename); - - /* TODO: XXX: Really, the caller should be modified to deal with this properly. */ - return; - } - - qq_get_md5(md5, QQ_KEY_LENGTH, buffer, filelen); -} - -static gint _qq_get_file_header(qq_file_header *fh, guint8 *buf) -{ - gint bytes = 0; - bytes += qq_get16(&(fh->client_ver), buf + bytes); - bytes += qq_get8(&fh->file_key, buf + bytes); - bytes += qq_get32(&(fh->sender_uid), buf + bytes); - bytes += qq_get32(&(fh->receiver_uid), buf + bytes); - - fh->sender_uid = _decrypt_qq_uid(fh->sender_uid, _get_file_key(fh->file_key)); - fh->receiver_uid = _decrypt_qq_uid(fh->receiver_uid, _get_file_key(fh->file_key)); - return bytes; -} - -static const gchar *qq_get_file_cmd_desc(gint type) -{ - switch (type) { - case QQ_FILE_CMD_SENDER_SAY_HELLO: - return "QQ_FILE_CMD_SENDER_SAY_HELLO"; - case QQ_FILE_CMD_SENDER_SAY_HELLO_ACK: - return "QQ_FILE_CMD_SENDER_SAY_HELLO_ACK"; - case QQ_FILE_CMD_RECEIVER_SAY_HELLO: - return "QQ_FILE_CMD_RECEIVER_SAY_HELLO"; - case QQ_FILE_CMD_RECEIVER_SAY_HELLO_ACK: - return "QQ_FILE_CMD_RECEIVER_SAY_HELLO_ACK"; - case QQ_FILE_CMD_NOTIFY_IP_ACK: - return "QQ_FILE_CMD_NOTIFY_IP_ACK"; - case QQ_FILE_CMD_PING: - return "QQ_FILE_CMD_PING"; - case QQ_FILE_CMD_PONG: - return "QQ_FILE_CMD_PONG"; - case QQ_FILE_CMD_INITATIVE_CONNECT: - return "QQ_FILE_CMD_INITATIVE_CONNECT"; - case QQ_FILE_CMD_FILE_OP: - return "QQ_FILE_CMD_FILE_OP"; - case QQ_FILE_CMD_FILE_OP_ACK: - return "QQ_FILE_CMD_FILE_OP_ACK"; - case QQ_FILE_BASIC_INFO: - return "QQ_FILE_BASIC_INFO"; - case QQ_FILE_DATA_INFO: - return "QQ_FILE_DATA_INFO"; - case QQ_FILE_EOF: - return "QQ_FILE_EOF"; - default: - return "UNKNOWN_TYPE"; - } -} - -/* The memmap version has better performance for big files transfering - * but it will spend plenty of memory, so do not use it in a low-memory host */ -#ifdef USE_MMAP -#include - -static int _qq_xfer_open_file(const gchar *filename, const gchar *method, PurpleXfer *xfer) -{ - ft_info *info = xfer->data; - int fd; - if (method[0] == 'r') { - fd = open(purple_xfer_get_local_filename(xfer), O_RDONLY); - info->buffer = mmap(0, purple_xfer_get_size(xfer), PROT_READ, MAP_PRIVATE, fd, 0); - } - else - { - fd = open(purple_xfer_get_local_filename(xfer), O_RDWR|O_CREAT, 0644); - info->buffer = mmap(0, purple_xfer_get_size(xfer), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FILE, fd, 0); - } - - if (info->buffer == NULL) { - return - 1; - } - return 0; -} - -static gint _qq_xfer_read_file(guint8 *buffer, guint index, guint len, PurpleXfer *xfer) -{ - ft_info *info = xfer->data; - gint readbytes; - - buffer = info->buffer + len * index; - readbytes = purple_xfer_get_size(xfer) - (buffer - info->buffer); - if (readbytes > info->fragment_len) readbytes = info->fragment_len; - return readbytes; -} - -static gint _qq_xfer_write_file(guint8 *buffer, guint index, guint len, PurpleXfer *xfer) -{ - ft_info *info = xfer->data; - - memcpy(info->buffer + index * len, buffer, len); - return 0; -} - -void qq_xfer_close_file(PurpleXfer *xfer) -{ - ft_info *info = xfer->data; - - if (info->buffer) munmap(info->buffer, purple_xfer_get_size(xfer)); -} -#else -static int _qq_xfer_open_file(const gchar *filename, const gchar *method, PurpleXfer *xfer) -{ - ft_info *info = xfer->data; - info->dest_fp = g_fopen(purple_xfer_get_local_filename(xfer), method); - if (info->dest_fp == NULL) { - return -1; - } - return 0; -} - -static gint _qq_xfer_read_file(guint8 *buffer, guint index, guint len, PurpleXfer *xfer) -{ - ft_info *info = xfer->data; - - fseek(info->dest_fp, index * len, SEEK_SET); - return fread(buffer, 1, len, info->dest_fp); -} - -static gint _qq_xfer_write_file(guint8 *buffer, guint index, guint len, PurpleXfer *xfer) -{ - ft_info *info = xfer->data; - fseek(info->dest_fp, index * len, SEEK_SET); - return fwrite(buffer, 1, len, info->dest_fp); -} - -void qq_xfer_close_file(PurpleXfer *xfer) -{ - ft_info *info = xfer->data; - - if (info->dest_fp) fclose(info->dest_fp); -} -#endif - -static gint _qq_send_file(PurpleConnection *gc, guint8 *data, gint len, guint16 packet_type, UID to_uid) -{ - guint8 *raw_data; - gint bytes = 0; - guint32 file_key; - qq_data *qd; - - qd = (qq_data *) gc->proto_data; - - raw_data = g_newa(guint8, MAX_PACKET_SIZE); - file_key = _gen_file_key(); - - bytes += qq_put8(raw_data + bytes, packet_type); - bytes += qq_put16(raw_data + bytes, qd->client_tag); - bytes += qq_put8(raw_data + bytes, file_key & 0xff); - bytes += qq_put32(raw_data + bytes, _encrypt_qq_uid(qd->uid, file_key)); - bytes += qq_put32(raw_data + bytes, _encrypt_qq_uid(to_uid, file_key)); - bytes += qq_putdata(raw_data + bytes, data, len); - - if (bytes == len + 12) { - _qq_xfer_write(raw_data, bytes, qd->xfer); - } else - purple_debug_info("QQ", "send_file: want %d but got %d\n", len + 12, bytes); - return bytes; -} - -/* send a file to udp channel with QQ_FILE_CONTROL_PACKET_TAG */ -void qq_send_file_ctl_packet(PurpleConnection *gc, guint16 packet_type, UID to_uid, guint8 hellobyte) -{ - qq_data *qd; - gint bytes, bytes_expected, encrypted_len; - guint8 *raw_data, *encrypted; - time_t now; - ft_info *info; - - qd = (qq_data *) gc->proto_data; - info = (ft_info *) qd->xfer->data; - - raw_data = g_newa (guint8, 61); - bytes = 0; - - now = time(NULL); - - bytes += qq_putdata(raw_data + bytes, qd->session_md5, 16); - bytes += qq_put16(raw_data + bytes, packet_type); - switch (packet_type) { - case QQ_FILE_CMD_SENDER_SAY_HELLO: - case QQ_FILE_CMD_SENDER_SAY_HELLO_ACK: - case QQ_FILE_CMD_RECEIVER_SAY_HELLO_ACK: - case QQ_FILE_CMD_NOTIFY_IP_ACK: - case QQ_FILE_CMD_RECEIVER_SAY_HELLO: - bytes += qq_put16(raw_data + bytes, info->send_seq); - break; - default: - bytes += qq_put16(raw_data + bytes, ++qd->send_seq); - } - bytes += qq_put32(raw_data + bytes, (guint32) now); - bytes += qq_put8(raw_data + bytes, 0x00); - bytes += qq_put8(raw_data + bytes, qd->my_icon); - bytes += qq_put32(raw_data + bytes, 0x00000000); - bytes += qq_put32(raw_data + bytes, 0x00000000); - bytes += qq_put32(raw_data + bytes, 0x00000000); - bytes += qq_put32(raw_data + bytes, 0x00000000); - bytes += qq_put16(raw_data + bytes, 0x0000); - bytes += qq_put8(raw_data + bytes, 0x00); - /* 0x65: send a file, 0x6b: send a custom face */ - bytes += qq_put8(raw_data + bytes, QQ_FILE_TRANSFER_FILE); /* FIXME temp by gfhuang */ - switch (packet_type) - { - case QQ_FILE_CMD_SENDER_SAY_HELLO: - case QQ_FILE_CMD_RECEIVER_SAY_HELLO: - case QQ_FILE_CMD_SENDER_SAY_HELLO_ACK: - case QQ_FILE_CMD_RECEIVER_SAY_HELLO_ACK: - bytes += qq_put8(raw_data + bytes, 0x00); - bytes += qq_put8(raw_data + bytes, hellobyte); - bytes_expected = 48; - break; - case QQ_FILE_CMD_PING: - case QQ_FILE_CMD_PONG: - case QQ_FILE_CMD_NOTIFY_IP_ACK: - bytes += qq_fill_conn_info(raw_data, info); - bytes_expected = 61; - break; - default: - purple_debug_info("QQ", "qq_send_file_ctl_packet: Unknown packet type[%d]\n", - packet_type); - bytes_expected = 0; - } - - if (bytes != bytes_expected) { - purple_debug_error("QQ", "qq_send_file_ctl_packet: Expected to get %d bytes, but get %d\n", - bytes_expected, bytes); - return; - } - - qq_hex_dump(PURPLE_DEBUG_INFO, "QQ", - raw_data, bytes, - "sending packet[%s]:", qq_get_file_cmd_desc(packet_type)); - - encrypted = g_newa(guint8, bytes + 17); - encrypted_len = qq_encrypt(encrypted, raw_data, bytes, info->file_session_key); - /*debug: try to decrypt it */ - -#if 0 - guint8 *buf; - int buflen; - hex_dump = hex_dump_to_str(encrypted, encrypted_len); - purple_debug_info("QQ", "encrypted packet: \n%s\n", hex_dump); - g_free(hex_dump); - buf = g_newa(guint8, MAX_PACKET_SIZE); - buflen = encrypted_len; - if (qq_crypt(DECRYPT, encrypted, encrypted_len, info->file_session_key, buf, &buflen)) { - purple_debug_info("QQ", "decrypt success\n"); - if (buflen == bytes && memcmp(raw_data, buf, buflen) == 0) - purple_debug_info("QQ", "checksum ok\n"); - - hex_dump = hex_dump_to_str(buf, buflen); - purple_debug_info("QQ", "decrypted packet: \n%s\n", hex_dump); - g_free(hex_dump); - } else { - purple_debug_info("QQ", "decrypt fail\n"); - } -#endif - - purple_debug_info("QQ", "<== send %s packet\n", qq_get_file_cmd_desc(packet_type)); - _qq_send_file(gc, encrypted, encrypted_len, QQ_FILE_CONTROL_PACKET_TAG, info->to_uid); -} - -/* send a file to udp channel with QQ_FILE_DATA_PACKET_TAG */ -static void _qq_send_file_data_packet(PurpleConnection *gc, guint16 packet_type, guint8 sub_type, - guint32 fragment_index, guint16 seq, guint8 *data, gint len) -{ - guint8 *raw_data, filename_md5[QQ_KEY_LENGTH], file_md5[QQ_KEY_LENGTH]; - gint bytes; - guint32 fragment_size = 1000; - const char *filename; - gint filename_len, filesize; - qq_data *qd; - ft_info *info; - - qd = (qq_data *) gc->proto_data; - info = (ft_info *) qd->xfer->data; - - filename = purple_xfer_get_filename(qd->xfer); - filesize = purple_xfer_get_size(qd->xfer); - - raw_data = g_newa(guint8, MAX_PACKET_SIZE); - bytes = 0; - - bytes += qq_put8(raw_data + bytes, 0x00); - bytes += qq_put16(raw_data + bytes, packet_type); - switch (packet_type) { - case QQ_FILE_BASIC_INFO: - case QQ_FILE_DATA_INFO: - case QQ_FILE_EOF: - bytes += qq_put16(raw_data + bytes, 0x0000); - bytes += qq_put8(raw_data + bytes, 0x00); - break; - case QQ_FILE_CMD_FILE_OP: - switch(sub_type) - { - case QQ_FILE_BASIC_INFO: - filename_len = strlen(filename); - qq_get_md5(filename_md5, sizeof(filename_md5), (guint8 *)filename, filename_len); - _fill_file_md5(purple_xfer_get_local_filename(qd->xfer), - purple_xfer_get_size(qd->xfer), - file_md5); - - info->fragment_num = (filesize - 1) / QQ_FILE_FRAGMENT_MAXLEN + 1; - info->fragment_len = QQ_FILE_FRAGMENT_MAXLEN; - - purple_debug_info("QQ", - "start transfering data, %d fragments with %d length each\n", - info->fragment_num, info->fragment_len); - /* Unknown */ - bytes += qq_put16(raw_data + bytes, 0x0000); - /* Sub-operation type */ - bytes += qq_put8(raw_data + bytes, sub_type); - /* Length of file */ - bytes += qq_put32(raw_data + bytes, filesize); - /* Number of fragments */ - bytes += qq_put32(raw_data + bytes, info->fragment_num); - /* Length of a single fragment */ - bytes += qq_put32(raw_data + bytes, info->fragment_len); - bytes += qq_putdata(raw_data + bytes, file_md5, 16); - bytes += qq_putdata(raw_data + bytes, filename_md5, 16); - /* Length of filename */ - bytes += qq_put16(raw_data + bytes, filename_len); - /* 8 unknown bytes */ - bytes += qq_put32(raw_data + bytes, 0x00000000); - bytes += qq_put32(raw_data + bytes, 0x00000000); - /* filename */ - bytes += qq_putdata(raw_data + bytes, (guint8 *) filename, - filename_len); - break; - case QQ_FILE_DATA_INFO: - purple_debug_info("QQ", - "sending %dth fragment with length %d, offset %d\n", - fragment_index, len, (fragment_index-1)*fragment_size); - /* bytes += qq_put16(raw_data + bytes, ++(qd->send_seq)); */ - bytes += qq_put16(raw_data + bytes, info->send_seq); - bytes += qq_put8(raw_data + bytes, sub_type); - /* bytes += qq_put32(raw_data + bytes, fragment_index); */ - bytes += qq_put32(raw_data + bytes, fragment_index - 1); - bytes += qq_put32(raw_data + bytes, (fragment_index - 1) * fragment_size); - bytes += qq_put16(raw_data + bytes, len); - bytes += qq_putdata(raw_data + bytes, data, len); - break; - case QQ_FILE_EOF: - purple_debug_info("QQ", "end of sending data\n"); - /* bytes += qq_put16(raw_data + bytes, info->fragment_num + 1); */ - bytes += qq_put16(raw_data + bytes, info->fragment_num); - bytes += qq_put8(raw_data + bytes, sub_type); - /* purple_xfer_set_completed(qd->xfer, TRUE); */ - } - break; - case QQ_FILE_CMD_FILE_OP_ACK: - switch (sub_type) - { - case QQ_FILE_BASIC_INFO: - bytes += qq_put16(raw_data + bytes, 0x0000); - bytes += qq_put8(raw_data + bytes, sub_type); - bytes += qq_put32(raw_data + bytes, 0x00000000); - break; - case QQ_FILE_DATA_INFO: - bytes += qq_put16(raw_data + bytes, seq); - bytes += qq_put8(raw_data + bytes, sub_type); - bytes += qq_put32(raw_data + bytes, fragment_index); - break; - case QQ_FILE_EOF: - bytes += qq_put16(raw_data + bytes, filesize / QQ_FILE_FRAGMENT_MAXLEN + 2); - bytes += qq_put8(raw_data + bytes, sub_type); - break; - } - } - purple_debug_info("QQ", "<== send %s packet\n", qq_get_file_cmd_desc(packet_type)); - _qq_send_file(gc, raw_data, bytes, QQ_FILE_DATA_PACKET_TAG, info->to_uid); -} - -/* A conversation starts like this: - * Sender ==> Receiver [QQ_FILE_CMD_PING] - * Sender <== Receiver [QQ_FILE_CMD_PONG] - * Sender ==> Receiver [QQ_FILE_CMD_SENDER_SAY_HELLO] - * Sender <== Receiver [QQ_FILE_CMD_SENDER_SAY_HELLO_ACK] - * Sender <== Receiver [QQ_FILE_CMD_RECEIVER_SAY_HELLO] - * Sender ==> Receiver [QQ_FILE_CMD_RECEIVER_SAY_HELLO_ACK] - * Sender ==> Receiver [QQ_FILE_CMD_FILE_OP, QQ_FILE_BASIC_INFO] - * Sender <== Receiver [QQ_FILE_CMD_FILE_OP_ACK, QQ_FILE_BASIC_INFO] - * Sender ==> Receiver [QQ_FILE_CMD_FILE_OP, QQ_FILE_DATA_INFO] - * Sender <== Receiver [QQ_FILE_CMD_FILE_OP_ACK, QQ_FILE_DATA_INFO] - * Sender ==> Receiver [QQ_FILE_CMD_FILE_OP, QQ_FILE_DATA_INFO] - * Sender <== Receiver [QQ_FILE_CMD_FILE_OP_ACK, QQ_FILE_DATA_INFO] - * ...... - * Sender ==> Receiver [QQ_FILE_CMD_FILE_OP, QQ_FILE_EOF] - * Sender <== Receiver [QQ_FILE_CMD_FILE_OP_ACK, QQ_FILE_EOF] - */ - - -static void _qq_process_recv_file_ctl_packet(PurpleConnection *gc, guint8 *data, gint data_len) -{ - gint bytes ; - gint decryped_bytes; - qq_file_header fh; - guint8 *decrypted_data; - gint decrypted_len; - qq_data *qd = (qq_data *) gc->proto_data; - guint16 packet_type; - guint16 seq; - guint8 hellobyte; - ft_info *info = (ft_info *) qd->xfer->data; - - bytes = 0; - bytes += _qq_get_file_header(&fh, data + bytes); - - decrypted_data = g_newa(guint8, data_len); - decrypted_len = qq_decrypt(decrypted_data, data, data_len, qd->session_md5); - if ( decrypted_len <= 0 ) { - purple_debug_error("QQ", "Error decrypt rcv file ctrl packet\n"); - return; - } - - /* only for debug info */ - decryped_bytes = 16; /* skip md5 section */ - decryped_bytes += qq_get16(&packet_type, decrypted_data + decryped_bytes); - decryped_bytes += qq_get16(&seq, decrypted_data + decryped_bytes); - decryped_bytes += 4+1+1+19+1; /* skip something */ - - purple_debug_info("QQ", "==> [%d] receive %s packet\n", seq, qq_get_file_cmd_desc(packet_type)); - qq_hex_dump(PURPLE_DEBUG_INFO, "QQ", - decrypted_data, decrypted_len, - "decrypted control packet received:"); - - switch (packet_type) { - case QQ_FILE_CMD_NOTIFY_IP_ACK: - decryped_bytes = 0; - qq_get_conn_info(info, decrypted_data + decryped_bytes); - /* qq_send_file_ctl_packet(gc, QQ_FILE_CMD_PING, fh->sender_uid, 0); */ - qq_send_file_ctl_packet(gc, QQ_FILE_CMD_SENDER_SAY_HELLO, fh.sender_uid, 0); - break; - case QQ_FILE_CMD_SENDER_SAY_HELLO: - /* I'm receiver, if we receive SAY_HELLO from sender, we send back the ACK */ - decryped_bytes += 47; - decryped_bytes += qq_get8(&hellobyte, decrypted_data + decryped_bytes); - qq_send_file_ctl_packet(gc, QQ_FILE_CMD_SENDER_SAY_HELLO_ACK, fh.sender_uid, hellobyte); - qq_send_file_ctl_packet(gc, QQ_FILE_CMD_RECEIVER_SAY_HELLO, fh.sender_uid, 0); - break; - case QQ_FILE_CMD_SENDER_SAY_HELLO_ACK: - /* I'm sender, do nothing */ - break; - case QQ_FILE_CMD_RECEIVER_SAY_HELLO: - /* I'm sender, ack the hello packet and send the first data */ - decryped_bytes += 47; - decryped_bytes += qq_get8(&hellobyte, decrypted_data + decryped_bytes); - qq_send_file_ctl_packet(gc, QQ_FILE_CMD_RECEIVER_SAY_HELLO_ACK, fh.sender_uid, hellobyte); - _qq_send_file_data_packet(gc, QQ_FILE_CMD_FILE_OP, QQ_FILE_BASIC_INFO, 0, 0, NULL, 0); - break; - case QQ_FILE_CMD_RECEIVER_SAY_HELLO_ACK: - /* I'm receiver, do nothing */ - break; - case QQ_FILE_CMD_PING: - /* I'm receiver, ack the PING */ - qq_send_file_ctl_packet(gc, QQ_FILE_CMD_PONG, fh.sender_uid, 0); - break; - case QQ_FILE_CMD_PONG: - qq_send_file_ctl_packet(gc, QQ_FILE_CMD_SENDER_SAY_HELLO, fh.sender_uid, 0); - break; - default: - purple_debug_info("QQ", "unprocess file command %d\n", packet_type); - } -} - -static void _qq_recv_file_progess(PurpleConnection *gc, guint8 *buffer, guint16 len, guint32 index, guint32 offset) -{ - qq_data *qd = (qq_data *) gc->proto_data; - PurpleXfer *xfer = qd->xfer; - ft_info *info = (ft_info *) xfer->data; - guint32 mask; - - purple_debug_info("QQ", - "receiving %dth fragment with length %d, slide window status %o, max_fragment_index %d\n", - index, len, info->window, info->max_fragment_index); - if (info->window == 0 && info->max_fragment_index == 0) { - if (_qq_xfer_open_file(purple_xfer_get_local_filename(xfer), "wb", xfer) == -1) { - purple_xfer_cancel_local(xfer); - return; - } - purple_debug_info("QQ", "object file opened for writing\n"); - } - mask = 0x1 << (index % sizeof(info->window)); - if (index < info->max_fragment_index || (info->window & mask)) { - purple_debug_info("QQ", "duplicate %dth fragment, drop it!\n", index+1); - return; - } - - info->window |= mask; - - _qq_xfer_write_file(buffer, index, len, xfer); - - xfer->bytes_sent += len; - xfer->bytes_remaining -= len; - purple_xfer_update_progress(xfer); - - mask = 0x1 << (info->max_fragment_index % sizeof(info->window)); - while (info->window & mask) - { - info->window &= ~mask; - info->max_fragment_index ++; - if (mask & 0x8000) mask = 0x0001; - else mask = mask << 1; - } - purple_debug_info("QQ", "procceed %dth fragment, slide window status %o, max_fragment_index %d\n", - index, info->window, info->max_fragment_index); -} - -static void _qq_send_file_progess(PurpleConnection *gc) -{ - qq_data *qd = (qq_data *) gc->proto_data; - PurpleXfer *xfer = qd->xfer; - ft_info *info = (ft_info *) xfer->data; - guint32 mask; - guint8 *buffer; - guint i; - gint readbytes; - - if (purple_xfer_get_bytes_remaining(xfer) <= 0) return; - if (info->window == 0 && info->max_fragment_index == 0) - { - if (_qq_xfer_open_file(purple_xfer_get_local_filename(xfer), "rb", xfer) == -1) { - purple_xfer_cancel_local(xfer); - return; - } - } - buffer = g_newa(guint8, info->fragment_len); - mask = 0x1 << (info->max_fragment_index % sizeof(info->window)); - for (i = 0; i < sizeof(info->window); i++) { - if ((info->window & mask) == 0) { - readbytes = _qq_xfer_read_file(buffer, info->max_fragment_index + i, info->fragment_len, xfer); - if (readbytes > 0) - _qq_send_file_data_packet(gc, QQ_FILE_CMD_FILE_OP, QQ_FILE_DATA_INFO, - info->max_fragment_index + i + 1, 0, buffer, readbytes); - } - if (mask & 0x8000) mask = 0x0001; - else mask = mask << 1; - } -} - -static void _qq_update_send_progess(PurpleConnection *gc, guint32 fragment_index) -{ - guint32 mask; - guint8 *buffer; - gint readbytes; - qq_data *qd = (qq_data *) gc->proto_data; - PurpleXfer *xfer = qd->xfer; - ft_info *info = (ft_info *) xfer->data; - - purple_debug_info("QQ", - "receiving %dth fragment ack, slide window status %o, max_fragment_index %d\n", - fragment_index, info->window, info->max_fragment_index); - if (fragment_index < info->max_fragment_index || - fragment_index >= info->max_fragment_index + sizeof(info->window)) { - purple_debug_info("QQ", "duplicate %dth fragment, drop it!\n", fragment_index+1); - return; - } - mask = 0x1 << (fragment_index % sizeof(info->window)); - if ((info->window & mask) == 0) - { - info->window |= mask; - if (fragment_index + 1 != info->fragment_num) { - xfer->bytes_sent += info->fragment_len; - } else { - xfer->bytes_sent += purple_xfer_get_size(xfer) % info->fragment_len; - } - xfer->bytes_remaining = purple_xfer_get_size(xfer) - purple_xfer_get_bytes_sent(xfer); - purple_xfer_update_progress(xfer); - if (purple_xfer_get_bytes_remaining(xfer) <= 0) { - /* We have finished sending the file */ - purple_xfer_set_completed(xfer, TRUE); - return; - } - mask = 0x1 << (info->max_fragment_index % sizeof(info->window)); - while (info->window & mask) - { - /* move the slide window */ - info->window &= ~mask; - - buffer = g_newa(guint8, info->fragment_len); - readbytes = _qq_xfer_read_file(buffer, info->max_fragment_index + sizeof(info->window), - info->fragment_len, xfer); - if (readbytes > 0) - _qq_send_file_data_packet(gc, QQ_FILE_CMD_FILE_OP, QQ_FILE_DATA_INFO, - info->max_fragment_index + sizeof(info->window) + 1, 0, buffer, readbytes); - - info->max_fragment_index ++; - if (mask & 0x8000) mask = 0x0001; - else mask = mask << 1; - } - } - purple_debug_info("QQ", - "procceed %dth fragment ack, slide window status %o, max_fragment_index %d\n", - fragment_index, info->window, info->max_fragment_index); -} - -static void _qq_process_recv_file_data(PurpleConnection *gc, guint8 *data, gint len) -{ - gint bytes ; - qq_file_header fh; - guint16 packet_type; - guint16 packet_seq; - guint8 sub_type; - guint32 fragment_index; - guint16 fragment_len; - guint32 fragment_offset; - qq_data *qd = (qq_data *) gc->proto_data; - ft_info *info = (ft_info *) qd->xfer->data; - - bytes = 0; - bytes += _qq_get_file_header(&fh, data + bytes); - - bytes += 1; /* skip an unknown byte */ - bytes += qq_get16(&packet_type, data + bytes); - switch(packet_type) - { - case QQ_FILE_CMD_FILE_OP: - bytes += qq_get16(&packet_seq, data + bytes); - bytes += qq_get8(&sub_type, data + bytes); - switch (sub_type) - { - case QQ_FILE_BASIC_INFO: - bytes += 4; /* file length, we have already known it from xfer */ - bytes += qq_get32(&info->fragment_num, data + bytes); - bytes += qq_get32(&info->fragment_len, data + bytes); - - /* FIXME: We must check the md5 here, - * if md5 doesn't match we will ignore - * the packet or send sth as error number */ - - info->max_fragment_index = 0; - info->window = 0; - purple_debug_info("QQ", - "start receiving data, %d fragments with %d length each\n", - info->fragment_num, info->fragment_len); - _qq_send_file_data_packet(gc, QQ_FILE_CMD_FILE_OP_ACK, sub_type, - 0, 0, NULL, 0); - break; - case QQ_FILE_DATA_INFO: - bytes += qq_get32(&fragment_index, data + bytes); - bytes += qq_get32(&fragment_offset, data + bytes); - bytes += qq_get16(&fragment_len, data + bytes); - purple_debug_info("QQ", - "received %dth fragment with length %d, offset %d\n", - fragment_index, fragment_len, fragment_offset); - - _qq_send_file_data_packet(gc, QQ_FILE_CMD_FILE_OP_ACK, sub_type, - fragment_index, packet_seq, NULL, 0); - _qq_recv_file_progess(gc, data + bytes, fragment_len, fragment_index, fragment_offset); - break; - case QQ_FILE_EOF: - purple_debug_info("QQ", "end of receiving\n"); - _qq_send_file_data_packet(gc, QQ_FILE_CMD_FILE_OP_ACK, sub_type, - 0, 0, NULL, 0); - break; - } - break; - case QQ_FILE_CMD_FILE_OP_ACK: - bytes += qq_get16(&packet_seq, data + bytes); - bytes += qq_get8(&sub_type, data + bytes); - switch (sub_type) - { - case QQ_FILE_BASIC_INFO: - info->max_fragment_index = 0; - info->window = 0; - /* It is ready to send file data */ - _qq_send_file_progess(gc); - break; - case QQ_FILE_DATA_INFO: - bytes += qq_get32(&fragment_index, data + bytes); - _qq_update_send_progess(gc, fragment_index); - if (purple_xfer_is_completed(qd->xfer)) - _qq_send_file_data_packet(gc, QQ_FILE_CMD_FILE_OP, QQ_FILE_EOF, 0, 0, NULL, 0); - /* else - _qq_send_file_progess(gc); */ - break; - case QQ_FILE_EOF: - /* FIXME: OK, we can end the connection successfully */ - - _qq_send_file_data_packet(gc, QQ_FILE_EOF, 0, 0, 0, NULL, 0); - purple_xfer_set_completed(qd->xfer, TRUE); - break; - } - break; - case QQ_FILE_EOF: - _qq_send_file_data_packet(gc, QQ_FILE_EOF, 0, 0, 0, NULL, 0); - purple_xfer_set_completed(qd->xfer, TRUE); - purple_xfer_end(qd->xfer); - break; - case QQ_FILE_BASIC_INFO: - purple_debug_info("QQ", "here\n"); - _qq_send_file_data_packet(gc, QQ_FILE_DATA_INFO, 0, 0, 0, NULL, 0); - break; - default: - purple_debug_info("QQ", "_qq_process_recv_file_data: unknown packet type [%d]\n", - packet_type); - break; - } -} - -void qq_process_recv_file(PurpleConnection *gc, guint8 *data, gint len) -{ - gint bytes; - guint8 tag; - - bytes = 0; - bytes += qq_get8(&tag, data + bytes); - - switch (tag) { - case QQ_FILE_CONTROL_PACKET_TAG: - _qq_process_recv_file_ctl_packet(gc, data + bytes, len - bytes); - break; - case QQ_FILE_DATA_PACKET_TAG: - _qq_process_recv_file_data(gc, data + bytes, len - bytes); - break; - default: - purple_debug_info("QQ", "unknown packet tag\n"); - } -} diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/qq/file_trans.h --- a/libpurple/protocols/qq/file_trans.h Thu May 05 03:40:29 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,67 +0,0 @@ -/** - * @file file_trans.h - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * 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 02111-1301 USA - */ - -#ifndef _QQ_QQ_FILE_TRANS_H_ -#define _QQ_QQ_FILE_TRANS_H_ - -#include "server.h" -#include "qq.h" - -enum { - QQ_FILE_CMD_SENDER_SAY_HELLO = 0x31, - QQ_FILE_CMD_SENDER_SAY_HELLO_ACK = 0x32, - QQ_FILE_CMD_RECEIVER_SAY_HELLO = 0x33, - QQ_FILE_CMD_RECEIVER_SAY_HELLO_ACK = 0x34, - QQ_FILE_CMD_NOTIFY_IP_ACK = 0x3c, - QQ_FILE_CMD_PING = 0x3d, - QQ_FILE_CMD_PONG = 0x3e, - QQ_FILE_CMD_INITATIVE_CONNECT = 0x40 -}; - -enum { - QQ_FILE_TRANSFER_FILE = 0x65, - QQ_FILE_TRANSFER_FACE = 0x6b -}; - -enum { - QQ_FILE_BASIC_INFO = 0x01, - QQ_FILE_DATA_INFO = 0x02, - QQ_FILE_EOF = 0x03, - QQ_FILE_CMD_FILE_OP = 0x07, - QQ_FILE_CMD_FILE_OP_ACK = 0x08 -}; - -#define QQ_FILE_FRAGMENT_MAXLEN 1000 - -#define QQ_FILE_CONTROL_PACKET_TAG 0x00 -/* #define QQ_PACKET_TAG 0x02 */ /* all QQ text packets starts with it */ -#define QQ_FILE_DATA_PACKET_TAG 0x03 -#define QQ_FILE_AGENT_PACKET_TAG 0x04 -/* #define QQ_PACKET_TAIL 0x03 */ /* all QQ text packets end with it */ - -void qq_send_file_ctl_packet(PurpleConnection *gc, guint16 packet_type, UID to_uid, guint8 hellobyte); -void qq_process_recv_file(PurpleConnection *gc, guint8 *data, gint len); -/* void qq_send_file_data_packet(PurpleConnection *gc, guint16 packet_type, guint8 sub_type, guint32 fragment_index, guint16 seq, guint8 *data, gint len); */ -void qq_xfer_close_file(PurpleXfer *xfer); -#endif diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/qq/group.c --- a/libpurple/protocols/qq/group.c Thu May 05 03:40:29 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,129 +0,0 @@ -/** - * @file group.c - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * 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 02111-1301 USA - */ - -#include "internal.h" - -#include "debug.h" -#include "prpl.h" -#include "request.h" - -#include "group_internal.h" -#include "group_info.h" -#include "group_join.h" -#include "utils.h" -#include "qq_network.h" -#include "qq_define.h" - -static void _qq_group_search_callback(PurpleConnection *gc, const gchar *input) -{ - guint32 ext_id; - - g_return_if_fail(input != NULL); - ext_id = strtoul(input, NULL, 10); - /* 0x00000000 means search for demo group */ - qq_request_room_search(gc, ext_id, QQ_ROOM_SEARCH_ONLY); -} - -static void _qq_group_search_cancel_callback(PurpleConnection *gc, const gchar *input) -{ - qq_data *qd; - - qd = (qq_data *) gc->proto_data; - purple_roomlist_set_in_progress(qd->roomlist, FALSE); -} - -/* This is needed for PurpleChat node to be valid */ -GList *qq_chat_info(PurpleConnection *gc) -{ - GList *m; - struct proto_chat_entry *pce; - - m = NULL; - - pce = g_new0(struct proto_chat_entry, 1); - pce->label = _("ID: "); - pce->identifier = QQ_ROOM_KEY_EXTERNAL_ID; - m = g_list_append(m, pce); - - return m; -} - -GHashTable *qq_chat_info_defaults(PurpleConnection *gc, const gchar *chat_name) -{ - GHashTable *defaults; - - defaults = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free); - - if (chat_name != NULL) - g_hash_table_insert(defaults, QQ_ROOM_KEY_EXTERNAL_ID, g_strdup(chat_name)); - - return defaults; -} - -/* get a list of qq groups */ -PurpleRoomlist *qq_roomlist_get_list(PurpleConnection *gc) -{ - GList *fields; - qq_data *qd; - PurpleRoomlist *rl; - PurpleRoomlistField *f; - - qd = (qq_data *) gc->proto_data; - - fields = NULL; - rl = purple_roomlist_new(purple_connection_get_account(gc)); - qd->roomlist = rl; - - f = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_STRING, _("Group ID"), QQ_ROOM_KEY_EXTERNAL_ID, FALSE); - fields = g_list_append(fields, f); - f = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_STRING, "", QQ_ROOM_KEY_INTERNAL_ID, TRUE); - fields = g_list_append(fields, f); - - fields = g_list_append(fields, f); - purple_roomlist_set_fields(rl, fields); - purple_roomlist_set_in_progress(qd->roomlist, TRUE); - - purple_request_input(gc, _("QQ Qun"), - _("Please enter Qun number"), - _("You can only search for permanent Qun\n"), - NULL, FALSE, FALSE, NULL, - _("Search"), G_CALLBACK(_qq_group_search_callback), - _("Cancel"), G_CALLBACK(_qq_group_search_cancel_callback), - purple_connection_get_account(gc), NULL, NULL, - gc); - - return qd->roomlist; -} - -/* free roomlist space, I have no idea when this one is called... */ -void qq_roomlist_cancel(PurpleRoomlist *list) -{ - PurpleConnection *gc; - - g_return_if_fail(list != NULL); - gc = purple_account_get_connection(list->account); - - purple_roomlist_set_in_progress(list, FALSE); - purple_roomlist_unref(list); -} diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/qq/group.h --- a/libpurple/protocols/qq/group.h Thu May 05 03:40:29 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,68 +0,0 @@ -/** - * @file group.h - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * 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 02111-1301 USA - */ - -#ifndef _QQ_GROUP_H_ -#define _QQ_GROUP_H_ - -#include -#include "account.h" -#include "connection.h" -#include "roomlist.h" -#include "qq.h" - -#define PURPLE_GROUP_QQ_QUN "QQ 群" - -typedef enum { - QQ_ROOM_ROLE_NO = 0x00, /* default 0x00 means not member */ - QQ_ROOM_ROLE_YES, - QQ_ROOM_ROLE_REQUESTING, - QQ_ROOM_ROLE_ADMIN -} qq_room_role; - -typedef struct _qq_room_data { - /* all these will be saved when we exit Purple */ - qq_room_role my_role; /* my role for this room */ - guint32 id; - guint32 ext_id; - guint8 type8; /* permanent or temporory */ - UID creator_uid; - guint32 category; - guint8 auth_type; - gchar *title_utf8; - gchar *desc_utf8; - /* all these will be loaded from the network */ - gchar *notice_utf8; /* group notice by admin */ - - gboolean is_got_buddies; - GList *members; -} qq_room_data; - -GList *qq_chat_info(PurpleConnection *gc); -GHashTable *qq_chat_info_defaults(PurpleConnection *gc, const gchar *chat_name); - -PurpleRoomlist *qq_roomlist_get_list(PurpleConnection *gc); - -void qq_roomlist_cancel(PurpleRoomlist *list); - -#endif diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/qq/group_im.c --- a/libpurple/protocols/qq/group_im.c Thu May 05 03:40:29 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,429 +0,0 @@ -/** - * @file group_im.c - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * 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 02111-1301 USA - */ - -#include "internal.h" - -#include "conversation.h" -#include "debug.h" -#include "notify.h" -#include "prefs.h" -#include "request.h" -#include "util.h" - -#include "char_conv.h" -#include "group_internal.h" -#include "group_info.h" -#include "group_join.h" -#include "group_im.h" -#include "group_opt.h" -#include "im.h" -#include "qq_define.h" -#include "packet_parse.h" -#include "qq_network.h" -#include "qq_process.h" -#include "utils.h" - -/* show group conversation window */ -PurpleConversation *qq_room_conv_open(PurpleConnection *gc, qq_room_data *rmd) -{ - PurpleConversation *conv; - gchar *topic_utf8; - - g_return_val_if_fail(rmd != NULL, NULL); - g_return_val_if_fail(rmd->title_utf8, NULL); - - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - rmd->title_utf8, purple_connection_get_account(gc)); - if (conv != NULL) { - /* show only one conversation per room */ - return conv; - } - - serv_got_joined_chat(gc, rmd->id, rmd->title_utf8); - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, rmd->title_utf8, purple_connection_get_account(gc)); - if (conv != NULL) { - if (rmd->notice_utf8 != NULL) { - topic_utf8 = g_strdup_printf("%u %s", rmd->ext_id, rmd->notice_utf8); - } else { - topic_utf8 = g_strdup_printf("%u", rmd->ext_id); - } - purple_debug_info("QQ", "Chat topic = %s\n", topic_utf8); - purple_conv_chat_set_topic(PURPLE_CONV_CHAT(conv), NULL, topic_utf8); - g_free(topic_utf8); - - if (rmd->is_got_buddies) - qq_send_room_cmd_only(gc, QQ_ROOM_CMD_GET_ONLINES, rmd->id); - else - qq_update_room(gc, 0, rmd->id); - return conv; - } - return NULL; -} - -/* refresh online member in group conversation window */ -void qq_room_conv_set_onlines(PurpleConnection *gc, qq_room_data *rmd) -{ - GList *names, *list, *flags; - qq_buddy_data *bd; - gchar *member_name, *member_uid; - PurpleConversation *conv; - gint flag; - gboolean is_find; - - g_return_if_fail(rmd != NULL); - - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - rmd->title_utf8, purple_connection_get_account(gc)); - if (conv == NULL) { - purple_debug_warning("QQ", "Conversation \"%s\" is not opened\n", rmd->title_utf8); - return; - } - g_return_if_fail(rmd->members != NULL); - - names = NULL; - flags = NULL; - - list = rmd->members; - while (list != NULL) { - bd = (qq_buddy_data *) list->data; - - /* we need unique identifiers for everyone in the chat or else we'll - * run into problems with functions like get_cb_real_name from qq.c */ - member_name = (bd->nickname != NULL && *(bd->nickname) != '\0') ? - g_strdup_printf("%s (%u)", bd->nickname, bd->uid) : - g_strdup_printf("(%u)", bd->uid); - member_uid = g_strdup_printf("(%u)", bd->uid); - - flag = 0; - /* TYPING to put online above OP and FOUNDER */ - if (is_online(bd->status)) flag |= (PURPLE_CBFLAGS_TYPING | PURPLE_CBFLAGS_VOICE); - if(1 == (bd->role & 1)) flag |= PURPLE_CBFLAGS_OP; - if(bd->uid == rmd->creator_uid) flag |= PURPLE_CBFLAGS_FOUNDER; - - is_find = TRUE; - if (purple_conv_chat_find_user(PURPLE_CONV_CHAT(conv), member_name)) - { - purple_conv_chat_user_set_flags(PURPLE_CONV_CHAT(conv), - member_name, - flag); - } else if (purple_conv_chat_find_user(PURPLE_CONV_CHAT(conv), member_uid)) - { - purple_conv_chat_user_set_flags(PURPLE_CONV_CHAT(conv), - member_uid, - flag); - purple_conv_chat_rename_user(PURPLE_CONV_CHAT(conv), member_uid, member_name); - } else { - is_find = FALSE; - } - if (!is_find) { - /* always put it even offline */ - names = g_list_append(names, member_name); - flags = g_list_append(flags, GINT_TO_POINTER(flag)); - } else { - g_free(member_name); - } - g_free(member_uid); - list = list->next; - } - - if (names != NULL && flags != NULL) { - purple_conv_chat_add_users(PURPLE_CONV_CHAT(conv), names, NULL, flags, FALSE); - } - - /* clean up names */ - while (names != NULL) { - member_name = (gchar *) names->data; - names = g_list_remove(names, member_name); - g_free(member_name); - } - g_list_free(flags); -} - -void qq_room_got_chat_in(PurpleConnection *gc, - guint32 room_id, UID uid_from, const gchar *msg, time_t in_time) -{ - PurpleConversation *conv; - qq_data *qd; - qq_buddy_data *bd; - qq_room_data *rmd; - gchar *from; - - g_return_if_fail(gc != NULL && room_id != 0); - g_return_if_fail(msg != NULL); - - qd = (qq_data *)gc->proto_data; - conv = purple_find_chat(gc, room_id); - rmd = qq_room_data_find(gc, room_id); - g_return_if_fail(rmd != NULL); - - purple_debug_info("QQ", "is_show_chat:%d\n", qd->is_show_chat); - if (NULL == conv && qd->is_show_chat) { - conv = qq_room_conv_open(gc, rmd); - } - - if (NULL == conv) { - purple_debug_info("QQ", "Conversion of %u is not open, missing from %d:/n%s/v\n", - room_id, uid_from, msg); - return; - } - - if (uid_from != 0) { - - bd = qq_room_buddy_find(rmd, uid_from); - if (bd == NULL || bd->nickname == NULL) - from = g_strdup_printf("%u", uid_from); - else - from = g_strdup(bd->nickname); - } else { - from = g_strdup(""); - } - serv_got_chat_in(gc, room_id, from, 0, msg, in_time); - g_free(from); -} - -/* recv an IM from a group chat */ -void qq_process_room_im(guint8 *data, gint data_len, guint32 id, PurpleConnection *gc, guint16 msg_type) -{ - gchar *msg_smiley, *msg_fmt, *msg_utf8; - gint bytes, tail_len; - qq_data *qd; - struct { - guint32 ext_id; - guint8 type8; - UID member_uid; - guint16 unknown; - guint16 msg_seq; - time_t send_time; - guint32 version; - guint16 msg_len; - gchar *msg; - } im_text; - guint32 temp_id; - guint16 content_type; - guint8 frag_count, frag_index; - guint16 msg_id; - guint32 use_default_font; - qq_im_format *fmt = NULL; - qd = (qq_data *) gc->proto_data; - - /* at least include im_text.msg_len */ - g_return_if_fail(data != NULL && data_len > 23); - - use_default_font = (qd->custom) & QQ_CUSTOM_USE_DEFAULT_FONT; - - /* qq_show_packet("ROOM_IM", data, data_len); */ - memset(&im_text, 0, sizeof(im_text)); - bytes = 0; - bytes += qq_get32(&(im_text.ext_id), data + bytes); - bytes += qq_get8(&(im_text.type8), data + bytes); - - if(QQ_MSG_TEMP_QUN_IM == msg_type) { - bytes += qq_get32(&temp_id, data + bytes); - } - - bytes += qq_get32(&(im_text.member_uid), bytes + data); - bytes += qq_get16(&im_text.unknown, data + bytes); /* 0x0001? */ - bytes += qq_get16(&(im_text.msg_seq), data + bytes); - bytes += qq_getime(&im_text.send_time, data + bytes); - bytes += qq_get32(&im_text.version, data + bytes); - bytes += qq_get16(&(im_text.msg_len), data + bytes); - purple_debug_info("QQ", "Room IM, ext id %u, seq %u, version 0x%04X, len %u\n", - im_text.ext_id, im_text.msg_seq, im_text.version, im_text.msg_len); - - if (im_text.msg_len != data_len - bytes) { - purple_debug_warning("QQ", "Room IM length %d should be %d\n", - im_text.msg_len, data_len - bytes); - im_text.msg_len = data_len - bytes; - } - - g_return_if_fail(im_text.msg_len > 0 && bytes + im_text.msg_len <= data_len); - if(msg_type != QQ_MSG_QUN_IM_UNKNOWN) { - g_return_if_fail(im_text.msg_len >= 10); - - bytes += qq_get16(&content_type, data + bytes); - bytes += qq_get8(&frag_count, data + bytes); - bytes += qq_get8(&frag_index, data + bytes); - bytes += qq_get16(&msg_id, data + bytes); - bytes += 4; /* skip 0x(00 00 00 00) */ - purple_debug_info("QQ", "Room IM, content %d, frag %d-%d, msg id %u\n", - content_type, frag_count, frag_index, msg_id); - im_text.msg_len -= 10; - } - g_return_if_fail(im_text.msg_len > 0); - - /* qq_show_packet("Message", data + bytes, data_len - bytes); */ - if (frag_count <= 1 || frag_count == frag_index + 1) { - fmt = qq_im_fmt_new(); - tail_len = qq_get_im_tail(fmt, data + bytes, data_len - bytes); - im_text.msg = g_strndup((gchar *)(data + bytes), data_len - tail_len); - } else { - im_text.msg = g_strndup((gchar *)(data + bytes), data_len - bytes); - } - - /* group im_group has no flag to indicate whether it has font_attr or not */ - msg_smiley = qq_emoticon_to_purple(im_text.msg); - if (fmt != NULL) { - purple_debug_info("QQ", "going to use_default_font\n"); - if (QQ_CUSTOM_USE_DEFAULT_FONT == use_default_font) { - qq_im_fmt_reset_font(fmt); - purple_debug_info("QQ", "use_default_font set\n"); - } - msg_fmt = qq_im_fmt_to_purple(fmt, msg_smiley); - msg_utf8 = qq_to_utf8(msg_fmt, QQ_CHARSET_DEFAULT); - purple_debug_info("QQ", "passed!\n"); - g_free(msg_fmt); - qq_im_fmt_free(fmt); - } else { - msg_utf8 = qq_to_utf8(msg_smiley, QQ_CHARSET_DEFAULT); - } - g_free(msg_smiley); - - purple_debug_info("QQ", "Room (%u) IM from %u: %s\n", - im_text.ext_id, im_text.member_uid, msg_utf8); - qq_room_got_chat_in(gc, id, im_text.member_uid, msg_utf8, im_text.send_time); - - g_free(msg_utf8); - g_free(im_text.msg); -} - -/* send IM to a group */ -static void request_room_send_im(PurpleConnection *gc, guint32 room_id, qq_im_format *fmt, const gchar *msg) -{ - guint8 raw_data[MAX_PACKET_SIZE - 16]; - gint bytes; - - g_return_if_fail(room_id != 0 && msg != NULL); - - bytes = 0; - bytes += qq_put16(raw_data + bytes, 0); - bytes += qq_putdata(raw_data + bytes, (guint8 *)msg, strlen(msg)); - bytes += qq_put_im_tail(raw_data + bytes, fmt); - /* reset first two bytes */ - qq_put16(raw_data, bytes - 2); - - qq_send_room_cmd(gc, QQ_ROOM_CMD_SEND_IM, room_id, raw_data, bytes); -} - -/* this is the ACK */ -void qq_process_room_send_im(PurpleConnection *gc, guint8 *data, gint len) -{ - /* return should be the internal group id - * but we have nothing to do with it */ - return; -} - -void qq_process_room_send_im_ex(PurpleConnection *gc, guint8 *data, gint len) -{ - /* return should be the internal group id - * but we have nothing to do with it */ - return; -} - -#if 0 -static void request_room_send_im_ex(PurpleConnection *gc, guint32 room_id, - qq_im_format *fmt, gchar *msg, guint16 msg_id, guint8 frag_count, guint8 frag_index) -{ - guint8 raw_data[MAX_PACKET_SIZE - 16]; - gint bytes; - - - g_return_if_fail(room_id != 0 && msg != NULL); - - bytes = 0; - bytes += qq_put16(raw_data + bytes, 0); /* packet len */ - /* type 0x0001, text only; 0x0002, with custom emoticon */ - bytes += qq_put16(raw_data + bytes, 0x0001); - bytes += qq_put8(raw_data + bytes, frag_count); - bytes += qq_put8(raw_data + bytes, frag_index); - bytes += qq_put16(raw_data + bytes, msg_id); - bytes += qq_put32(raw_data + bytes, 0); /* unknow 4 bytes */ - bytes += qq_putdata(raw_data + bytes, (guint8 *)msg, strlen(msg)); - if (frag_count == frag_index + 1) { - bytes += qq_put8(raw_data + bytes, 0x20); /* add extra SPACE */ - bytes += qq_put_im_tail(raw_data + bytes, fmt); - } - - /* reset first two bytes as length */ - qq_put16(raw_data, bytes - 2); - - /*qq_show_packet("QQ_ROOM_CMD_SEND_IM_EX", raw_data, bytes); */ - qq_send_room_cmd(gc, QQ_ROOM_CMD_SEND_IM_EX, room_id, raw_data, bytes); -} -#endif - -/* send a chat msg to a QQ Qun - * called by purple */ -int qq_chat_send(PurpleConnection *gc, int id, const char *what, PurpleMessageFlags flags) -{ - qq_data *qd; - qq_im_format *fmt; - gchar *msg_stripped, *tmp; - GSList *segments, *it; - gint msg_len; - const gchar *start_invalid; - gboolean is_smiley_none; - - g_return_val_if_fail(NULL != gc && NULL != gc->proto_data, -1); - g_return_val_if_fail(id != 0 && what != NULL, -1); - - qd = (qq_data *) gc->proto_data; - purple_debug_info("QQ", "Send chat IM to %u, len %" G_GSIZE_FORMAT ":\n%s\n", id, strlen(what), what); - - /* qq_show_packet("chat IM UTF8", (guint8 *)what, strlen(what)); */ - - msg_stripped = purple_markup_strip_html(what); - g_return_val_if_fail(msg_stripped != NULL, -1); - /* qq_show_packet("IM Stripped", (guint8 *)what, strlen(what)); */ - - /* Check and valid utf8 string */ - msg_len = strlen(msg_stripped); - if (!g_utf8_validate(msg_stripped, msg_len, &start_invalid)) { - if (start_invalid > msg_stripped) { - tmp = g_strndup(msg_stripped, start_invalid - msg_stripped); - g_free(msg_stripped); - msg_stripped = g_strconcat(tmp, _("(Invalid UTF-8 string)"), NULL); - g_free(tmp); - } else { - g_free(msg_stripped); - msg_stripped = g_strdup(_("(Invalid UTF-8 string)")); - } - } - - is_smiley_none = qq_im_smiley_none(what); - segments = qq_im_get_segments(msg_stripped, is_smiley_none); - g_free(msg_stripped); - - if (segments == NULL) { - return -1; - } - - qd->send_im_id++; - fmt = qq_im_fmt_new_by_purple(what); - for (it = segments; it; it = g_slist_delete_link(it, it)) { - request_room_send_im(gc, id, fmt, (gchar *)it->data); - g_free(it->data); - } - qq_im_fmt_free(fmt); - return 1; -} diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/qq/group_im.h --- a/libpurple/protocols/qq/group_im.h Thu May 05 03:40:29 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,51 +0,0 @@ -/** - * @file group_im.h - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * 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 02111-1301 USA - */ - -#ifndef _QQ_GROUP_IM_H_ -#define _QQ_GROUP_IM_H_ - -#include -#include "connection.h" -#include "conversation.h" -#include "group.h" - -enum { - QQ_CUSTOM_USE_DEFAULT_FONT = 0x00000001, - QQ_CUSTOM_NONE = 0x00000000 -}; - -PurpleConversation *qq_room_conv_open(PurpleConnection *gc, qq_room_data *rmd); -void qq_room_conv_set_onlines(PurpleConnection *gc, qq_room_data *rmd); - -void qq_room_got_chat_in(PurpleConnection *gc, - guint32 room_id, UID uid_from, const gchar *msg, time_t in_time); - -int qq_chat_send(PurpleConnection *gc, int id, const char *message, PurpleMessageFlags flags); -void qq_process_room_send_im(PurpleConnection *gc, guint8 *data, gint len); -void qq_process_room_send_im_ex(PurpleConnection *gc, guint8 *data, gint len); - -void qq_process_room_im(guint8 *data, gint data_len, guint32 id, PurpleConnection *gc, guint16 msg_type); - -#endif - diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/qq/group_info.c --- a/libpurple/protocols/qq/group_info.c Thu May 05 03:40:29 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,396 +0,0 @@ -/** - * @file group_info.c - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * 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 02111-1301 USA - */ - -#include "internal.h" - -#include "conversation.h" -#include "debug.h" - -#include "char_conv.h" -#include "group_im.h" -#include "group_internal.h" -#include "group_info.h" -#include "buddy_list.h" -#include "qq_define.h" -#include "packet_parse.h" -#include "qq_network.h" -#include "utils.h" - -/* we check who needs to update member info every minutes - * this interval determines if their member info is outdated */ -#define QQ_GROUP_CHAT_REFRESH_NICKNAME_INTERNAL 180 - -static gboolean check_update_interval(qq_buddy_data *member) -{ - g_return_val_if_fail(member != NULL, FALSE); - return (member->nickname == NULL) || - (time(NULL) - member->last_update) > QQ_GROUP_CHAT_REFRESH_NICKNAME_INTERNAL; -} - -/* this is done when we receive the reply to get_online_members sub_cmd - * all member are set offline, and then only those in reply packets are online */ -static void set_all_offline(qq_room_data *rmd) -{ - GList *list; - qq_buddy_data *bd; - g_return_if_fail(rmd != NULL); - - list = rmd->members; - while (list != NULL) { - bd = (qq_buddy_data *) list->data; - bd->status = QQ_BUDDY_CHANGE_TO_OFFLINE; - list = list->next; - } -} - -/* send packet to get info for each group member */ -gint qq_request_room_get_buddies(PurpleConnection *gc, guint32 room_id, UPDCLS update_class) -{ - guint8 *raw_data; - gint bytes, num; - GList *list; - qq_room_data *rmd; - qq_buddy_data *bd; - - g_return_val_if_fail(room_id > 0, 0); - - rmd = qq_room_data_find(gc, room_id); - g_return_val_if_fail(rmd != NULL, 0); - - for (num = 0, list = rmd->members; list != NULL; list = list->next) { - bd = (qq_buddy_data *) list->data; - if (check_update_interval(bd)) - num++; - } - - if (num <= 0) { - purple_debug_info("QQ", "No group member info needs to be updated now.\n"); - return 0; - } - - raw_data = g_newa(guint8, 4 * num); - - bytes = 0; - - list = rmd->members; - while (list != NULL) { - bd = (qq_buddy_data *) list->data; - if (check_update_interval(bd)) - bytes += qq_put32(raw_data + bytes, bd->uid); - list = list->next; - } - - qq_send_room_cmd_mess(gc, QQ_ROOM_CMD_GET_BUDDIES, rmd->id, raw_data, bytes, - update_class, 0); - return num; -} - -static gchar *get_role_desc(qq_room_role role) -{ - const char *role_desc; - switch (role) { - case QQ_ROOM_ROLE_NO: - role_desc = _("Not member"); - break; - case QQ_ROOM_ROLE_YES: - role_desc = _("Member"); - break; - case QQ_ROOM_ROLE_REQUESTING: - role_desc = _("Requesting"); - break; - case QQ_ROOM_ROLE_ADMIN: - role_desc = _("Admin"); - break; - default: - role_desc = _("Unknown"); - } - - return g_strdup(role_desc); -} - -static void room_info_display(PurpleConnection *gc, qq_room_data *rmd) -{ - PurpleNotifyUserInfo *room_info; - gchar *utf8_value; - - g_return_if_fail(rmd != NULL && rmd->id > 0); - - room_info = purple_notify_user_info_new(); - - /* XXX: Should this be "Topic"? */ - purple_notify_user_info_add_pair(room_info, _("Room Title"), rmd->title_utf8); - purple_notify_user_info_add_pair(room_info, _("Notice"), rmd->notice_utf8); - purple_notify_user_info_add_pair(room_info, _("Detail"), rmd->desc_utf8); - - purple_notify_user_info_add_section_break(room_info); - - utf8_value = g_strdup_printf(("%u"), rmd->creator_uid); - purple_notify_user_info_add_pair(room_info, _("Creator"), utf8_value); - g_free(utf8_value); - - utf8_value = get_role_desc(rmd->my_role); - purple_notify_user_info_add_pair(room_info, _("About me"), utf8_value); - g_free(utf8_value); - - utf8_value = g_strdup_printf(("%d"), rmd->category); - purple_notify_user_info_add_pair(room_info, _("Category"), utf8_value); - g_free(utf8_value); - - utf8_value = g_strdup_printf(("%d"), rmd->auth_type); - purple_notify_user_info_add_pair(room_info, _("Authorize"), utf8_value); - g_free(utf8_value); - - utf8_value = g_strdup_printf(("%u"), rmd->ext_id); - purple_notify_userinfo(gc, utf8_value, room_info, NULL, NULL); - g_free(utf8_value); - - purple_notify_user_info_destroy(room_info); -} - -void qq_process_room_cmd_get_info(guint8 *data, gint data_len, guint32 action, PurpleConnection *gc) -{ - qq_data *qd; - qq_room_data *rmd; - qq_buddy_data *bd; - PurpleChat *chat; - PurpleConversation *conv; - guint8 organization, role; - guint16 unknown, max_members; - UID member_uid; - guint32 id, ext_id; - guint32 unknown4; - guint8 unknown1; - gint bytes, num; - gchar *notice; - gchar *topic_utf8; - - g_return_if_fail(data != NULL && data_len > 0); - qd = (qq_data *) gc->proto_data; - - /* qq_show_packet("Room Info", data, data_len); */ - - bytes = 0; - bytes += qq_get32(&id, data + bytes); - g_return_if_fail(id > 0); - - bytes += qq_get32(&ext_id, data + bytes); - g_return_if_fail(ext_id > 0); - - chat = qq_room_find_or_new(gc, id, ext_id); - g_return_if_fail(chat != NULL); - rmd = qq_room_data_find(gc, id); - g_return_if_fail(rmd != NULL); - - bytes += qq_get8(&(rmd->type8), data + bytes); - bytes += qq_get32(&unknown4, data + bytes); /* unknown 4 bytes */ - bytes += qq_get32(&(rmd->creator_uid), data + bytes); - bytes += qq_get8(&(rmd->auth_type), data + bytes); - bytes += qq_get32(&unknown4, data + bytes); /* oldCategory */ - bytes += qq_get16(&unknown, data + bytes); - bytes += qq_get32(&(rmd->category), data + bytes); - bytes += qq_get16(&max_members, data + bytes); - bytes += qq_get8(&unknown1, data + bytes); - /* the following, while Eva: - * 4(unk), 4(verID), 1(nameLen), nameLen(qunNameContent), 1(0x00), - * 2(qunNoticeLen), qunNoticeLen(qunNoticeContent, 1(qunDescLen), - * qunDestLen(qunDestcontent)) */ - bytes += qq_get8(&unknown1, data + bytes); - purple_debug_info("QQ", "type: %u creator: %u category: %u maxmembers: %u\n", - rmd->type8, rmd->creator_uid, rmd->category, max_members); - - if (qd->client_version >= 2007) { - /* skip 7 bytes unknow in qq2007 0x(00 00 01 00 00 00 fc)*/ - bytes += 7; - } - /* qq_show_packet("Room Info", data + bytes, data_len - bytes); */ - /* strlen + */ - bytes += qq_get_vstr(&(rmd->title_utf8), QQ_CHARSET_DEFAULT, data + bytes); - bytes += qq_get16(&unknown, data + bytes); /* 0x0000 */ - bytes += qq_get_vstr(¬ice, QQ_CHARSET_DEFAULT, data + bytes); - bytes += qq_get_vstr(&(rmd->desc_utf8), QQ_CHARSET_DEFAULT, data + bytes); - - purple_debug_info("QQ", "room [%s] notice [%s] desc [%s] unknow 0x%04X\n", - rmd->title_utf8, notice, rmd->desc_utf8, unknown); - - num = 0; - /* now comes the member list separated by 0x00 */ - while (bytes < data_len) { - bytes += qq_get32(&member_uid, data + bytes); - num++; - bytes += qq_get8(&organization, data + bytes); - bytes += qq_get8(&role, data + bytes); - -#if 0 - if(organization != 0 || role != 0) { - purple_debug_info("QQ", "%u, organization=%d, role=%d\n", member_uid, organization, role); - } -#endif - - bd = qq_room_buddy_find_or_new(gc, rmd, member_uid); - if (bd != NULL) - bd->role = role; - } - if(bytes > data_len) { - purple_debug_error("QQ", - "group_cmd_get_group_info: Dangerous error! maybe protocol changed, notify me!"); - } - - purple_debug_info("QQ", "group \"%s\" has %d members\n", rmd->title_utf8, num); - - if (rmd->creator_uid == qd->uid) - rmd->my_role = QQ_ROOM_ROLE_ADMIN; - - /* filter \r\n in notice */ - qq_filter_str(notice); - rmd->notice_utf8 = strdup(notice); - g_free(notice); - - qq_room_update_chat_info(chat, rmd); - - if (action == QQ_ROOM_INFO_DISPLAY) { - room_info_display(gc, rmd); - } - - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - rmd->title_utf8, purple_connection_get_account(gc)); - if(NULL == conv) { - purple_debug_warning("QQ", "Conversation \"%s\" is not opened\n", rmd->title_utf8); - return; - } - - topic_utf8 = g_strdup_printf("%u %s", rmd->ext_id, rmd->notice_utf8); - purple_debug_info("QQ", "Set chat topic to %s\n", topic_utf8); - purple_conv_chat_set_topic(PURPLE_CONV_CHAT(conv), NULL, topic_utf8); - g_free(topic_utf8); -} - -void qq_process_room_cmd_get_onlines(guint8 *data, gint len, PurpleConnection *gc) -{ - guint32 room_id; - UID member_uid; - guint8 unknown; - gint bytes, num; - qq_room_data *rmd; - qq_buddy_data *bd; - - g_return_if_fail(data != NULL && len > 0); - - if (len <= 3) { - purple_debug_error("QQ", "Invalid group online member reply, discard it!\n"); - return; - } - - bytes = 0; - bytes += qq_get32(&room_id, data + bytes); - bytes += qq_get8(&unknown, data + bytes); /* 0x3c ?? */ - g_return_if_fail(room_id > 0); - - rmd = qq_room_data_find(gc, room_id); - if (rmd == NULL) { - purple_debug_error("QQ", "Can not info of room id [%u]\n", room_id); - return; - } - - /* set all offline first, then update those online */ - set_all_offline(rmd); - num = 0; - while (bytes < len) { - bytes += qq_get32(&member_uid, data + bytes); - num++; - bd = qq_room_buddy_find_or_new(gc, rmd, member_uid); - if (bd != NULL) - bd->status = QQ_BUDDY_ONLINE_NORMAL; - } - if(bytes > len) { - purple_debug_error("QQ", - "group_cmd_get_online_members: Dangerous error! maybe protocol changed, notify developers!"); - } - - purple_debug_info("QQ", "Group \"%s\" has %d online members\n", rmd->title_utf8, num); - qq_room_conv_set_onlines(gc, rmd); -} - -/* process the reply to get_members_info packet */ -void qq_process_room_cmd_get_buddies(guint8 *data, gint len, PurpleConnection *gc) -{ - gint bytes; - gint num; - guint32 id; - UID member_uid; - guint16 unknown; - qq_room_data *rmd; - qq_buddy_data *bd; - gchar *nick; - - g_return_if_fail(data != NULL && len > 0); - - /* qq_show_packet("qq_process_room_cmd_get_buddies", data, len); */ - - bytes = 0; - bytes += qq_get32(&id, data + bytes); - g_return_if_fail(id > 0); - - rmd = qq_room_data_find(gc, id); - g_return_if_fail(rmd != NULL); - - num = 0; - /* now starts the member info, as get buddy list reply */ - while (bytes < len) { - bytes += qq_get32(&member_uid, data + bytes); - g_return_if_fail(member_uid > 0); - bd = qq_room_buddy_find_or_new(gc, rmd, member_uid); - g_return_if_fail(bd != NULL); - - num++; - bytes += qq_get16(&(bd->face), data + bytes); - bytes += qq_get8(&(bd->age), data + bytes); - bytes += qq_get8(&(bd->gender), data + bytes); - bytes += qq_get_vstr(&nick, QQ_CHARSET_DEFAULT, data + bytes); - bytes += qq_get16(&unknown, data + bytes); - bytes += qq_get8(&(bd->ext_flag), data + bytes); - bytes += qq_get8(&(bd->comm_flag), data + bytes); - - /* filter \r\n in nick */ - qq_filter_str(nick); - bd->nickname = g_strdup(nick); - g_free(nick); - -#if 0 - purple_debug_info("QQ", - "member [%09d]: ext_flag=0x%02x, comm_flag=0x%02x, nick=%s\n", - member_uid, bd->ext_flag, bd->comm_flag, bd->nickname); -#endif - - bd->last_update = time(NULL); - } - if (bytes > len) { - purple_debug_error("QQ", - "group_cmd_get_members_info: Dangerous error! maybe protocol changed, notify developers!"); - } - purple_debug_info("QQ", "Group \"%s\" got %d member info\n", rmd->title_utf8, num); - - rmd->is_got_buddies = TRUE; - qq_room_conv_set_onlines(gc, rmd); -} - diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/qq/group_info.h --- a/libpurple/protocols/qq/group_info.h Thu May 05 03:40:29 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,42 +0,0 @@ -/** - * @file group_info.h - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * 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 02111-1301 USA - */ - -#ifndef _QQ_GROUP_INFO_H_ -#define _QQ_GROUP_INFO_H_ - -#include -#include "connection.h" -#include "group.h" - -enum { - QQ_ROOM_INFO_UPDATE_ONLY = 0, - QQ_ROOM_INFO_DISPLAY -}; - -gint qq_request_room_get_buddies(PurpleConnection *gc, guint32 room_id, UPDCLS update_class); - -void qq_process_room_cmd_get_info(guint8 *data, gint len, guint32 action, PurpleConnection *gc); -void qq_process_room_cmd_get_onlines(guint8 *data, gint len, PurpleConnection *gc); -void qq_process_room_cmd_get_buddies(guint8 *data, gint len, PurpleConnection *gc); -#endif diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/qq/group_internal.c --- a/libpurple/protocols/qq/group_internal.c Thu May 05 03:40:29 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,434 +0,0 @@ -/** - * @file group_internal.c - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * 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 02111-1301 USA - */ - -#include "internal.h" -#include "blist.h" -#include "debug.h" - -#include "buddy_opt.h" -#include "group_internal.h" -#include "utils.h" - -static qq_room_data *room_data_new(guint32 id, guint32 ext_id, const gchar *title) -{ - qq_room_data *rmd; - - purple_debug_info("QQ", "Created room data: %s, ext id %u, id %u\n", - title == NULL ? "(NULL)" : title, - ext_id, id); - rmd = g_new0(qq_room_data, 1); - rmd->my_role = QQ_ROOM_ROLE_NO; - rmd->id = id; - rmd->ext_id = ext_id; - rmd->type8 = 0x01; /* assume permanent Qun */ - rmd->creator_uid = 10000; /* assume by QQ admin */ - rmd->category = 0x01; - rmd->auth_type = 0x02; /* assume need auth */ - rmd->title_utf8 = g_strdup(title == NULL ? "" : title); - rmd->desc_utf8 = g_strdup(""); - rmd->notice_utf8 = g_strdup(""); - rmd->members = NULL; - rmd->is_got_buddies = FALSE; - return rmd; -} - -/* create a qq_room_data from hashtable */ -static qq_room_data *room_data_new_by_hashtable(PurpleConnection *gc, GHashTable *data) -{ - qq_room_data *rmd; - guint32 id, ext_id; - gchar *value; - - value = g_hash_table_lookup(data, QQ_ROOM_KEY_INTERNAL_ID); - id = value ? strtoul(value, NULL, 10) : 0; - value = g_hash_table_lookup(data, QQ_ROOM_KEY_EXTERNAL_ID); - ext_id = value ? strtoul(value, NULL, 10) : 0; - value = g_hash_table_lookup(data, QQ_ROOM_KEY_TITLE_UTF8); - - rmd = room_data_new(id, ext_id, value); - rmd->my_role = QQ_ROOM_ROLE_YES; - return rmd; -} - -/* gracefully free all members in a room */ -static void room_buddies_free(qq_room_data *rmd) -{ - gint i; - GList *list; - qq_buddy_data *bd; - - g_return_if_fail(rmd != NULL); - i = 0; - while (NULL != (list = rmd->members)) { - bd = (qq_buddy_data *) list->data; - i++; - rmd->members = g_list_remove(rmd->members, bd); - qq_buddy_data_free(bd); - } - - rmd->members = NULL; -} - -/* gracefully free the memory for one qq_room_data */ -static void room_data_free(qq_room_data *rmd) -{ - g_return_if_fail(rmd != NULL); - room_buddies_free(rmd); - g_free(rmd->title_utf8); - g_free(rmd->desc_utf8); - g_free(rmd->notice_utf8); - g_free(rmd); -} - -void qq_room_update_chat_info(PurpleChat *chat, qq_room_data *rmd) -{ - GHashTable *components; - - if (rmd->title_utf8 != NULL && strlen(rmd->title_utf8) > 0) { - purple_blist_alias_chat(chat, rmd->title_utf8); - } - - components = purple_chat_get_components(chat); - - g_hash_table_replace(components, - g_strdup(QQ_ROOM_KEY_INTERNAL_ID), - g_strdup_printf("%u", rmd->id)); - g_hash_table_replace(components, - g_strdup(QQ_ROOM_KEY_EXTERNAL_ID), - g_strdup_printf("%u", rmd->ext_id)); - g_hash_table_replace(components, - g_strdup(QQ_ROOM_KEY_TITLE_UTF8), g_strdup(rmd->title_utf8)); -} - -static PurpleChat *chat_new(PurpleConnection *gc, qq_room_data *rmd) -{ - GHashTable *components; - PurpleGroup *g; - PurpleChat *chat; - - purple_debug_info("QQ", "Add new chat: id %u, ext id %u, title %s\n", - rmd->id, rmd->ext_id, - rmd->title_utf8 == NULL ? "(NULL)" : rmd->title_utf8); - - components = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); - g_hash_table_insert(components, - g_strdup(QQ_ROOM_KEY_INTERNAL_ID), g_strdup_printf("%u", rmd->id)); - g_hash_table_insert(components, g_strdup(QQ_ROOM_KEY_EXTERNAL_ID), - g_strdup_printf("%u", rmd->ext_id)); - g_hash_table_insert(components, g_strdup(QQ_ROOM_KEY_TITLE_UTF8), g_strdup(rmd->title_utf8)); - - chat = purple_chat_new(purple_connection_get_account(gc), rmd->title_utf8, components); - g = qq_group_find_or_new(PURPLE_GROUP_QQ_QUN); - purple_blist_add_chat(chat, g, NULL); - - return chat; -} - -PurpleChat *qq_room_find_or_new(PurpleConnection *gc, guint32 id, guint32 ext_id) -{ - qq_data *qd; - qq_room_data *rmd; - PurpleChat *chat; - gchar *num_str; - - g_return_val_if_fail (gc != NULL && gc->proto_data != NULL, NULL); - qd = (qq_data *) gc->proto_data; - - g_return_val_if_fail(id != 0 && ext_id != 0, NULL); - - purple_debug_info("QQ", "Find or add new room: id %u, ext id %u\n", id, ext_id); - - rmd = qq_room_data_find(gc, id); - if (rmd == NULL) { - rmd = room_data_new(id, ext_id, NULL); - g_return_val_if_fail(rmd != NULL, NULL); - rmd->my_role = QQ_ROOM_ROLE_YES; - qd->groups = g_list_append(qd->groups, rmd); - } - - num_str = g_strdup_printf("%u", ext_id); - chat = purple_blist_find_chat(purple_connection_get_account(gc), num_str); - g_free(num_str); - if (chat) { - return chat; - } - - return chat_new(gc, rmd); -} - -void qq_room_remove(PurpleConnection *gc, guint32 id) -{ - qq_data *qd; - PurpleChat *chat; - qq_room_data *rmd; - gchar *num_str; - guint32 ext_id; - - g_return_if_fail (gc != NULL && gc->proto_data != NULL); - qd = (qq_data *) gc->proto_data; - - purple_debug_info("QQ", "Find and remove room data, id %u\n", id); - rmd = qq_room_data_find(gc, id); - g_return_if_fail (rmd != NULL); - - ext_id = rmd->ext_id; - qd->groups = g_list_remove(qd->groups, rmd); - room_data_free(rmd); - - purple_debug_info("QQ", "Find and remove chat, ext_id %u\n", ext_id); - num_str = g_strdup_printf("%u", ext_id); - chat = purple_blist_find_chat(purple_connection_get_account(gc), num_str); - g_free(num_str); - - g_return_if_fail (chat != NULL); - - purple_blist_remove_chat(chat); -} - -/* find a qq_buddy_data by uid, called by im.c */ -qq_buddy_data *qq_room_buddy_find(qq_room_data *rmd, UID uid) -{ - GList *list; - qq_buddy_data *bd; - g_return_val_if_fail(rmd != NULL && uid > 0, NULL); - - list = rmd->members; - while (list != NULL) { - bd = (qq_buddy_data *) list->data; - if (bd->uid == uid) - return bd; - else - list = list->next; - } - - return NULL; -} - -/* remove a qq_buddy_data by uid, called by qq_group_opt.c */ -void qq_room_buddy_remove(qq_room_data *rmd, UID uid) -{ - GList *list; - qq_buddy_data *bd; - g_return_if_fail(rmd != NULL && uid > 0); - - list = rmd->members; - while (list != NULL) { - bd = (qq_buddy_data *) list->data; - if (bd->uid == uid) { - rmd->members = g_list_remove(rmd->members, bd); - return; - } else { - list = list->next; - } - } -} - -qq_buddy_data *qq_room_buddy_find_or_new(PurpleConnection *gc, qq_room_data *rmd, UID member_uid) -{ - qq_buddy_data *member, *bd; - PurpleBuddy *buddy; - g_return_val_if_fail(rmd != NULL && member_uid > 0, NULL); - - member = qq_room_buddy_find(rmd, member_uid); - if (member == NULL) { /* first appear during my session */ - member = g_new0(qq_buddy_data, 1); - member->uid = member_uid; - buddy = purple_find_buddy(purple_connection_get_account(gc), uid_to_purple_name(member_uid)); - if (buddy != NULL) { - const gchar *alias = NULL; - - bd = purple_buddy_get_protocol_data(buddy); - if (bd != NULL && bd->nickname != NULL) - member->nickname = g_strdup(bd->nickname); - else if ((alias = purple_buddy_get_alias(buddy)) != NULL) - member->nickname = g_strdup(alias); - } - rmd->members = g_list_append(rmd->members, member); - } - - return member; -} - -qq_room_data *qq_room_data_find(PurpleConnection *gc, guint32 room_id) -{ - GList *list; - qq_room_data *rmd; - qq_data *qd; - - qd = (qq_data *) gc->proto_data; - - if (qd->groups == NULL || room_id <= 0) - return 0; - - list = qd->groups; - while (list != NULL) { - rmd = (qq_room_data *) list->data; - if (rmd->id == room_id) { - return rmd; - } - list = list->next; - } - - return NULL; -} - -guint32 qq_room_get_next(PurpleConnection *gc, guint32 room_id) -{ - GList *list; - qq_room_data *rmd; - qq_data *qd; - gboolean is_find = FALSE; - - qd = (qq_data *) gc->proto_data; - - if (qd->groups == NULL) { - return 0; - } - - if (room_id <= 0) { - rmd = (qq_room_data *) qd->groups->data; - return rmd->id; - } - - list = qd->groups; - while (list != NULL) { - rmd = (qq_room_data *) list->data; - list = list->next; - if (rmd->id == room_id) { - is_find = TRUE; - break; - } - } - - g_return_val_if_fail(is_find, 0); - if (list == NULL) return 0; /* be the end */ - rmd = (qq_room_data *) list->data; - g_return_val_if_fail(rmd != NULL, 0); - return rmd->id; -} - -guint32 qq_room_get_next_conv(PurpleConnection *gc, guint32 room_id) -{ - GList *list; - qq_room_data *rmd; - qq_data *qd; - gboolean is_find; - - qd = (qq_data *) gc->proto_data; - - list = qd->groups; - if (room_id > 0) { - /* search next room */ - is_find = FALSE; - while (list != NULL) { - rmd = (qq_room_data *) list->data; - list = list->next; - if (rmd->id == room_id) { - is_find = TRUE; - break; - } - } - g_return_val_if_fail(is_find, 0); - } - - while (list != NULL) { - rmd = (qq_room_data *) list->data; - g_return_val_if_fail(rmd != NULL, 0); - - if (rmd->my_role == QQ_ROOM_ROLE_YES || rmd->my_role == QQ_ROOM_ROLE_ADMIN) { - if (NULL != purple_find_conversation_with_account( - PURPLE_CONV_TYPE_CHAT,rmd->title_utf8, purple_connection_get_account(gc))) { - /* In convseration*/ - return rmd->id; - } - } - list = list->next; - } - - return 0; -} - -/* this should be called upon signin, even when we did not open group chat window */ -void qq_room_data_initial(PurpleConnection *gc) -{ - PurpleAccount *account; - PurpleChat *chat; - PurpleGroup *purple_group; - PurpleBlistNode *node; - qq_data *qd; - qq_room_data *rmd; - gint count; - - account = purple_connection_get_account(gc); - qd = (qq_data *) gc->proto_data; - - purple_debug_info("QQ", "Initial QQ Qun configurations\n"); - purple_group = purple_find_group(PURPLE_GROUP_QQ_QUN); - if (purple_group == NULL) { - purple_debug_info("QQ", "We have no QQ Qun\n"); - return; - } - - count = 0; - for (node = purple_blist_node_get_first_child((PurpleBlistNode *)purple_group); - node != NULL; - node = purple_blist_node_get_sibling_next(node)) - { - if ( !PURPLE_BLIST_NODE_IS_CHAT(node)) { - continue; - } - /* got one */ - chat = (PurpleChat *) node; - if (account != purple_chat_get_account(chat)) /* not qq account*/ - continue; - - rmd = room_data_new_by_hashtable(gc, purple_chat_get_components(chat)); - qd->groups = g_list_append(qd->groups, rmd); - count++; - } - - purple_debug_info("QQ", "Load %d QQ Qun configurations\n", count); -} - -void qq_room_data_free_all(PurpleConnection *gc) -{ - qq_data *qd; - qq_room_data *rmd; - gint count; - - g_return_if_fail (gc != NULL && gc->proto_data != NULL); - qd = (qq_data *) gc->proto_data; - - count = 0; - while (qd->groups != NULL) { - rmd = (qq_room_data *) qd->groups->data; - qd->groups = g_list_remove(qd->groups, rmd); - room_data_free(rmd); - count++; - } - - if (count > 0) { - purple_debug_info("QQ", "%d rooms are freed\n", count); - } -} diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/qq/group_internal.h --- a/libpurple/protocols/qq/group_internal.h Thu May 05 03:40:29 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +0,0 @@ -/** - * @file group_internal.h - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * 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 02111-1301 USA - */ - -#ifndef _QQ_GROUP_HASH_H_ -#define _QQ_GROUP_HASH_H_ - -#include -#include "group.h" - -#define QQ_ROOM_KEY_INTERNAL_ID "id" -#define QQ_ROOM_KEY_EXTERNAL_ID "ext_id" -#define QQ_ROOM_KEY_TITLE_UTF8 "title_utf8" - -PurpleChat *qq_room_find_or_new(PurpleConnection *gc, guint32 id, guint32 ext_id); -void qq_room_remove(PurpleConnection *gc, guint32 id); -void qq_room_update_chat_info(PurpleChat *chat, qq_room_data *rmd); - -qq_buddy_data *qq_room_buddy_find(qq_room_data *rmd, UID uid); -void qq_room_buddy_remove(qq_room_data *rmd, UID uid); -qq_buddy_data *qq_room_buddy_find_or_new(PurpleConnection *gc, qq_room_data *rmd, UID member_uid); - -void qq_room_data_initial(PurpleConnection *gc); -void qq_room_data_free_all(PurpleConnection *gc); -qq_room_data *qq_room_data_find(PurpleConnection *gc, guint32 room_id); - -guint32 qq_room_get_next(PurpleConnection *gc, guint32 room_id); -guint32 qq_room_get_next_conv(PurpleConnection *gc, guint32 room_id); - -#endif diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/qq/group_join.c --- a/libpurple/protocols/qq/group_join.c Thu May 05 03:40:29 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,423 +0,0 @@ -/** - * @file group_join.c - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * 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 02111-1301 USA - */ - -#include "internal.h" - -#include "debug.h" -#include "notify.h" -#include "request.h" -#include "server.h" - -#include "char_conv.h" -#include "im.h" -#include "group_internal.h" -#include "group_info.h" -#include "group_join.h" -#include "group_opt.h" -#include "group_im.h" -#include "qq_define.h" -#include "packet_parse.h" -#include "qq_network.h" -#include "qq_process.h" - -enum { - QQ_ROOM_JOIN_OK = 0x01, - QQ_ROOM_JOIN_NEED_AUTH = 0x02, - QQ_ROOM_JOIN_DENIED = 0x03 -}; - -enum { - QQ_ROOM_SEARCH_TYPE_BY_ID = 0x01, - QQ_ROOM_SEARCH_TYPE_DEMO = 0x02 -}; - -static void group_quit_cb(qq_room_req *add_req) -{ - PurpleConnection *gc; - guint32 id; - qq_room_data *rmd; - - if (add_req->gc == NULL || add_req->id == 0) { - g_free(add_req); - return; - } - - gc = add_req->gc; - id = add_req->id; - - rmd = qq_room_data_find(gc, id); - if (rmd == NULL) { - g_free(add_req); - return; - } - - qq_send_room_cmd_only(gc, QQ_ROOM_CMD_QUIT, rmd->id); - g_free(add_req); -} - -/* send packet to join a group without auth */ -void qq_request_room_join(PurpleConnection *gc, qq_room_data *rmd) -{ - g_return_if_fail(rmd != NULL); - - if (rmd->my_role == QQ_ROOM_ROLE_NO) { - rmd->my_role = QQ_ROOM_ROLE_REQUESTING; - } - - switch (rmd->auth_type) { - case QQ_ROOM_AUTH_TYPE_NO_AUTH: - case QQ_ROOM_AUTH_TYPE_NEED_AUTH: - break; - case QQ_ROOM_AUTH_TYPE_NO_ADD: - if (rmd->my_role == QQ_ROOM_ROLE_NO - && rmd->my_role == QQ_ROOM_ROLE_REQUESTING) { - purple_notify_warning(gc, NULL, _("The Qun does not allow others to join"), NULL); - return; - } - break; - default: - purple_debug_error("QQ", "Unknown room auth type: %d\n", rmd->auth_type); - break; - } - - qq_send_room_cmd_only(gc, QQ_ROOM_CMD_JOIN, rmd->id); -} - -static void group_join_cb(qq_room_req *add_req, const gchar *reason_utf8) -{ - qq_room_data *rmd; - - g_return_if_fail(add_req != NULL); - if (add_req->gc == NULL || add_req->id == 0) { - g_free(add_req); - return; - } - - rmd = qq_room_data_find(add_req->gc, add_req->id); - if (rmd == NULL) { - purple_debug_error("QQ", "Can not find room data of %u\n", add_req->id); - g_free(add_req); - return; - } - - qq_send_cmd_group_auth(add_req->gc, rmd, QQ_ROOM_AUTH_REQUEST_APPLY, 0, reason_utf8); - g_free(add_req); -} - -static void room_join_cancel_cb(qq_room_req *add_req, const gchar *msg) -{ - g_return_if_fail(add_req != NULL); - g_free(add_req); -} - -static void do_room_join_request(PurpleConnection *gc, qq_room_data *rmd) -{ - gchar *msg; - qq_room_req *add_req; - g_return_if_fail(rmd != NULL); - - purple_debug_info("QQ", "Room id %u needs authentication\n", rmd->id); - - msg = g_strdup_printf("QQ Qun %u needs authentication\n", rmd->ext_id); - add_req = g_new0(qq_room_req, 1); - add_req->gc = gc; - add_req->id = rmd->id; - purple_request_input(gc, _("Join QQ Qun"), msg, - _("Input request here"), - _("Would you be my friend?"), TRUE, FALSE, NULL, - _("Send"), - G_CALLBACK(group_join_cb), - _("Cancel"), G_CALLBACK(room_join_cancel_cb), - purple_connection_get_account(gc), rmd->title_utf8, NULL, - add_req); - g_free(msg); -} - -void qq_send_cmd_group_auth(PurpleConnection *gc, qq_room_data *rmd, - guint8 opt, UID uid, const gchar *reason_utf8) -{ - guint8 raw_data[MAX_PACKET_SIZE - 16]; - gint bytes; - - g_return_if_fail(rmd != NULL); - - if (opt == QQ_ROOM_AUTH_REQUEST_APPLY) { - rmd->my_role = QQ_ROOM_ROLE_REQUESTING; - uid = 0; - } - - bytes = 0; - bytes += qq_put8(raw_data + bytes, opt); - bytes += qq_put32(raw_data + bytes, uid); - bytes += qq_put_vstr(raw_data + bytes, reason_utf8, QQ_CHARSET_DEFAULT); - - qq_send_room_cmd(gc, QQ_ROOM_CMD_AUTH, rmd->id, raw_data, bytes); -} - -/* If comes here, cmd is OK already */ -void qq_process_group_cmd_exit_group(guint8 *data, gint len, PurpleConnection *gc) -{ - gint bytes; - guint32 id; - - g_return_if_fail(data != NULL && len > 0); - - if (len < 4) { - purple_debug_error("QQ", "Invalid exit group reply, expect %d bytes, read %d bytes\n", 4, len); - return; - } - - bytes = 0; - bytes += qq_get32(&id, data + bytes); - - qq_room_remove(gc, id); -} - -/* Process the reply to group_auth subcmd */ -void qq_process_group_cmd_join_group_auth(guint8 *data, gint len, PurpleConnection *gc) -{ - gint bytes; - guint32 id; - qq_room_data *rmd; - gchar *msg; - - g_return_if_fail(data != NULL && len > 0); - - if (len < 4) { - purple_debug_error("QQ", - "Invalid join room reply, expect %d bytes, read %d bytes\n", 4, len); - return; - } - bytes = 0; - bytes += qq_get32(&id, data + bytes); - g_return_if_fail(id > 0); - - rmd = qq_room_data_find(gc, id); - if (rmd != NULL) { - msg = g_strdup_printf(_("Successfully joined Qun %s (%u)"), rmd->title_utf8, rmd->ext_id); - qq_got_message(gc, msg); - g_free(msg); - } else { - qq_got_message(gc, _("Successfully joined Qun")); - } -} - -/* process group cmd reply "join group" */ -void qq_process_group_cmd_join_group(guint8 *data, gint len, PurpleConnection *gc) -{ - gint bytes; - guint32 id; - guint8 reply; - qq_room_data *rmd; - gchar *msg; - - g_return_if_fail(data != NULL && len > 0); - - if (len < 5) { - purple_debug_error("QQ", - "Invalid join room reply, expect %d bytes, read %d bytes\n", 5, len); - return; - } - - bytes = 0; - bytes += qq_get32(&id, data + bytes); - bytes += qq_get8(&reply, data + bytes); - - /* join group OK */ - rmd = qq_room_data_find(gc, id); - /* need to check if group is NULL or not. */ - g_return_if_fail(rmd != NULL); - switch (reply) { - case QQ_ROOM_JOIN_OK: - purple_debug_info("QQ", "Succeeded in joining group \"%s\"\n", rmd->title_utf8); - rmd->my_role = QQ_ROOM_ROLE_YES; - /* this must be shown before getting online members */ - qq_room_conv_open(gc, rmd); - break; - case QQ_ROOM_JOIN_NEED_AUTH: - purple_debug_info("QQ", - "Failed to join room ext id %u %s, needs authentication\n", - rmd->ext_id, rmd->title_utf8); - rmd->my_role = QQ_ROOM_ROLE_NO; - do_room_join_request(gc, rmd); - break; - case QQ_ROOM_JOIN_DENIED: - msg = g_strdup_printf(_("Qun %u denied from joining"), rmd->ext_id); - purple_notify_info(gc, _("QQ Qun Operation"), _("Failed:"), msg); - g_free(msg); - break; - default: - purple_debug_info("QQ", - "Failed to join room ext id %u %s, unknown reply: 0x%02x\n", - rmd->ext_id, rmd->title_utf8, reply); - - purple_notify_info(gc, _("QQ Qun Operation"), _("Failed:"), _("Join Qun, Unknown Reply")); - } -} - -/* Attempt to join a group without auth */ -void qq_group_join(PurpleConnection *gc, GHashTable *data) -{ - gchar *ext_id_str; - gchar *id_str; - guint32 ext_id; - guint32 id; - qq_room_data *rmd; - - g_return_if_fail(data != NULL); - - ext_id_str = g_hash_table_lookup(data, QQ_ROOM_KEY_EXTERNAL_ID); - id_str = g_hash_table_lookup(data, QQ_ROOM_KEY_INTERNAL_ID); - purple_debug_info("QQ", "Join room %s, extend id %s\n", id_str, ext_id_str); - - if (id_str != NULL) { - id = strtoul(id_str, NULL, 10); - if (id != 0) { - rmd = qq_room_data_find(gc, id); - if (rmd) { - qq_request_room_join(gc, rmd); - return; - } - } - } - - purple_debug_info("QQ", "Search and join extend id %s\n", ext_id_str); - if (ext_id_str == NULL) { - return; - } - ext_id = strtoul(ext_id_str, NULL, 10); - if (ext_id == 0) { - return; - } - - qq_request_room_search(gc, ext_id, QQ_ROOM_SEARCH_FOR_JOIN); -} - -void qq_room_quit(PurpleConnection *gc, guint32 room_id) -{ - qq_room_req *add_req; - - add_req = g_new0(qq_room_req, 1); - add_req->gc = gc; - add_req->id = room_id; - - purple_request_action(gc, _("QQ Qun Operation"), - _("Quit Qun"), - _("Note, if you are the creator, \nthis operation will eventually remove this Qun."), - 1, - purple_connection_get_account(gc), NULL, NULL, - add_req, 2, _("Cancel"), - G_CALLBACK(room_join_cancel_cb), - _("Continue"), G_CALLBACK(group_quit_cb)); -} - -/* send packet to search for qq_group */ -void qq_request_room_search(PurpleConnection *gc, guint32 ext_id, int action) -{ - guint8 raw_data[16] = {0}; - gint bytes = 0; - guint8 type; - - purple_debug_info("QQ", "Search QQ Qun %u\n", ext_id); - type = (ext_id == 0x00000000) ? QQ_ROOM_SEARCH_TYPE_DEMO : QQ_ROOM_SEARCH_TYPE_BY_ID; - - bytes = 0; - bytes += qq_put8(raw_data + bytes, type); - bytes += qq_put32(raw_data + bytes, ext_id); - - qq_send_room_cmd_mess(gc, QQ_ROOM_CMD_SEARCH, 0, raw_data, bytes, 0, action); -} - -static void add_to_roomlist(qq_data *qd, qq_room_data *rmd) -{ - PurpleRoomlistRoom *room; - gchar field[11]; - - room = purple_roomlist_room_new(PURPLE_ROOMLIST_ROOMTYPE_ROOM, rmd->title_utf8, NULL); - g_snprintf(field, sizeof(field), "%u", rmd->ext_id); - purple_roomlist_room_add_field(qd->roomlist, room, field); - g_snprintf(field, sizeof(field), "%u", rmd->creator_uid); - purple_roomlist_room_add_field(qd->roomlist, room, field); - purple_roomlist_room_add_field(qd->roomlist, room, rmd->desc_utf8); - g_snprintf(field, sizeof(field), "%u", rmd->id); - purple_roomlist_room_add_field(qd->roomlist, room, field); - g_snprintf(field, sizeof(field), "%d", rmd->type8); - purple_roomlist_room_add_field(qd->roomlist, room, field); - g_snprintf(field, sizeof(field), "%d", rmd->auth_type); - purple_roomlist_room_add_field(qd->roomlist, room, field); - g_snprintf(field, sizeof(field), "%d", rmd->category); - purple_roomlist_room_add_field(qd->roomlist, room, field); - purple_roomlist_room_add_field(qd->roomlist, room, rmd->title_utf8); - purple_roomlist_room_add(qd->roomlist, room); - - purple_roomlist_set_in_progress(qd->roomlist, FALSE); -} - -/* process group cmd reply "search group" */ -void qq_process_room_search(PurpleConnection *gc, guint8 *data, gint len, guint32 ship32) -{ - qq_data *qd; - qq_room_data rmd; - PurpleChat *chat; - gint bytes; - guint8 search_type; - guint16 unknown; - - g_return_if_fail(data != NULL && len > 0); - qd = (qq_data *) gc->proto_data; - - bytes = 0; - bytes += qq_get8(&search_type, data + bytes); - - /* now it starts with group_info_entry */ - bytes += qq_get32(&(rmd.id), data + bytes); - bytes += qq_get32(&(rmd.ext_id), data + bytes); - bytes += qq_get8(&(rmd.type8), data + bytes); - bytes += qq_get16(&(unknown), data + bytes); - bytes += qq_get16(&(unknown), data + bytes); - bytes += qq_get32(&(rmd.creator_uid), data + bytes); - bytes += qq_get16(&(unknown), data + bytes); - bytes += qq_get16(&(unknown), data + bytes); - bytes += qq_get16(&(unknown), data + bytes); - bytes += qq_get32(&(rmd.category), data + bytes); - bytes += qq_get_vstr(&(rmd.title_utf8), QQ_CHARSET_DEFAULT, data + bytes); - bytes += qq_get16(&(unknown), data + bytes); - bytes += qq_get8(&(rmd.auth_type), data + bytes); - bytes += qq_get_vstr(&(rmd.desc_utf8), QQ_CHARSET_DEFAULT, data + bytes); - /* end of one qq_group */ - if(bytes != len) { - purple_debug_error("QQ", - "group_cmd_search_group: Dangerous error! maybe protocol changed, notify developers!"); - } - - if (ship32 == QQ_ROOM_SEARCH_FOR_JOIN) { - chat = qq_room_find_or_new(gc, rmd.id, rmd.ext_id); - g_return_if_fail(chat != NULL); - - qq_room_update_chat_info(chat, &rmd); - qq_request_room_join(gc, &rmd); - } else { - add_to_roomlist(qd, &rmd); - } -} diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/qq/group_join.h --- a/libpurple/protocols/qq/group_join.h Thu May 05 03:40:29 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,60 +0,0 @@ -/** - * @file group_join.h - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * 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 02111-1301 USA - */ - -#ifndef _QQ_GROUP_JOIN_H_ -#define _QQ_GROUP_JOIN_H_ - -#include -#include "connection.h" -#include "group.h" - -enum { - QQ_ROOM_AUTH_TYPE_NO_AUTH = 0x01, - QQ_ROOM_AUTH_TYPE_NEED_AUTH = 0x02, - QQ_ROOM_AUTH_TYPE_NO_ADD = 0x03 -}; - -enum { - QQ_ROOM_AUTH_REQUEST_APPLY = 0x01, - QQ_ROOM_AUTH_REQUEST_APPROVE = 0x02, - QQ_ROOM_AUTH_REQUEST_REJECT = 0x03 -}; - -enum { - QQ_ROOM_SEARCH_ONLY = 0, - QQ_ROOM_SEARCH_FOR_JOIN -}; - -void qq_request_room_search(PurpleConnection *gc, guint32 ext_id, int action); -void qq_process_room_search(PurpleConnection *gc, guint8 *data, gint len, guint32 ship32); - -void qq_send_cmd_group_auth(PurpleConnection *gc, qq_room_data *rmd, guint8 opt, UID uid, const gchar *reason_utf8); -void qq_group_join(PurpleConnection *gc, GHashTable *data); -void qq_request_room_join(PurpleConnection *gc, qq_room_data *rmd); -void qq_room_quit(PurpleConnection *gc, guint32 room_id); -void qq_process_group_cmd_exit_group(guint8 *data, gint len, PurpleConnection *gc); -void qq_process_group_cmd_join_group_auth(guint8 *data, gint len, PurpleConnection *gc); -void qq_process_group_cmd_join_group(guint8 *data, gint len, PurpleConnection *gc); -#endif - diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/qq/group_opt.c --- a/libpurple/protocols/qq/group_opt.c Thu May 05 03:40:29 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,592 +0,0 @@ -/** - * @file group_opt.c - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * 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 02111-1301 USA - */ - -#include "qq.h" - -#include "debug.h" -#include "notify.h" -#include "request.h" - -#include "buddy_info.h" -#include "char_conv.h" -#include "group_internal.h" -#include "group_info.h" -#include "group_join.h" -#include "group_im.h" -#include "group_opt.h" -#include "qq_define.h" -#include "packet_parse.h" -#include "qq_network.h" -#include "qq_process.h" -#include "utils.h" - -static int _compare_guint32(const void *a, - const void *b) -{ - const guint32 *x = a; - const guint32 *y = b; - return (*x - *y); -} - -static void _sort(guint32 *list) -{ - gint i; - for (i = 0; list[i] < 0xffffffff; i++) {; - } - qsort (list, i, sizeof (guint32), _compare_guint32); -} - -static void _qq_group_member_opt(PurpleConnection *gc, qq_room_data *rmd, gint operation, guint32 *members) -{ - guint8 *data; - gint i, count, data_len; - gint bytes; - g_return_if_fail(members != NULL); - - for (count = 0; members[count] != 0xffffffff; count++) {; - } - data_len = 6 + count * 4; - data = g_newa(guint8, data_len); - - bytes = 0; - bytes += qq_put8(data + bytes, operation); - for (i = 0; i < count; i++) - bytes += qq_put32(data + bytes, members[i]); - - qq_send_room_cmd(gc, QQ_ROOM_CMD_MEMBER_OPT, rmd->id, data, bytes); -} - -static void room_req_cancel_cb(qq_room_req *add_req) -{ - if (add_req != NULL) - g_free(add_req); -} - -static void member_join_authorize_cb(gpointer data) -{ - qq_room_req *add_req = (qq_room_req *)data; - qq_room_data *rmd; - g_return_if_fail(add_req != NULL && add_req->gc != NULL); - g_return_if_fail(add_req->id > 0 && add_req->member > 0); - rmd = qq_room_data_find(add_req->gc, add_req->id); - g_return_if_fail(rmd != NULL); - - qq_send_cmd_group_auth(add_req->gc, rmd, QQ_ROOM_AUTH_REQUEST_APPROVE, add_req->member, ""); - qq_room_buddy_find_or_new(add_req->gc, rmd, add_req->member); - g_free(add_req); -} - -static void member_join_deny_reason_cb(qq_room_req *add_req, gchar *msg_utf8) -{ - qq_room_data *rmd; - g_return_if_fail(add_req != NULL && add_req->gc != NULL); - g_return_if_fail(add_req->id > 0 && add_req->member > 0); - rmd = qq_room_data_find(add_req->gc, add_req->id); - g_return_if_fail(rmd != NULL); - qq_send_cmd_group_auth(add_req->gc, rmd, QQ_ROOM_AUTH_REQUEST_REJECT, add_req->member, msg_utf8); - g_free(add_req); -} - -static void member_join_deny_noreason_cb(qq_room_req *add_req, gchar *msg_utf8) -{ - member_join_deny_reason_cb(add_req, NULL); -} - -static void member_join_deny_cb(gpointer data) -{ - qq_room_req *add_req = (qq_room_req *)data; - gchar *who; - g_return_if_fail(add_req != NULL && add_req->gc != NULL); - g_return_if_fail(add_req->id > 0 && add_req->member > 0); - - who = uid_to_purple_name(add_req->member); - purple_request_input(add_req->gc, NULL, _("Authorization denied message:"), - NULL, _("Sorry, you are not our style"), TRUE, FALSE, NULL, - _("OK"), G_CALLBACK(member_join_deny_reason_cb), - _("Cancel"), G_CALLBACK(member_join_deny_noreason_cb), - purple_connection_get_account(add_req->gc), who, NULL, - add_req); - g_free(who); -} - -void qq_group_modify_members(PurpleConnection *gc, qq_room_data *rmd, guint32 *new_members) -{ - guint32 *old_members, *del_members, *add_members; - qq_buddy_data *bd; - gint i = 0, old = 0, new = 0, del = 0, add = 0; - GList *list; - - g_return_if_fail(rmd != NULL); - if (new_members[0] == 0xffffffff) - return; - - old_members = g_newa(guint32, QQ_QUN_MEMBER_MAX); - del_members = g_newa(guint32, QQ_QUN_MEMBER_MAX); - add_members = g_newa(guint32, QQ_QUN_MEMBER_MAX); - - /* construct the old member list */ - list = rmd->members; - while (list != NULL) { - bd = (qq_buddy_data *) list->data; - if (bd != NULL) - old_members[i++] = bd->uid; - list = list->next; - } - old_members[i] = 0xffffffff; /* this is the end */ - - /* sort to speed up making del_members and add_members list */ - _sort(old_members); - _sort(new_members); - - for (old = 0, new = 0; old_members[old] < 0xffffffff || new_members[new] < 0xffffffff;) { - if (old_members[old] > new_members[new]) { - add_members[add++] = new_members[new++]; - } else if (old_members[old] < new_members[new]) { - del_members[del++] = old_members[old++]; - } else { - if (old_members[old] < 0xffffffff) - old++; - if (new_members[new] < 0xffffffff) - new++; - } - } - del_members[del] = add_members[add] = 0xffffffff; - - for (i = 0; i < del; i++) - qq_room_buddy_remove(rmd, del_members[i]); - for (i = 0; i < add; i++) - qq_room_buddy_find_or_new(gc, rmd, add_members[i]); - - if (del > 0) - _qq_group_member_opt(gc, rmd, QQ_ROOM_MEMBER_DEL, del_members); - if (add > 0) - _qq_group_member_opt(gc, rmd, QQ_ROOM_MEMBER_ADD, add_members); -} - -void qq_group_process_modify_members_reply(guint8 *data, gint len, PurpleConnection *gc) -{ - gint bytes; - guint32 id; - time_t now = time(NULL); - qq_room_data *rmd; - g_return_if_fail(data != NULL); - - bytes = 0; - bytes += qq_get32(&id, data + bytes); - g_return_if_fail(id > 0); - - /* we should have its info locally */ - rmd = qq_room_data_find(gc, id); - g_return_if_fail(rmd != NULL); - - purple_debug_info("QQ", "Succeed in modify members for room %u\n", rmd->ext_id); - - qq_room_got_chat_in(gc, id, 0, _("Successfully changed Qun members"), now); -} - -void qq_room_change_info(PurpleConnection *gc, qq_room_data *rmd) -{ - guint8 data[MAX_PACKET_SIZE - 16]; - gint bytes; - - g_return_if_fail(rmd != NULL); - - bytes = 0; - /* 005-005 */ - bytes += qq_put8(data + bytes, 0x01); - /* 006-006 */ - bytes += qq_put8(data + bytes, rmd->auth_type); - /* 007-008 */ - bytes += qq_put16(data + bytes, 0x0000); - /* 009-010 */ - bytes += qq_put16(data + bytes, rmd->category); - - bytes += qq_put_vstr(data + bytes, rmd->title_utf8, QQ_CHARSET_DEFAULT); - - bytes += qq_put16(data + bytes, 0x0000); - - bytes += qq_put_vstr(data + bytes, rmd->notice_utf8, QQ_CHARSET_DEFAULT); - bytes += qq_put_vstr(data + bytes, rmd->desc_utf8, QQ_CHARSET_DEFAULT); - - qq_send_room_cmd(gc, QQ_ROOM_CMD_CHANGE_INFO, rmd->id, data, bytes); -} - -void qq_group_process_modify_info_reply(guint8 *data, gint len, PurpleConnection *gc) -{ - gint bytes; - guint32 id; - time_t now = time(NULL); - - g_return_if_fail(data != NULL); - - bytes = 0; - bytes += qq_get32(&id, data + bytes); - g_return_if_fail(id > 0); - - purple_debug_info("QQ", "Successfully modified room info of %u\n", id); - - qq_room_got_chat_in(gc, id, 0, _("Successfully changed Qun information"), now); -} - -/* we create a very simple room first, and then let the user to modify */ -void qq_create_room(PurpleConnection *gc, const gchar *name) -{ - guint8 *data; - gint data_len; - gint bytes; - qq_data *qd; - g_return_if_fail(name != NULL); - - qd = (qq_data *) gc->proto_data; - - data_len = 64 + strlen(name); - data = g_newa(guint8, data_len); - - bytes = 0; - /* we create the simpleset group, only group name is given */ - /* 001 */ - bytes += qq_put8(data + bytes, QQ_ROOM_TYPE_PERMANENT); - /* 002 */ - bytes += qq_put8(data + bytes, QQ_ROOM_AUTH_TYPE_NEED_AUTH); - /* 003-004 */ - bytes += qq_put16(data + bytes, 0x0000); - /* 005-006 */ - bytes += qq_put16(data + bytes, 0x0003); - /* 007 */ - bytes += qq_put8(data + bytes, strlen(name)); - bytes += qq_putdata(data + bytes, (guint8 *) name, strlen(name)); - bytes += qq_put16(data + bytes, 0x0000); - bytes += qq_put8(data + bytes, 0x00); /* no group notice */ - bytes += qq_put8(data + bytes, 0x00); /* no group desc */ - bytes += qq_put32(data + bytes, qd->uid); /* I am member of coz */ - - if (bytes > data_len) { - purple_debug_error("QQ", - "Overflow in qq_room_create, max %d bytes, now %d bytes\n", - data_len, bytes); - return; - } - qq_send_room_cmd_noid(gc, QQ_ROOM_CMD_CREATE, data, bytes); -} - -static void room_create_cb(qq_room_req *add_req) -{ - qq_room_data *rmd; - g_return_if_fail(add_req != NULL); - if (add_req->gc == NULL || add_req->id == 0) { - g_free(add_req); - return; - } - - rmd = qq_room_data_find(add_req->gc, add_req->id); - if (rmd == NULL) { - g_free(add_req); - return; - } - - /* TODO insert UI code here */ - /* qq_group_detail_window_show(g->gc, rmd); */ - g_free(add_req); -} - -void qq_group_process_create_group_reply(guint8 *data, gint len, PurpleConnection *gc) -{ - gint bytes; - guint32 id, ext_id; - qq_room_data *rmd; - qq_room_req *add_req; - qq_data *qd; - - g_return_if_fail(data != NULL); - g_return_if_fail(gc->proto_data != NULL); - qd = (qq_data *) gc->proto_data; - - bytes = 0; - bytes += qq_get32(&id, data + bytes); - bytes += qq_get32(&ext_id, data + bytes); - g_return_if_fail(id > 0 && ext_id); - - qq_room_find_or_new(gc, id, ext_id); - rmd = qq_room_data_find(gc, id); - g_return_if_fail(rmd != NULL); - - rmd->my_role = QQ_ROOM_ROLE_ADMIN; - rmd->creator_uid = qd->uid; - - qq_send_room_cmd_only(gc, QQ_ROOM_CMD_ACTIVATE, id); - qq_update_room(gc, 0, rmd->id); - - purple_debug_info("QQ", "Succeed in create Qun, ext id %u\n", rmd->ext_id); - - add_req = g_new0(qq_room_req, 1); - add_req->gc = gc; - add_req->id = id; - - purple_request_action(gc, _("QQ Qun Operation"), - _("You have successfully created a Qun"), - _("Would you like to set up detailed information now?"), - 1, - purple_connection_get_account(gc), NULL, NULL, - add_req, 2, - _("Setup"), G_CALLBACK(room_create_cb), - _("Cancel"), G_CALLBACK(room_req_cancel_cb)); -} - -void qq_group_process_activate_group_reply(guint8 *data, gint len, PurpleConnection *gc) -{ - gint bytes; - guint32 id; - qq_room_data *rmd; - g_return_if_fail(data != NULL); - - bytes = 0; - bytes += qq_get32(&id, data + bytes); - g_return_if_fail(id > 0); - - /* we should have its info locally */ - rmd = qq_room_data_find(gc, id); - g_return_if_fail(rmd != NULL); - - purple_debug_info("QQ", "Succeed in activate Qun %u\n", rmd->ext_id); -} - -void qq_group_manage_group(PurpleConnection *gc, GHashTable *data) -{ - gchar *id_ptr; - guint32 id; - qq_room_data *rmd; - - g_return_if_fail(data != NULL); - - id_ptr = g_hash_table_lookup(data, QQ_ROOM_KEY_INTERNAL_ID); - id = strtoul(id_ptr, NULL, 10); - g_return_if_fail(id > 0); - - rmd = qq_room_data_find(gc, id); - g_return_if_fail(rmd != NULL); - - /* XXX insert UI code here */ - /* qq_group_detail_window_show(gc, rmd); */ -} - -/* receive an application to join the group */ -void qq_process_room_buddy_request_join(guint8 *data, gint len, guint32 id, PurpleConnection *gc) -{ - guint32 ext_id, member_id; - guint8 type8; - gchar *msg, *reason; - qq_room_req *add_req; - gchar *who; - gint bytes = 0; - qq_room_data *rmd; - time_t now = time(NULL); - - g_return_if_fail(id > 0 && data != NULL && len > 0); - - /* FIXME: check length here */ - - bytes += qq_get32(&ext_id, data + bytes); - bytes += qq_get8(&type8, data + bytes); - bytes += qq_get32(&member_id, data + bytes); - - g_return_if_fail(ext_id > 0 && member_id > 0); - - bytes += qq_get_vstr(&reason, QQ_CHARSET_DEFAULT, data + bytes); - - purple_debug_info("QQ", "%u requested to join room, ext id %u\n", member_id, ext_id); - - rmd = qq_room_data_find(gc, id); - g_return_if_fail(rmd != NULL); - if (qq_room_buddy_find(rmd, member_id)) { - purple_debug_info("QQ", "Approve join, buddy joined before\n"); - msg = g_strdup_printf(_("%u requested to join Qun %u for %s"), - member_id, ext_id, reason); - qq_room_got_chat_in(gc, id, 0, msg, now); - qq_send_cmd_group_auth(gc, rmd, QQ_ROOM_AUTH_REQUEST_APPROVE, member_id, ""); - g_free(msg); - g_free(reason); - return; - } - - if (purple_prefs_get_bool("/plugins/prpl/qq/auto_get_authorize_info")) { - qq_request_buddy_info(gc, member_id, 0, QQ_BUDDY_INFO_DISPLAY); - } - who = uid_to_purple_name(member_id); - msg = g_strdup_printf(_("%u request to join Qun %u"), member_id, ext_id); - - add_req = g_new0(qq_room_req, 1); - add_req->gc = gc; - add_req->id = id; - add_req->member = member_id; - - purple_request_action(gc, _("QQ Qun Operation"), - msg, reason, - PURPLE_DEFAULT_ACTION_NONE, - purple_connection_get_account(gc), who, NULL, - add_req, 2, - _("Deny"), G_CALLBACK(member_join_deny_cb), - _("Authorize"), G_CALLBACK(member_join_authorize_cb)); - - g_free(who); - g_free(msg); - g_free(reason); -} - -/* the request to join a group is rejected */ -void qq_process_room_buddy_rejected(guint8 *data, gint len, guint32 id, PurpleConnection *gc) -{ - guint32 ext_id, admin_uid; - guint8 type8; - gchar *msg, *reason; - qq_room_data *rmd; - gint bytes; - - g_return_if_fail(data != NULL && len > 0); - - /* FIXME: check length here */ - bytes = 0; - bytes += qq_get32(&ext_id, data + bytes); - bytes += qq_get8(&type8, data + bytes); - bytes += qq_get32(&admin_uid, data + bytes); - - g_return_if_fail(ext_id > 0 && admin_uid > 0); - - bytes += qq_get_vstr(&reason, QQ_CHARSET_DEFAULT, data + bytes); - - msg = g_strdup_printf - (_("Failed to join Qun %u, operated by admin %u"), ext_id, admin_uid); - - purple_notify_warning(gc, _("QQ Qun Operation"), msg, reason); - - qq_room_find_or_new(gc, id, ext_id); - rmd = qq_room_data_find(gc, id); - if (rmd != NULL) { - rmd->my_role = QQ_ROOM_ROLE_NO; - } - - g_free(msg); - g_free(reason); -} - -/* the request to join a group is approved */ -void qq_process_room_buddy_approved(guint8 *data, gint len, guint32 id, PurpleConnection *gc) -{ - guint32 ext_id, admin_uid; - guint8 type8; - gchar *msg, *reason; - qq_room_data *rmd; - gint bytes; - time_t now; - - g_return_if_fail(data != NULL && len > 0); - - /* FIXME: check length here */ - bytes = 0; - bytes += qq_get32(&ext_id, data + bytes); - bytes += qq_get8(&type8, data + bytes); - bytes += qq_get32(&admin_uid, data + bytes); - - g_return_if_fail(ext_id > 0 && admin_uid > 0); - /* it is also a "无" here, so do not display */ - bytes += qq_get_vstr(&reason, QQ_CHARSET_DEFAULT, data + bytes); - - qq_room_find_or_new(gc, id, ext_id); - rmd = qq_room_data_find(gc, id); - if (rmd != NULL) { - rmd->my_role = QQ_ROOM_ROLE_YES; - } - - msg = g_strdup_printf(_("Joining Qun %u is approved by admin %u for %s"), - ext_id, admin_uid, reason); - now = time(NULL); - qq_room_got_chat_in(gc, id, 0, msg, now); - - g_free(msg); - g_free(reason); -} - -/* process the packet when removed from a group */ -void qq_process_room_buddy_removed(guint8 *data, gint len, guint32 id, PurpleConnection *gc) -{ - guint32 ext_id, uid; - guint8 type8; - gchar *msg; - qq_room_data *rmd; - gint bytes = 0; - time_t now = time(NULL); - - g_return_if_fail(data != NULL && len > 0); - - /* FIXME: check length here */ - bytes = 0; - bytes += qq_get32(&ext_id, data + bytes); - bytes += qq_get8(&type8, data + bytes); - bytes += qq_get32(&uid, data + bytes); - - g_return_if_fail(ext_id > 0 && uid > 0); - - qq_room_find_or_new(gc, id, ext_id); - rmd = qq_room_data_find(gc, id); - if (rmd != NULL) { - rmd->my_role = QQ_ROOM_ROLE_NO; - } - - msg = g_strdup_printf(_("Removed buddy %u."), uid); - qq_room_got_chat_in(gc, id, 0, msg, now); - g_free(msg); -} - -/* process the packet when added to a group */ -void qq_process_room_buddy_joined(guint8 *data, gint len, guint32 id, PurpleConnection *gc) -{ - guint32 ext_id, uid; - guint8 type8; - qq_room_data *rmd; - gint bytes; - gchar *msg; - time_t now = time(NULL); - - g_return_if_fail(data != NULL && len > 0); - - /* FIXME: check length here */ - bytes = 0; - bytes += qq_get32(&ext_id, data + bytes); - bytes += qq_get8(&type8, data + bytes); - bytes += qq_get32(&uid, data + bytes); - - g_return_if_fail(ext_id > 0 && id > 0); - - qq_room_find_or_new(gc, id, ext_id); - rmd = qq_room_data_find(gc, id); - g_return_if_fail(rmd != NULL); - - rmd->my_role = QQ_ROOM_ROLE_YES; - - qq_update_room(gc, 0, rmd->id); - - msg = g_strdup_printf(_("New buddy %u joined."), uid); - qq_room_got_chat_in(gc, id, 0, msg, now); - g_free(msg); -} - diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/qq/group_opt.h --- a/libpurple/protocols/qq/group_opt.h Thu May 05 03:40:29 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ -/** - * @file group_opt.h - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * 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 02111-1301 USA - */ - -#ifndef _QQ_GROUP_OPT_H_ -#define _QQ_GROUP_OPT_H_ - -#include -#include "connection.h" -#include "group.h" - -#define QQ_QUN_MEMBER_MAX 80 /* max number of the group */ - -typedef struct _qq_room_req { - PurpleConnection *gc; - guint32 id; - guint32 member; -} qq_room_req; - -enum { - QQ_ROOM_TYPE_PERMANENT = 0x01, - QQ_ROOM_TYPE_TEMPORARY -}; - -enum { - QQ_ROOM_MEMBER_ADD = 0x01, - QQ_ROOM_MEMBER_DEL -}; - -void qq_group_modify_members(PurpleConnection *gc, qq_room_data *rmd, guint32 *new_members); -void qq_room_change_info(PurpleConnection *gc, qq_room_data *rmd); - -void qq_create_room(PurpleConnection *gc, const gchar *name); -void qq_group_process_modify_info_reply(guint8 *data, gint len, PurpleConnection *gc); -void qq_group_process_modify_members_reply(guint8 *data, gint len, PurpleConnection *gc); -void qq_group_manage_group(PurpleConnection *gc, GHashTable *data); -void qq_group_process_activate_group_reply(guint8 *data, gint len, PurpleConnection *gc); -void qq_group_process_create_group_reply(guint8 *data, gint len, PurpleConnection *gc); - -void qq_process_room_buddy_request_join(guint8 *data, gint len, guint32 id, PurpleConnection *gc); -void qq_process_room_buddy_rejected(guint8 *data, gint len, guint32 id, PurpleConnection *gc); -void qq_process_room_buddy_approved(guint8 *data, gint len, guint32 id, PurpleConnection *gc); -void qq_process_room_buddy_removed(guint8 *data, gint len, guint32 id, PurpleConnection *gc); -void qq_process_room_buddy_joined(guint8 *data, gint len, guint32 id, PurpleConnection *gc); -#endif diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/qq/im.c --- a/libpurple/protocols/qq/im.c Thu May 05 03:40:29 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1325 +0,0 @@ -/** - * @file im.c - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * 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 02111-1301 USA - */ - -#include "internal.h" - -#include "conversation.h" -#include "debug.h" -#include "internal.h" -#include "notify.h" -#include "server.h" -#include "util.h" - -#include "buddy_info.h" -#include "buddy_list.h" -#include "buddy_opt.h" -#include "char_conv.h" -#include "qq_define.h" -#include "im.h" -#include "packet_parse.h" -#include "qq_network.h" -#include "send_file.h" -#include "utils.h" - -#define QQ_MSG_IM_MAX 700 /* max length of IM */ - -enum { - QQ_IM_TEXT = 0x01, - QQ_IM_AUTO_REPLY = 0x02 -}; - -enum -{ - QQ_NORMAL_IM_TEXT = 0x000b, - QQ_NORMAL_IM_FILE_REQUEST_TCP = 0x0001, - QQ_NORMAL_IM_FILE_APPROVE_TCP = 0x0003, - QQ_NORMAL_IM_FILE_REJECT_TCP = 0x0005, - QQ_NORMAL_IM_FILE_REQUEST_UDP = 0x0035, - QQ_NORMAL_IM_FILE_APPROVE_UDP = 0x0037, - QQ_NORMAL_IM_FILE_REJECT_UDP = 0x0039, - QQ_NORMAL_IM_FILE_NOTIFY = 0x003b, - QQ_NORMAL_IM_FILE_PASV = 0x003f, /* are you behind a firewall? */ - QQ_NORMAL_IM_FILE_CANCEL = 0x0049, - QQ_NORMAL_IM_FILE_EX_REQUEST_UDP = 0x81, - QQ_NORMAL_IM_FILE_EX_REQUEST_ACCEPT = 0x83, - QQ_NORMAL_IM_FILE_EX_REQUEST_CANCEL = 0x85, - QQ_NORMAL_IM_FILE_EX_NOTIFY_IP = 0x87 -}; - -typedef struct _qq_im_header { - /* this is the common part of normal_text */ - guint16 version_from; - UID uid_from; - UID uid_to; - guint8 session_md5[QQ_KEY_LENGTH]; - guint16 im_type; -} qq_im_header; - -/* read the common parts of the normal_im, - * returns the bytes read if succeed, or -1 if there is any error */ -static gint get_im_header(qq_im_header *im_header, guint8 *data, gint len) -{ - gint bytes; - g_return_val_if_fail(data != NULL && len > 0, -1); - - bytes = 0; - bytes += qq_get16(&(im_header->version_from), data + bytes); - bytes += qq_get32(&(im_header->uid_from), data + bytes); - bytes += qq_get32(&(im_header->uid_to), data + bytes); - bytes += qq_getdata(im_header->session_md5, QQ_KEY_LENGTH, data + bytes); - bytes += qq_get16(&(im_header->im_type), data + bytes); - return bytes; -} - -typedef struct _qq_emoticon { - guint8 symbol; - gchar *name; -} qq_emoticon; - -static gboolean emoticons_is_sorted = FALSE; -/* Map for purple smiley convert to qq, need qsort */ -static qq_emoticon emoticons_std[] = { - {0x4f, "/:)"}, {0x4f, "/wx"}, {0x4f, "/small_smile"}, - {0x42, "/:~"}, {0x42, "/pz"}, {0x42, "/curl_lip"}, - {0x43, "/:*"}, {0x43, "/se"}, {0x43, "/desire"}, - {0x44, "/:|"}, {0x44, "/fd"}, {0x44, "/dazed"}, - {0x45, "/8-)"}, {0x45, "/dy"}, {0x45, "/revel"}, - {0x46, "/:<"}, {0x46, "/ll"}, {0x46, "/cry"}, - {0x47, "/:$"}, {0x47, "/hx"}, {0x47, "/bashful"}, - {0x48, "/:x"}, {0x48, "/bz"}, {0x48, "/shut_mouth"}, - {0x8f, "/|-)"}, {0x8f, "/kun"}, {0x8f, "/sleepy"}, - {0x49, "/:z"}, {0x49, "/shui"}, {0x49, "/sleep"}, /* after sleepy */ - {0x4a, "/:'"}, {0x4a, "/dk"}, {0x4a, "/weep"}, - {0x4b, "/:-|"}, {0x4b, "/gg"}, {0x4b, "/embarassed"}, - {0x4c, "/:@"}, {0x4c, "/fn"}, {0x4c, "/pissed_off"}, - {0x4d, "/:P"}, {0x4d, "/tp"}, {0x4d, "/act_up"}, - {0x4e, "/:D"}, {0x4e, "/cy"}, {0x4e, "/toothy_smile"}, - {0x41, "/:O"}, {0x41, "/jy"}, {0x41, "/surprised"}, - {0x73, "/:("}, {0x73, "/ng"}, {0x73, "/sad"}, - {0x74, "/:+"}, {0x74, "/kuk"}, {0x74, "/cool"}, - {0xa1, "/--b"}, {0xa1, "/lengh"}, - {0x76, "/:Q"}, {0x76, "/zk"}, {0x76, "/crazy"}, - {0x8a, "/;P"}, {0x8a, "/tx"}, {0x8a, "/titter"}, - {0x8b, "/;-D"}, {0x8b, "/ka"}, {0x8b, "/cute"}, - {0x8c, "/;d"}, {0x8c, "/by"}, {0x8c, "/disdain"}, - {0x8d, "/;o"}, {0x8d, "/am"}, {0x8d, "/arrogant"}, - {0x8e, "/:g"}, {0x8e, "/jie"}, {0x8e, "/starving"}, - {0x78, "/:!"}, {0x78, "/jk"}, {0x78, "/terror"}, - {0x79, "/:L"}, {0x79, "/lh"}, {0x79, "/sweat"}, - {0x7a, "/:>"}, {0x7a, "/hanx"}, {0x7a, "/smirk"}, - {0x7b, "/:;"}, {0x7b, "/db"}, {0x7b, "/soldier"}, - {0x90, "/;f"}, {0x90, "/fendou"}, {0x90, "/struggle"}, - {0x91, "/:-S"}, {0x91, "/zhm"}, {0x91, "/curse"}, - {0x92, "/?"}, {0x92, "/yiw"}, {0x92, "/question"}, - {0x93, "/;x"}, {0x93, "/xu"}, {0x93, "/shh"}, - {0x94, "/;@"}, {0x94, "/yun"}, {0x94, "/dizzy"}, - {0x95, "/:8"}, {0x95, "/zhem"}, {0x95, "/excrutiating"}, - {0x96, "/;!"}, {0x96, "/shuai"}, {0x96, "/freaked_out"}, - {0x97, "/!!!"}, {0x97, "/kl"}, {0x97, "/skeleton"}, - {0x98, "/xx"}, {0x98, "/qiao"}, {0x98, "/hammer"}, - {0x99, "/bye"}, {0x99, "/zj"}, {0x99, "/bye"}, - {0xa2, "/wipe"}, {0xa2, "/ch"}, - {0xa3, "/dig"}, {0xa3, "/kb"}, - {0xa4, "/handclap"},{0xa4, "/gz"}, - {0xa5, "/&-("}, {0xa5, "/qd"}, - {0xa6, "/B-)"}, {0xa6, "/huaix"}, - {0xa7, "/<@"}, {0xa7, "/zhh"}, - {0xa8, "/@>"}, {0xa8, "/yhh"}, - {0xa9, "/:-O"}, {0xa9, "/hq"}, - {0xaa, "/>-|"}, {0xaa, "/bs"}, - {0xab, "/P-("}, {0xab, "/wq"}, - {0xac, "/:'|"}, {0xac, "/kk"}, - {0xad, "/X-)"}, {0xad, "/yx"}, - {0xae, "/:*"}, {0xae, "/qq"}, - {0xaf, "/@x"}, {0xaf, "/xia"}, - {0xb0, "/8*"}, {0xb0, "/kel"}, - {0xb1, "/pd"}, {0xb1, "/cd"}, - {0x61, "/"}, {0x61, "/xig"}, {0x61, "/watermelon"}, - {0xb2, "/beer"}, {0xb2, "/pj"}, - {0xb3, "/basketb"}, {0xb3, "/lq"}, - {0xb4, "/oo"}, {0xb4, "/pp"}, - {0x80, "/coffee"}, {0x80, "/kf"}, - {0x81, "/eat"}, {0x81, "/fan"}, - {0x62, "/rose"}, {0x62, "/mg"}, - {0x63, "/fade"}, {0x63, "/dx"}, {0x63, "/wilt"}, - {0xb5, "/showlove"},{0xb5, "/sa"}, /* after sad */ - {0x65, "/heart"}, {0x65, "/xin"}, - {0x66, "/break"}, {0x66, "/xs"}, {0x66, "/broken_heart"}, - {0x67, "/cake"}, {0x67, "/dg"}, - {0x9c, "/li"}, {0x9c, "/shd"}, {0x9c, "/lightning"}, - {0x9d, "/bome"}, {0x9d, "/zhd"}, {0x9d, "/bomb"}, - {0x9e, "/kn"}, {0x9e, "/dao"}, {0x9e, "/knife"}, - {0x5e, "/footb"}, {0x5e, "/zq"}, {0x5e, "/soccer"}, - {0xb6, "/ladybug"}, {0xb6, "/pc"}, - {0x89, "/shit"}, {0x89, "/bb"}, - {0x6e, "/moon"}, {0x6e, "/yl"}, - {0x6b, "/sun"}, {0x6b, "/ty"}, - {0x68, "/gift"}, {0x68, "/lw"}, - {0x7f, "/hug"}, {0x7f, "/yb"}, - {0x6f, "/strong"}, {0x6f, "/qiang"}, {0x6f, "/thumbs_up"}, - {0x70, "/weak"}, {0x70, "/ruo"}, {0x70, "/thumbs_down"}, - {0x88, "/share"}, {0x88, "/ws"}, {0x88, "/handshake"}, - {0xb7, "/@)"}, {0xb7, "/bq"}, - {0xb8, "/jj"}, {0xb8, "/gy"}, - {0xb9, "/@@"}, {0xb9, "/qt"}, - {0xba, "/bad"}, {0xba, "/cj"}, - {0xbb, "/loveu"}, {0xbb, "/aini"}, - {0xbc, "/no"}, {0xbc, "/bu"}, - {0xbd, "/ok"}, {0xbd, "/hd"}, - {0x5c, "/love"}, {0x5c, "/aiq"}, /* after loveu */ - {0x56, "/"}, {0x56, "/fw"}, {0x56, "/blow_kiss"}, - {0x58, "/jump"}, {0x58, "/tiao"}, - {0x5a, "/shake"}, {0x5a, "/fad"}, /* after fade */ - {0x5b, "/"}, {0x5b, "/oh"}, {0x5b, "/angry"}, - {0xbe, "/circle"}, {0xbe, "/zhq"}, - {0xbf, "/kotow"}, {0xbf, "/kt"}, - {0xc0, "/turn"}, {0xc0, "/ht"}, - {0x77, "/:t"}, {0x77, "/tu"}, {0x77, "/vomit"}, /* after turn */ - {0xa0, "/victory"}, {0xa0, "/shl"}, {0xa0, "/v"}, /* end of v */ - {0xc1, "/skip"}, {0xc1, "/tsh"}, - {0xc2, "/oY"}, {0xc2, "/hsh"}, - {0xc3, "/#-O"}, {0xc3, "/jd"}, - {0xc4, "/hiphop"}, {0xc4, "/jw"}, - {0xc5, "/kiss"}, {0xc5, "/xw"}, - {0xc6, "/<&"}, {0xc6, "/ztj"}, - {0x7c, "/pig"}, {0x7c, "/zt"}, /* after ztj */ - {0xc7, "/&>"}, {0xc7, "/ytj"}, /* must be end of "&" */ - {0x75, "/:#"}, {0x75, "/feid"}, {0x75, "/SARS"}, - {0x59, "/go"}, {0x59, "/shan"}, - {0x57, "/find"}, {0x57, "/zhao"}, {0x57, "/search"}, - {0x55, "/&"}, {0x55, "/mm"}, {0x55, "/beautiful_eyebrows"}, - {0x7d, "/cat"}, {0x7d, "/maom"}, - {0x7e, "/dog"}, {0x7e, "/xg"}, - {0x9a, "/$"}, {0x9a, "/qianc"}, {0x9a, "/money"}, - {0x9b, "/(!)"}, {0x9b, "/dp"}, {0x9b, "/lightbulb"}, - {0x60, "/cup"}, {0x60, "/bei"}, - {0x9f, "/music"}, {0x9f, "/yy"}, - {0x82, "/pill"}, {0x82, "/yw"}, - {0x64, "/kiss"}, {0x64, "/wen"}, - {0x83, "/meeting"}, {0x83, "/hy"}, - {0x84, "/phone"}, {0x84, "/dh"}, - {0x85, "/time"}, {0x85, "/sj"}, - {0x86, "/email"}, {0x86, "/yj"}, - {0x87, "/tv"}, {0x87, "/ds"}, - {0x50, "/"}, {0x50, "/dd"}, - {0x51, "/"}, {0x51, "/mn"}, {0x51, "/beauty"}, - {0x52, "/"}, {0x52, "/hl"}, - {0x53, "/"}, {0x53, "/mamao"}, - {0x54, "/"}, {0x54, "/qz"}, {0x54, "/qq"}, - {0x5d, "/"}, {0x5d, "/bj"}, {0x5d, "/baijiu"}, - {0x5f, "/"}, {0x5f, "/qsh"}, {0x5f, "/soda"}, - {0x69, "/"}, {0x69, "/xy"}, {0x69, "/rain"}, - {0x6a, "/<~>"}, {0x6a, "/duoy"}, {0x6a, "/cloudy"}, - {0x6c, "/"}, {0x6c, "/xr"}, {0x6c, "/snowman"}, - {0x6d, "/<*>"}, {0x6d, "/xixing"}, {0x6d, "/star"}, /* after starving */ - {0x71, "/<00>"}, {0x71, "/nv"}, {0x71, "/woman"}, - {0x72, "/<11>"}, {0x72, "/nan"}, {0x72, "/man"}, - {0, NULL} -}; -gint emoticons_std_num = sizeof(emoticons_std) / sizeof(qq_emoticon) - 1; - -/* Map for purple smiley convert to qq, need qsort */ -static qq_emoticon emoticons_ext[] = { - {0xc7, "/&>"}, {0xa5, "/&-("}, - {0xbb, "/loveu"}, - {0x63, "/fade"}, - {0x8f, "/sleepy"}, {0x73, "/sad"}, {0x8e, "/starving"}, - {0xc0, "/turn"}, - {0xa0, "/victory"}, {0x77, "/vomit"}, - {0xc6, "/ztj"}, - {0, NULL} -}; -gint emoticons_ext_num = sizeof(emoticons_ext) / sizeof(qq_emoticon) - 1; - -/* Map for qq smiley convert to purple */ -static qq_emoticon emoticons_sym[] = { - {0x41, "/jy"}, - {0x42, "/pz"}, - {0x43, "/se"}, - {0x44, "/fd"}, - {0x45, "/dy"}, - {0x46, "/ll"}, - {0x47, "/hx"}, - {0x48, "/bz"}, - {0x49, "/shui"}, - {0x4a, "/dk"}, - {0x4b, "/gg"}, - {0x4c, "/fn"}, - {0x4d, "/tp"}, - {0x4e, "/cy"}, - {0x4f, "/wx"}, - {0x50, "/dd"}, - {0x51, "/mn"}, - {0x52, "/hl"}, - {0x53, "/mamao"}, - {0x54, "/qz"}, - {0x55, "/mm"}, - {0x56, "/fw"}, - {0x57, "/zhao"}, - {0x58, "/tiao"}, - {0x59, "/shan"}, - {0x5a, "/fad"}, - {0x5b, "/oh"}, - {0x5c, "/aiq"}, - {0x5d, "/bj"}, - {0x5e, "/zq"}, - {0x5f, "/qsh"}, - {0x60, "/bei"}, - {0x61, "/xig"}, - {0x62, "/mg"}, - {0x63, "/dx"}, - {0x64, "/wen"}, - {0x65, "/xin"}, - {0x66, "/xs"}, - {0x67, "/dg"}, - {0x68, "/lw"}, - {0x69, "/xy"}, - {0x6a, "/duoy"}, - {0x6b, "/ty"}, - {0x6c, "/xr"}, - {0x6d, "/xixing"}, - {0x6e, "/yl"}, - {0x6f, "/qiang"}, - {0x70, "/ruo"}, - {0x71, "/nv"}, - {0x72, "/nan"}, - {0x73, "/ng"}, - {0x74, "/kuk"}, - {0x75, "/feid"}, - {0x76, "/zk"}, - {0x77, "/tu"}, - {0x78, "/jk"}, - {0x79, "/sweat"}, - {0x7a, "/hanx"}, - {0x7b, "/db"}, - {0x7c, "/zt"}, - {0x7d, "/maom"}, - {0x7e, "/xg"}, - {0x7f, "/yb"}, - {0x80, "/coffee"}, - {0x81, "/fan"}, - {0x82, "/yw"}, - {0x83, "/hy"}, - {0x84, "/dh"}, - {0x85, "/sj"}, - {0x86, "/yj"}, - {0x87, "/ds"}, - {0x88, "/ws"}, - {0x89, "/bb"}, - {0x8a, "/tx"}, - {0x8b, "/ka"}, - {0x8c, "/by"}, - {0x8d, "/am"}, - {0x8e, "/jie"}, - {0x8f, "/kun"}, - {0x90, "/fendou"}, - {0x91, "/zhm"}, - {0x92, "/yiw"}, - {0x93, "/xu"}, - {0x94, "/yun"}, - {0x95, "/zhem"}, - {0x96, "/shuai"}, - {0x97, "/kl"}, - {0x98, "/qiao"}, - {0x99, "/zj"}, - {0x9a, "/qianc"}, - {0x9b, "/dp"}, - {0x9c, "/shd"}, - {0x9d, "/zhd"}, - {0x9e, "/dao"}, - {0x9f, "/yy"}, - {0xa0, "/shl"}, - {0xa1, "/lengh"}, - {0xa2, "/wipe"}, - {0xa3, "/kb"}, - {0xa4, "/gz"}, - {0xa5, "/qd"}, - {0xa6, "/huaix"}, - {0xa7, "/zhh"}, - {0xa8, "/yhh"}, - {0xa9, "/hq"}, - {0xaa, "/bs"}, - {0xab, "/wq"}, - {0xac, "/kk"}, - {0xad, "/yx"}, - {0xae, "/qq"}, - {0xaf, "/xia"}, - {0xb0, "/kel"}, - {0xb1, "/cd"}, - {0xb2, "/pj"}, - {0xb3, "/lq"}, - {0xb4, "/pp"}, - {0xb5, "/sa"}, - {0xb6, "/pc"}, - {0xb7, "/bq"}, - {0xb8, "/gy"}, - {0xb9, "/qt"}, - {0xba, "/cj"}, - {0xbb, "/aini"}, - {0xbc, "/bu"}, - {0xbd, "/hd"}, - {0xbe, "/zhq"}, - {0xbf, "/kt"}, - {0xc0, "/ht"}, - {0xc1, "/tsh"}, - {0xc2, "/hsh"}, - {0xc3, "/jd"}, - {0xc4, "/jw"}, - {0xc5, "/xw"}, - {0xc6, "/ztj"}, - {0xc7, "/ytj"}, - {0, NULL} -}; -gint emoticons_sym_num = sizeof(emoticons_sym) / sizeof(qq_emoticon) - 1;; - -static int emoticon_cmp(const void *k1, const void *k2) -{ - const qq_emoticon *e1 = (const qq_emoticon *) k1; - const qq_emoticon *e2 = (const qq_emoticon *) k2; - if (e1->symbol == 0) { - /* purple_debug_info("QQ", "emoticon_cmp len %d\n", strlen(e2->name)); */ - return strncmp(e1->name, e2->name, strlen(e2->name)); - } - if (e2->symbol == 0) { - /* purple_debug_info("QQ", "emoticon_cmp len %d\n", strlen(e1->name)); */ - return strncmp(e1->name, e2->name, strlen(e1->name)); - } - return strcmp(e1->name, e2->name); -} - -static void emoticon_try_sort() -{ - if (emoticons_is_sorted) - return; - - purple_debug_info("QQ", "qsort stand emoticons\n"); - qsort(emoticons_std, emoticons_std_num, sizeof(qq_emoticon), emoticon_cmp); - purple_debug_info("QQ", "qsort extend emoticons\n"); - qsort(emoticons_ext, emoticons_ext_num, sizeof(qq_emoticon), emoticon_cmp); - emoticons_is_sorted = TRUE; -} - -static qq_emoticon *emoticon_find(gchar *name) -{ - qq_emoticon *ret = NULL; - qq_emoticon key; - - g_return_val_if_fail(name != NULL, NULL); - emoticon_try_sort(); - - key.name = name; - key.symbol = 0; - - /* purple_debug_info("QQ", "bsearch emoticon %.20s\n", name); */ - ret = (qq_emoticon *)bsearch(&key, emoticons_ext, emoticons_ext_num, - sizeof(qq_emoticon), emoticon_cmp); - if (ret != NULL) { - return ret; - } - ret = (qq_emoticon *)bsearch(&key, emoticons_std, emoticons_std_num, - sizeof(qq_emoticon), emoticon_cmp); - return ret; -} - -static gchar *emoticon_get(guint8 symbol) -{ - g_return_val_if_fail(symbol >= emoticons_sym[0].symbol, NULL); - g_return_val_if_fail(symbol <= emoticons_sym[emoticons_sym_num - 2].symbol, NULL); - - return emoticons_sym[symbol - emoticons_sym[0].symbol].name; -} - -/* convert qq emote icon to purple sytle - Notice: text is in qq charset, GB18030 or utf8 */ -gchar *qq_emoticon_to_purple(gchar *text) -{ - gchar *ret; - GString *converted; - gchar **segments; - gboolean have_smiley; - gchar *purple_smiley; - gchar *cur; - guint8 symbol; - - /* qq_show_packet("text", (guint8 *)text, strlen(text)); */ - g_return_val_if_fail(text != NULL && strlen(text) != 0, g_strdup("")); - - while ((cur = strchr(text, '\x14')) != NULL) - *cur = '\x15'; - - segments = g_strsplit(text, "\x15", 0); - if(segments == NULL) { - return g_strdup(""); - } - - converted = g_string_new(""); - have_smiley = FALSE; - if (segments[0] != NULL) { - g_string_append(converted, segments[0]); - } else { - purple_debug_info("QQ", "segments[0] is NULL\n"); - } - while ((*(++segments)) != NULL) { - have_smiley = TRUE; - - cur = *segments; - if (cur == NULL) { - purple_debug_info("QQ", "current segment is NULL\n"); - break; - } - if (strlen(cur) == 0) { - purple_debug_info("QQ", "current segment length is 0\n"); - break; - } - symbol = (guint8)cur[0]; - - purple_smiley = emoticon_get(symbol); - if (purple_smiley == NULL) { - purple_debug_info("QQ", "Not found smiley of 0x%02X\n", symbol); - g_string_append(converted, ""); - } else { - purple_debug_info("QQ", "Found 0x%02X smiley is %s\n", symbol, purple_smiley); - g_string_append(converted, purple_smiley); - g_string_append(converted, cur + 1); - } - /* purple_debug_info("QQ", "next segment\n"); */ - } - - /* purple_debug_info("QQ", "end of convert\n"); */ - if (!have_smiley) { - g_string_prepend(converted, ""); - g_string_append(converted, ""); - } - ret = converted->str; - g_string_free(converted, FALSE); - return ret; -} - -void qq_im_fmt_free(qq_im_format *fmt) -{ - g_return_if_fail(fmt != NULL); - if (fmt->font) g_free(fmt->font); - g_free(fmt); -} - -qq_im_format *qq_im_fmt_new(void) -{ - qq_im_format *fmt; - /* '0xcb, 0xce, 0xcc, 0xe5' means Chinese '宋体' in utf8 */ - const gchar simsun[] = { 0xcb, 0xce, 0xcc, 0xe5, 0}; - - fmt = g_new0(qq_im_format, 1); - memset(fmt, 0, sizeof(qq_im_format)); - fmt->font_len = strlen(simsun); - fmt->font = g_strdup(simsun); - fmt->attr = 10; - /* encoding, 0x8602=GB, 0x0000=EN, define BIG5 support here */ - fmt->charset = 0x8602; - - return fmt; -} - -void qq_im_fmt_reset_font(qq_im_format *fmt) -{ - const gchar simsun[] = {0xcb, 0xce, 0xcc, 0xe5, 0x00}; - g_return_if_fail(NULL != fmt); - - if (NULL != fmt->font) { - g_free(fmt->font); - fmt->font = g_strdup(simsun); - } -} - -qq_im_format *qq_im_fmt_new_by_purple(const gchar *msg) -{ - qq_im_format *fmt; - const gchar *start, *end, *last; - GData *attribs; - gchar *tmp; - - g_return_val_if_fail(msg != NULL, NULL); - - fmt = qq_im_fmt_new(); - - last = msg; - while (purple_markup_find_tag("font", last, &start, &end, &attribs)) { - tmp = g_datalist_get_data(&attribs, "face"); - if (tmp && strlen(tmp) > 0) { - if (fmt->font) g_free(fmt->font); - fmt->font_len = strlen(tmp); - fmt->font = g_strdup(tmp); - } - - tmp = g_datalist_get_data(&attribs, "size"); - if (tmp) { - fmt->attr = atoi(tmp) * 3 + 1; - fmt->attr &= 0x0f; - } - - tmp = g_datalist_get_data(&attribs, "color"); - if (tmp && strlen(tmp) > 1) { - unsigned char *rgb; - gsize rgb_len; - rgb = purple_base16_decode(tmp + 1, &rgb_len); - if (rgb != NULL && rgb_len >= 3) - g_memmove(fmt->rgb, rgb, 3); - g_free(rgb); - } - - g_datalist_clear(&attribs); - last = end + 1; - } - - if (purple_markup_find_tag("b", msg, &start, &end, &attribs)) { - fmt->attr |= 0x20; - g_datalist_clear(&attribs); - } - - if (purple_markup_find_tag("i", msg, &start, &end, &attribs)) { - fmt->attr |= 0x40; - g_datalist_clear(&attribs); - } - - if (purple_markup_find_tag("u", msg, &start, &end, &attribs)) { - fmt->attr |= 0x80; - g_datalist_clear(&attribs); - } - - return fmt; -} - -/* convert qq format to purple - Notice: text is in qq charset, GB18030 or utf8 */ -gchar *qq_im_fmt_to_purple(qq_im_format *fmt, gchar *text) -{ - GString *converted, *tmp; - gchar *ret; - gint size; - - converted = g_string_new(text); - tmp = g_string_new(""); - g_string_append_printf(tmp, "", - fmt->rgb[0], fmt->rgb[1], fmt->rgb[2]); - g_string_prepend(converted, tmp->str); - g_string_set_size(tmp, 0); - g_string_append(converted, ""); - - /* Fixme: - * check font face can be convert to utf8 or not? - * If failed, prepending font face cause msg display as "(NULL)" */ - if (fmt->font != NULL) { - g_string_append_printf(tmp, "", fmt->font); - g_string_prepend(converted, tmp->str); - g_string_set_size(tmp, 0); - g_string_append(converted, ""); - } - size = (fmt->attr & 0x1f) / 3; - if (size >= 0) { - g_string_append_printf(tmp, "", size); - g_string_prepend(converted, tmp->str); - g_string_set_size(tmp, 0); - g_string_append(converted, ""); - } - if (fmt->attr & 0x20) { - /* bold */ - g_string_prepend(converted, ""); - g_string_append(converted, ""); - } - if (fmt->attr & 0x40) { - /* italic */ - g_string_prepend(converted, ""); - g_string_append(converted, ""); - } - if (fmt->attr & 0x80) { - /* underline */ - g_string_prepend(converted, ""); - g_string_append(converted, ""); - } - - g_string_free(tmp, TRUE); - ret = converted->str; - g_string_free(converted, FALSE); - return ret; -} - -gint qq_put_im_tail(guint8 *buf, qq_im_format *fmt) -{ - gint bytes; - - g_return_val_if_fail(buf != NULL && fmt != NULL, 0); - - bytes = 0; - bytes += qq_put8(buf + bytes, 0); - bytes += qq_put8(buf + bytes, fmt->attr); - bytes += qq_putdata(buf + bytes, fmt->rgb, sizeof(fmt->rgb)); - bytes += qq_put8(buf + bytes, 0); - bytes += qq_put16(buf + bytes, fmt->charset); - if (fmt->font != NULL && fmt->font_len > 0) { - bytes += qq_putdata(buf + bytes, (guint8 *)fmt->font, fmt->font_len); - } else { - purple_debug_warning("QQ", "Font name is empty\n"); - } - bytes += qq_put8(buf + bytes, bytes + 1); - /* qq_show_packet("IM tail", buf, bytes); */ - return bytes; -} - -/* data includes text msg and font attr*/ -gint qq_get_im_tail(qq_im_format *fmt, guint8 *data, gint data_len) -{ - gint bytes, text_len; - guint8 tail_len; - guint8 font_len; - - g_return_val_if_fail(fmt != NULL && data != NULL, 0); - g_return_val_if_fail(data_len > 1, 0); - tail_len = data[data_len - 1]; - g_return_val_if_fail(tail_len > 2, 0); - text_len = data_len - tail_len; - g_return_val_if_fail(text_len >= 0, 0); - - bytes = text_len; - /* qq_show_packet("IM tail", data + bytes, tail_len); */ - bytes += 1; /* skip 0x00 */ - bytes += qq_get8(&fmt->attr, data + bytes); - bytes += qq_getdata(fmt->rgb, sizeof(fmt->rgb), data + bytes); /* red,green,blue */ - bytes += 1; /* skip 0x00 */ - bytes += qq_get16(&fmt->charset, data + bytes); - - font_len = data_len - bytes - 1; - g_return_val_if_fail(font_len > 0, bytes + 1); - - fmt->font_len = font_len; - if (fmt->font != NULL) g_free(fmt->font); - fmt->font = g_strndup((gchar *)data + bytes, fmt->font_len); - return tail_len; -} - -void qq_got_message(PurpleConnection *gc, const gchar *msg) -{ - qq_data *qd; - gchar *from; - time_t now = time(NULL); - - g_return_if_fail(gc != NULL && gc->proto_data != NULL); - qd = gc->proto_data; - - g_return_if_fail(qd->uid > 0); - - qq_buddy_find_or_new(gc, qd->uid); - - from = uid_to_purple_name(qd->uid); - serv_got_im(gc, from, msg, PURPLE_MESSAGE_SYSTEM, now); - g_free(from); -} - -/* process received normal text IM */ -static void process_im_text(PurpleConnection *gc, guint8 *data, gint len, qq_im_header *im_header) -{ - guint16 purple_msg_type; - gchar *who; - gchar *msg_smiley, *msg_fmt, *msg_utf8; - PurpleBuddy *buddy; - qq_buddy_data *bd; - gint bytes, tail_len; - qq_im_format *fmt = NULL; - - struct { - /* now comes the part for text only */ - guint16 msg_seq; - guint32 send_time; - guint16 sender_icon; - guint8 unknown1[3]; - guint8 has_font_attr; - guint8 fragment_count; - guint8 fragment_index; - guint8 msg_id; - guint8 unknown2; - guint8 msg_type; - gchar *msg; /* no fixed length, ends with 0x00 */ - } im_text; - - g_return_if_fail(data != NULL && len > 0); - g_return_if_fail(im_header != NULL); - - memset(&im_text, 0, sizeof(im_text)); - - /* qq_show_packet("IM text", data, len); */ - bytes = 0; - bytes += qq_get16(&(im_text.msg_seq), data + bytes); - bytes += qq_get32(&(im_text.send_time), data + bytes); - bytes += qq_get16(&(im_text.sender_icon), data + bytes); - bytes += qq_getdata(im_text.unknown1, sizeof(im_text.unknown1), data + bytes); /* 0x(00 00 00)*/ - bytes += qq_get8(&(im_text.has_font_attr), data + bytes); - bytes += qq_get8(&(im_text.fragment_count), data + bytes); - bytes += qq_get8(&(im_text.fragment_index), data + bytes); - bytes += qq_get8(&(im_text.msg_id), data + bytes); - bytes += 1; /* skip 0x00 */ - bytes += qq_get8(&(im_text.msg_type), data + bytes); - purple_debug_info("QQ", "IM Seq %u, id %04X, fragment %d-%d, type %d, %s\n", - im_text.msg_seq, im_text.msg_id, - im_text.fragment_count, im_text.fragment_index, - im_text.msg_type, - im_text.has_font_attr ? "exist font atrr" : ""); - - if (im_text.has_font_attr) { - fmt = qq_im_fmt_new(); - tail_len = qq_get_im_tail(fmt, data + bytes, len - bytes); - im_text.msg = g_strndup((gchar *)(data + bytes), len - tail_len); - } else { - im_text.msg = g_strndup((gchar *)(data + bytes), len - bytes); - } - /* qq_show_packet("IM text", (guint8 *)im_text.msg , strlen(im_text.msg) ); */ - - who = uid_to_purple_name(im_header->uid_from); - buddy = purple_find_buddy(gc->account, who); - if (buddy == NULL) { - /* create no-auth buddy */ - buddy = qq_buddy_new(gc, im_header->uid_from); - } - bd = (buddy == NULL) ? NULL : purple_buddy_get_protocol_data(buddy); - if (bd != NULL) { - bd->client_tag = im_header->version_from; - bd->face = im_text.sender_icon; - qq_update_buddy_icon(gc->account, who, bd->face); - } - - purple_msg_type = (im_text.msg_type == QQ_IM_AUTO_REPLY) - ? PURPLE_MESSAGE_AUTO_RESP : 0; - - msg_smiley = qq_emoticon_to_purple(im_text.msg); - if (fmt != NULL) { - msg_fmt = qq_im_fmt_to_purple(fmt, msg_smiley); - msg_utf8 = qq_to_utf8(msg_fmt, QQ_CHARSET_DEFAULT); - g_free(msg_fmt); - qq_im_fmt_free(fmt); - } else { - msg_utf8 = qq_to_utf8(msg_smiley, QQ_CHARSET_DEFAULT); - } - g_free(msg_smiley); - - /* send encoded to purple, note that we use im_text.send_time, - * not the time we receive the message - * as it may have been delayed when I am not online. */ - purple_debug_info("QQ", "IM from %u: %s\n", im_header->uid_from,msg_utf8); - serv_got_im(gc, who, msg_utf8, purple_msg_type, (time_t) im_text.send_time); - - g_free(msg_utf8); - g_free(who); - g_free(im_text.msg); -} - -/* process received extended (2007) text IM */ -static void process_extend_im_text(PurpleConnection *gc, guint8 *data, gint len, qq_im_header *im_header) -{ - guint16 purple_msg_type; - gchar *who; - gchar *msg_smiley, *msg_fmt, *msg_utf8; - PurpleBuddy *buddy; - qq_buddy_data *bd; - gint bytes, tail_len; - qq_im_format *fmt = NULL; - - struct { - /* now comes the part for text only */ - guint16 msg_seq; - guint32 send_time; - guint16 sender_icon; - guint32 has_font_attr; - guint8 unknown1[8]; - guint8 fragment_count; - guint8 fragment_index; - guint8 msg_id; - guint8 unknown2; - guint8 msg_type; - gchar *msg; /* no fixed length, ends with 0x00 */ - guint8 fromMobileQQ; - } im_text; - - g_return_if_fail(data != NULL && len > 0); - g_return_if_fail(im_header != NULL); - - memset(&im_text, 0, sizeof(im_text)); - - /* qq_show_packet("Extend IM text", data, len); */ - bytes = 0; - bytes += qq_get16(&(im_text.msg_seq), data + bytes); - bytes += qq_get32(&(im_text.send_time), data + bytes); - bytes += qq_get16(&(im_text.sender_icon), data + bytes); - bytes += qq_get32(&(im_text.has_font_attr), data + bytes); - bytes += qq_getdata(im_text.unknown1, sizeof(im_text.unknown1), data + bytes); - bytes += qq_get8(&(im_text.fragment_count), data + bytes); - bytes += qq_get8(&(im_text.fragment_index), data + bytes); - bytes += qq_get8(&(im_text.msg_id), data + bytes); - bytes += 1; /* skip 0x00 */ - bytes += qq_get8(&(im_text.msg_type), data + bytes); - purple_debug_info("QQ", "IM Seq %u, id %04X, fragment %d-%d, type %d, %s\n", - im_text.msg_seq, im_text.msg_id, - im_text.fragment_count, im_text.fragment_index, - im_text.msg_type, - im_text.has_font_attr ? "exist font atrr" : ""); - - if (im_text.has_font_attr) { - fmt = qq_im_fmt_new(); - tail_len = qq_get_im_tail(fmt, data + bytes, len - bytes); - im_text.msg = g_strndup((gchar *)(data + bytes), len - tail_len); - } else { - im_text.msg = g_strndup((gchar *)(data + bytes), len - bytes); - } - /* qq_show_packet("IM text", (guint8 *)im_text.msg , strlen(im_text.msg)); */ - - if(im_text.fragment_count == 0) im_text.fragment_count = 1; - - who = uid_to_purple_name(im_header->uid_from); - buddy = purple_find_buddy(gc->account, who); - if (buddy == NULL) { - /* create no-auth buddy */ - buddy = qq_buddy_new(gc, im_header->uid_from); - } - bd = (buddy == NULL) ? NULL : purple_buddy_get_protocol_data(buddy); - if (bd != NULL) { - bd->client_tag = im_header->version_from; - bd->face = im_text.sender_icon; - qq_update_buddy_icon(gc->account, who, bd->face); - } - - purple_msg_type = 0; - - msg_smiley = qq_emoticon_to_purple(im_text.msg); - if (fmt != NULL) { - msg_fmt = qq_im_fmt_to_purple(fmt, msg_smiley); - msg_utf8 = qq_to_utf8(msg_fmt, QQ_CHARSET_DEFAULT); - g_free(msg_fmt); - qq_im_fmt_free(fmt); - } else { - msg_utf8 = qq_to_utf8(msg_smiley, QQ_CHARSET_DEFAULT); - } - g_free(msg_smiley); - - /* send encoded to purple, note that we use im_text.send_time, - * not the time we receive the message - * as it may have been delayed when I am not online. */ - serv_got_im(gc, who, msg_utf8, purple_msg_type, (time_t) im_text.send_time); - - g_free(msg_utf8); - g_free(who); - g_free(im_text.msg); -} - -/* it is a normal IM, maybe text or video request */ -void qq_process_im(PurpleConnection *gc, guint8 *data, gint len) -{ - gint bytes = 0; - qq_im_header im_header; - - g_return_if_fail (data != NULL && len > 0); - - bytes = get_im_header(&im_header, data, len); - if (bytes < 0) { - purple_debug_error("QQ", "Fail read im header, len %d\n", len); - qq_show_packet ("IM Header", data, len); - return; - } - purple_debug_info("QQ", - "Got IM to %u, type: %02X from: %u ver: %s (%04X)\n", - im_header.uid_to, im_header.im_type, im_header.uid_from, - qq_get_ver_desc(im_header.version_from), im_header.version_from); - - switch (im_header.im_type) { - case QQ_NORMAL_IM_TEXT: - if (bytes >= len - 1) { - purple_debug_warning("QQ", "Received normal IM text is empty\n"); - return; - } - process_im_text(gc, data + bytes, len - bytes, &im_header); - break; - case QQ_NORMAL_IM_FILE_REJECT_UDP: - qq_process_recv_file_reject(data + bytes, len - bytes, im_header.uid_from, gc); - break; - case QQ_NORMAL_IM_FILE_APPROVE_UDP: - qq_process_recv_file_accept(data + bytes, len - bytes, im_header.uid_from, gc); - break; - case QQ_NORMAL_IM_FILE_REQUEST_UDP: - qq_process_recv_file_request(data + bytes, len - bytes, im_header.uid_from, gc); - break; - case QQ_NORMAL_IM_FILE_CANCEL: - qq_process_recv_file_cancel(data + bytes, len - bytes, im_header.uid_from, gc); - break; - case QQ_NORMAL_IM_FILE_NOTIFY: - qq_process_recv_file_notify(data + bytes, len - bytes, im_header.uid_from, gc); - break; - case QQ_NORMAL_IM_FILE_REQUEST_TCP: - /* Check ReceivedFileIM::parseContents in eva*/ - /* some client use this function for detect invisable buddy*/ - case QQ_NORMAL_IM_FILE_APPROVE_TCP: - case QQ_NORMAL_IM_FILE_REJECT_TCP: - case QQ_NORMAL_IM_FILE_PASV: - case QQ_NORMAL_IM_FILE_EX_REQUEST_UDP: - case QQ_NORMAL_IM_FILE_EX_REQUEST_ACCEPT: - case QQ_NORMAL_IM_FILE_EX_REQUEST_CANCEL: - case QQ_NORMAL_IM_FILE_EX_NOTIFY_IP: - qq_show_packet ("Not support", data, len); - break; - default: - /* a simple process here, maybe more later */ - qq_show_packet ("Unknow", data + bytes, len - bytes); - return; - } -} - -/* it is a extended IM, maybe text or video request */ -void qq_process_extend_im(PurpleConnection *gc, guint8 *data, gint len) -{ - gint bytes; - qq_im_header im_header; - - g_return_if_fail (data != NULL && len > 0); - - bytes = get_im_header(&im_header, data, len); - if (bytes < 0) { - purple_debug_error("QQ", "Fail read im header, len %d\n", len); - qq_show_packet ("IM Header", data, len); - return; - } - purple_debug_info("QQ", - "Got Extend IM to %u, type: %02X from: %u ver: %s (%04X)\n", - im_header.uid_to, im_header.im_type, im_header.uid_from, - qq_get_ver_desc(im_header.version_from), im_header.version_from); - - switch (im_header.im_type) { - case QQ_NORMAL_IM_TEXT: - process_extend_im_text(gc, data + bytes, len - bytes, &im_header); - break; - case QQ_NORMAL_IM_FILE_REJECT_UDP: - qq_process_recv_file_reject (data + bytes, len - bytes, im_header.uid_from, gc); - break; - case QQ_NORMAL_IM_FILE_APPROVE_UDP: - qq_process_recv_file_accept (data + bytes, len - bytes, im_header.uid_from, gc); - break; - case QQ_NORMAL_IM_FILE_REQUEST_UDP: - qq_process_recv_file_request (data + bytes, len - bytes, im_header.uid_from, gc); - break; - case QQ_NORMAL_IM_FILE_CANCEL: - qq_process_recv_file_cancel (data + bytes, len - bytes, im_header.uid_from, gc); - break; - case QQ_NORMAL_IM_FILE_NOTIFY: - qq_process_recv_file_notify (data + bytes, len - bytes, im_header.uid_from, gc); - break; - case QQ_NORMAL_IM_FILE_REQUEST_TCP: - /* Check ReceivedFileIM::parseContents in eva*/ - /* some client use this function for detect invisable buddy*/ - case QQ_NORMAL_IM_FILE_APPROVE_TCP: - case QQ_NORMAL_IM_FILE_REJECT_TCP: - case QQ_NORMAL_IM_FILE_PASV: - case QQ_NORMAL_IM_FILE_EX_REQUEST_UDP: - case QQ_NORMAL_IM_FILE_EX_REQUEST_ACCEPT: - case QQ_NORMAL_IM_FILE_EX_REQUEST_CANCEL: - case QQ_NORMAL_IM_FILE_EX_NOTIFY_IP: - qq_show_packet ("Not support", data, len); - break; - default: - /* a simple process here, maybe more later */ - qq_show_packet ("Unknow", data + bytes, len - bytes); - break; - } -} - -/* send an IM to uid_to */ -static void request_send_im(PurpleConnection *gc, UID uid_to, gint type, - qq_im_format *fmt, gchar *msg, guint8 id, guint8 frag_count, guint8 frag_index) -{ - qq_data *qd; - guint8 raw_data[MAX_PACKET_SIZE - 16]; - gint bytes; - time_t now; - - qd = (qq_data *) gc->proto_data; - - /* purple_debug_info("QQ", "Send IM %d-%d\n", frag_count, frag_index); */ - bytes = 0; - /* 000-003: receiver uid */ - bytes += qq_put32(raw_data + bytes, qd->uid); - /* 004-007: sender uid */ - bytes += qq_put32(raw_data + bytes, uid_to); - /* 008-009: sender client version */ - bytes += qq_put16(raw_data + bytes, qd->client_tag); - /* 010-013: receiver uid */ - bytes += qq_put32(raw_data + bytes, qd->uid); - /* 014-017: sender uid */ - bytes += qq_put32(raw_data + bytes, uid_to); - /* 018-033: md5 of (uid+session_key) */ - bytes += qq_putdata(raw_data + bytes, qd->session_md5, 16); - /* 034-035: message type */ - bytes += qq_put16(raw_data + bytes, QQ_NORMAL_IM_TEXT); - /* 036-037: sequence number */ - bytes += qq_put16(raw_data + bytes, qd->send_seq); - /* 038-041: send time */ - now = time(NULL); - bytes += qq_put32(raw_data + bytes, (guint32) now); - /* 042-043: sender icon */ - bytes += qq_put16(raw_data + bytes, qd->my_icon); - /* 044-046: always 0x00 */ - bytes += qq_put16(raw_data + bytes, 0x0000); - bytes += qq_put8(raw_data + bytes, 0x00); - /* 047-047: always use font attr */ - bytes += qq_put8(raw_data + bytes, 0x01); - /* 048-051: always 0x00 */ - /* Fixme: frag_count, frag_index not working now */ - bytes += qq_put8(raw_data + bytes, frag_count); - bytes += qq_put8(raw_data + bytes, frag_index); - bytes += qq_put8(raw_data + bytes, id); - bytes += qq_put8(raw_data + bytes, 0); - /* 052-052: text message type (normal/auto-reply) */ - bytes += qq_put8(raw_data + bytes, type); - /* 053- : msg ends with 0x00 */ - bytes += qq_putdata(raw_data + bytes, (guint8 *)msg, strlen(msg)); - if (frag_count == frag_index + 1) { - bytes += qq_put8(raw_data + bytes, 0x20); /* add extra SPACE */ - } - bytes += qq_put_im_tail(raw_data + bytes, fmt); - - /* qq_show_packet("QQ_CMD_SEND_IM", raw_data, bytes); */ - qq_send_cmd(gc, QQ_CMD_SEND_IM, raw_data, bytes); -} - -static void im_convert_and_merge(GString *dest, GString *append) -{ - gchar *converted; - g_return_if_fail(dest != NULL && append != NULL); - - if (append->str == NULL || append->len <= 0) { - return; - } - /* purple_debug_info("QQ", "Append:\n%s\n", append->str); */ - converted = utf8_to_qq(append->str, QQ_CHARSET_DEFAULT); - g_string_append(dest, converted); - g_string_set_size(append, 0); - g_free(converted); -} - -GSList *qq_im_get_segments(gchar *msg_stripped, gboolean is_smiley_none) -{ - GSList *string_list = NULL; - GString *new_string; - GString *append_utf8; - gchar *start, *p; - gint len; - qq_emoticon *emoticon; - - g_return_val_if_fail(msg_stripped != NULL, NULL); - - start = msg_stripped; - new_string = g_string_new(""); - append_utf8 = g_string_new(""); - while (*start) { - p = start; - - /* Convert emoticon */ - if (!is_smiley_none && *p == '/') { - if (new_string->len + append_utf8->len + 2 > QQ_MSG_IM_MAX) { - /* enough chars to send */ - im_convert_and_merge(new_string, append_utf8); - string_list = g_slist_append(string_list, strdup(new_string->str)); - g_string_set_size(new_string, 0); - continue; - } - emoticon = emoticon_find(p); - if (emoticon != NULL) { - purple_debug_info("QQ", "found emoticon %s as 0x%02X\n", - emoticon->name, emoticon->symbol); - /* QQ emoticon code prevent converting from utf8 to QQ charset - * convert append_utf8 to QQ charset - * merge the result to dest - * append qq QQ emoticon code to dest */ - im_convert_and_merge(new_string, append_utf8); - g_string_append_c(new_string, 0x14); - g_string_append_c(new_string, emoticon->symbol); - start += strlen(emoticon->name); - continue; - } else { - purple_debug_info("QQ", "Not found emoticon %.20s\n", p); - } - } - - /* Get next char */ - start = g_utf8_next_char(p); - len = start - p; - if (new_string->len + append_utf8->len + len > QQ_MSG_IM_MAX) { - /* enough chars to send */ - im_convert_and_merge(new_string, append_utf8); - string_list = g_slist_append(string_list, strdup(new_string->str)); - g_string_set_size(new_string, 0); - } - g_string_append_len(append_utf8, p, len); - } - - if (new_string->len + append_utf8->len > 0) { - im_convert_and_merge(new_string, append_utf8); - string_list = g_slist_append(string_list, strdup(new_string->str)); - } - g_string_free(new_string, TRUE); - g_string_free(append_utf8, TRUE); - return string_list; -} - -gboolean qq_im_smiley_none(const gchar *msg) -{ - const gchar *start, *end, *last; - GData *attribs; - gchar *tmp; - gboolean ret = FALSE; - - g_return_val_if_fail(msg != NULL, TRUE); - - last = msg; - while (purple_markup_find_tag("font", last, &start, &end, &attribs)) { - tmp = g_datalist_get_data(&attribs, "sml"); - if (tmp && strlen(tmp) > 0) { - if (strcmp(tmp, "none") == 0) { - ret = TRUE; - break; - } - } - g_datalist_clear(&attribs); - last = end + 1; - } - return ret; -} - -/* Grab custom emote icons -static GSList* qq_grab_emoticons(const char *msg, const char*username) -{ - GSList *list; - GList *smileys; - PurpleSmiley *smiley; - const char *smiley_shortcut; - char *ptr; - int length; - PurpleStoredImage *img; - - smileys = purple_smileys_get_all(); - length = strlen(msg); - - for (; smileys; smileys = g_list_delete_link(smileys, smileys)) { - smiley = smileys->data; - smiley_shortcut = purple_smiley_get_shortcut(smiley); - purple_debug_info("QQ", "Smiley shortcut [%s]\n", smiley_shortcut); - - ptr = g_strstr_len(msg, length, smiley_shortcut); - - if (!ptr) - continue; - - purple_debug_info("QQ", "Found Smiley shortcut [%s]\n", smiley_shortcut); - - img = purple_smiley_get_stored_image(smiley); - - emoticon = g_new0(MsnEmoticon, 1); - emoticon->smile = g_strdup(purple_smiley_get_shortcut(smiley)); - emoticon->obj = msn_object_new_from_image(img, - purple_imgstore_get_filename(img), - username, MSN_OBJECT_EMOTICON); - - purple_imgstore_unref(img); - list = g_slist_prepend(list, emoticon); - } - return list; -} -*/ - -gint qq_send_im(PurpleConnection *gc, const gchar *who, const gchar *what, PurpleMessageFlags flags) -{ - qq_data *qd; - UID uid_to; - gint type; - qq_im_format *fmt; - gchar *msg_stripped, *tmp; - GSList *segments, *it; - gint msg_len; - const gchar *start_invalid; - gboolean is_smiley_none; - guint8 frag_count, frag_index; - guint8 msg_id; - - g_return_val_if_fail(NULL != gc && NULL != gc->proto_data, -1); - g_return_val_if_fail(who != NULL && what != NULL, -1); - - qd = (qq_data *) gc->proto_data; - purple_debug_info("QQ", "Send IM to %s, len %" G_GSIZE_FORMAT ":\n%s\n", who, strlen(what), what); - - uid_to = purple_name_to_uid(who); - if (uid_to == qd->uid) { - /* if msg is to myself, bypass the network */ - serv_got_im(gc, who, what, flags, time(NULL)); - return 1; - } - - type = (flags == PURPLE_MESSAGE_AUTO_RESP ? QQ_IM_AUTO_REPLY : QQ_IM_TEXT); - /* qq_show_packet("IM UTF8", (guint8 *)what, strlen(what)); */ - - msg_stripped = purple_markup_strip_html(what); - g_return_val_if_fail(msg_stripped != NULL, -1); - /* qq_show_packet("IM Stripped", (guint8 *)what, strlen(what)); */ - - /* Check and valid utf8 string */ - msg_len = strlen(msg_stripped); - g_return_val_if_fail(msg_len > 0, -1); - if (!g_utf8_validate(msg_stripped, msg_len, &start_invalid)) { - if (start_invalid > msg_stripped) { - tmp = g_strndup(msg_stripped, start_invalid - msg_stripped); - g_free(msg_stripped); - msg_stripped = g_strconcat(tmp, _("(Invalid UTF-8 string)"), NULL); - g_free(tmp); - } else { - g_free(msg_stripped); - msg_stripped = g_strdup(_("(Invalid UTF-8 string)")); - } - } - - is_smiley_none = qq_im_smiley_none(what); - segments = qq_im_get_segments(msg_stripped, is_smiley_none); - g_free(msg_stripped); - - if (segments == NULL) { - return -1; - } - - qd->send_im_id++; - msg_id = (guint8)(qd->send_im_id && 0xFF); - fmt = qq_im_fmt_new_by_purple(what); - frag_count = g_slist_length(segments); - frag_index = 0; - for (it = segments; it; it = it->next) { - /* - request_send_im(gc, uid_to, type, fmt, (gchar *)it->data, - msg_id, frag_count, frag_index); - */ - request_send_im(gc, uid_to, type, fmt, (gchar *)it->data, 0, 0, 0); - g_free(it->data); - frag_index++; - } - g_slist_free(segments); - qq_im_fmt_free(fmt); - return 1; -} diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/qq/im.h --- a/libpurple/protocols/qq/im.h Thu May 05 03:40:29 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,81 +0,0 @@ -/** - * @file im.h - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * 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 02111-1301 USA - */ - -#ifndef _QQ_IM_H_ -#define _QQ_IM_H_ - -#include -#include "connection.h" - -enum { - QQ_MSG_TO_BUDDY = 0x0009, - QQ_MSG_TO_UNKNOWN = 0x000a, - QQ_MSG_SMS = 0x0014, /* not sure */ - QQ_MSG_NEWS = 0x0018, - QQ_MSG_QUN_IM_UNKNOWN = 0x0020, - QQ_MSG_ADD_TO_QUN = 0x0021, - QQ_MSG_DEL_FROM_QUN = 0x0022, - QQ_MSG_APPLY_ADD_TO_QUN = 0x0023, - QQ_MSG_APPROVE_APPLY_ADD_TO_QUN = 0x0024, - QQ_MSG_REJCT_APPLY_ADD_TO_QUN = 0x0025, - QQ_MSG_CREATE_QUN = 0x0026, - QQ_MSG_TEMP_QUN_IM = 0x002A, - QQ_MSG_QUN_IM = 0x002B, - QQ_MSG_SYS_30 = 0x0030, - QQ_MSG_SYS_4C = 0x004C, - QQ_MSG_EXTEND = 0x0084, - QQ_MSG_EXTEND_85 = 0x0085 -}; - -typedef struct { - /* attr: - bit0-4 for font size, bit5 for bold, - bit6 for italic, bit7 for underline - */ - guint8 attr; - guint8 rgb[3]; - guint16 charset; - gchar *font; /* Attension: font may NULL. font name is in QQ charset */ - guint8 font_len; -} qq_im_format; - -gint qq_put_im_tail(guint8 *buf, qq_im_format *fmt); -gint qq_get_im_tail(qq_im_format *fmt, guint8 *data, gint data_len); - -qq_im_format *qq_im_fmt_new(void); -void qq_im_fmt_free(qq_im_format *fmt); -void qq_im_fmt_reset_font(qq_im_format *fmt); -qq_im_format *qq_im_fmt_new_by_purple(const gchar *msg); -gchar *qq_im_fmt_to_purple(qq_im_format *fmt, gchar *text); -gboolean qq_im_smiley_none(const gchar *msg); -GSList *qq_im_get_segments(gchar *msg_stripped, gboolean is_smiley_none); - -void qq_got_message(PurpleConnection *gc, const gchar *msg); -gint qq_send_im(PurpleConnection *gc, const gchar *who, const gchar *message, PurpleMessageFlags flags); - -void qq_process_im(PurpleConnection *gc, guint8 *data, gint len); -void qq_process_extend_im(PurpleConnection *gc, guint8 *data, gint len); - -gchar *qq_emoticon_to_purple(gchar *text); -#endif diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/qq/packet_parse.c --- a/libpurple/protocols/qq/packet_parse.c Thu May 05 03:40:29 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,190 +0,0 @@ -/** - * @file packet_parse.c - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * 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 02111-1301 USA - */ - -#include - -#include "packet_parse.h" -#include "debug.h" - -/*------------------------------------------------PUT------------------------------------------------*/ - -/* note: - * 1, in these functions, 'b' stands for byte, 'w' stands for word, 'dw' stands for double word. - * 2, we use '*cursor' and 'buf' as two addresses to calculate the length. - * 3, change 'undef' to 'define' to get more info about the packet parsing. */ - -#undef PARSER_DEBUG - -/* read one byte from buf, - * return the number of bytes read if succeeds, otherwise return -1 */ -gint qq_get8(guint8 *b, guint8 *buf) -{ - guint8 b_dest; - memcpy(&b_dest, buf, sizeof(b_dest)); - *b = b_dest; -#ifdef PARSER_DEBUG - purple_debug_info("QQ", "[DBG][get8] buf %p\n", (void *)buf); - purple_debug_info("QQ", "[DBG][get8] b_dest 0x%2x, *b 0x%02x\n", b_dest, *b); -#endif - return sizeof(b_dest); -} - - -/* read two bytes as "guint16" from buf, - * return the number of bytes read if succeeds, otherwise return -1 */ -gint qq_get16(guint16 *w, guint8 *buf) -{ - guint16 w_dest; - memcpy(&w_dest, buf, sizeof(w_dest)); - *w = g_ntohs(w_dest); -#ifdef PARSER_DEBUG - purple_debug_info("QQ", "[DBG][get16] buf %p\n", (void *)buf); - purple_debug_info("QQ", "[DBG][get16] w_dest 0x%04x, *w 0x%04x\n", w_dest, *w); -#endif - return sizeof(w_dest); -} - -/* read four bytes as "guint32" from buf, - * return the number of bytes read if succeeds, otherwise return -1 */ -gint qq_get32(guint32 *dw, guint8 *buf) -{ - guint32 dw_dest; - memcpy(&dw_dest, buf, sizeof(dw_dest)); - *dw = g_ntohl(dw_dest); -#ifdef PARSER_DEBUG - purple_debug_info("QQ", "[DBG][get32] buf %p\n", (void *)buf); - purple_debug_info("QQ", "[DBG][get32] dw_dest 0x%08x, *dw 0x%08x\n", dw_dest, *dw); -#endif - return sizeof(dw_dest); -} - -gint qq_getIP(struct in_addr *ip, guint8 *buf) -{ - memcpy(ip, buf, sizeof(struct in_addr)); - return sizeof(struct in_addr); -} - -/* read datalen bytes from buf, - * return the number of bytes read if succeeds, otherwise return -1 */ -gint qq_getdata(guint8 *data, gint datalen, guint8 *buf) -{ - memcpy(data, buf, datalen); -#ifdef PARSER_DEBUG - purple_debug_info("QQ", "[DBG][getdata] buf %p\n", (void *)buf); -#endif - return datalen; -} - - -/* read four bytes as "time_t" from buf, - * return the number of bytes read if succeeds, otherwise return -1 - * This function is a wrapper around read_packet_dw() to avoid casting. */ -gint qq_getime(time_t *t, guint8 *buf) -{ - guint32 dw_dest; - memcpy(&dw_dest, buf, sizeof(dw_dest)); -#ifdef PARSER_DEBUG - purple_debug_info("QQ", "[DBG][getime] buf %p\n", (void *)buf); - purple_debug_info("QQ", "[DBG][getime] dw_dest before 0x%08x\n", dw_dest); -#endif - dw_dest = g_ntohl(dw_dest); -#ifdef PARSER_DEBUG - purple_debug_info("QQ", "[DBG][getime] dw_dest after 0x%08x\n", dw_dest); -#endif - memcpy(t, &dw_dest, sizeof(dw_dest)); - return sizeof(dw_dest); -} - -/*------------------------------------------------PUT------------------------------------------------*/ -/* pack one byte into buf - * return the number of bytes packed, otherwise return -1 */ -gint qq_put8(guint8 *buf, guint8 b) -{ - memcpy(buf, &b, sizeof(b)); -#ifdef PARSER_DEBUG - purple_debug_info("QQ", "[DBG][put8] buf %p\n", (void *)buf); - purple_debug_info("QQ", "[DBG][put8] b 0x%02x\n", b); -#endif - return sizeof(b); -} - - -/* pack two bytes as "guint16" into buf - * return the number of bytes packed, otherwise return -1 */ -gint qq_put16(guint8 *buf, guint16 w) -{ - guint16 w_porter; - w_porter = g_htons(w); -#ifdef PARSER_DEBUG - purple_debug_info("QQ", "[DBG][put16] buf %p\n", (void *)buf); - purple_debug_info("QQ", "[DBG][put16] w 0x%04x, w_porter 0x%04x\n", w, w_porter); -#endif - memcpy(buf, &w_porter, sizeof(w_porter)); - return sizeof(w_porter); -} - - -/* pack four bytes as "guint32" into buf - * return the number of bytes packed, otherwise return -1 */ -gint qq_put32(guint8 *buf, guint32 dw) -{ - guint32 dw_porter; - dw_porter = g_htonl(dw); -#ifdef PARSER_DEBUG - purple_debug_info("QQ", "[DBG][put32] buf %p\n", (void *)buf); - purple_debug_info("QQ", "[DBG][put32] dw 0x%08x, dw_porter 0x%08x\n", dw, dw_porter); -#endif - memcpy(buf, &dw_porter, sizeof(dw_porter)); - return sizeof(dw_porter); -} - -gint qq_putime(guint8 *buf, time_t *t) -{ - guint32 dw, dw_porter; - memcpy(&dw, t, sizeof(dw)); - dw_porter = g_htonl(dw); -#ifdef PARSER_DEBUG - purple_debug_info("QQ", "[DBG][put32] buf %p\n", (void *)buf); - purple_debug_info("QQ", "[DBG][put32] dw 0x%08x, dw_porter 0x%08x\n", dw, dw_porter); -#endif - memcpy(buf, &dw_porter, sizeof(dw_porter)); - return sizeof(dw_porter); -} - -gint qq_putIP(guint8* buf, struct in_addr *ip) -{ - memcpy(buf, ip, sizeof(struct in_addr)); - return sizeof(struct in_addr); -} - -/* pack datalen bytes into buf - * return the number of bytes packed, otherwise return -1 */ -gint qq_putdata(guint8 *buf, const guint8 *data, const int datalen) -{ - memcpy(buf, data, datalen); -#ifdef PARSER_DEBUG - purple_debug_info("QQ", "[DBG][putdata] buf %p\n", (void *)buf); -#endif - return datalen; -} diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/qq/packet_parse.h --- a/libpurple/protocols/qq/packet_parse.h Thu May 05 03:40:29 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,73 +0,0 @@ -/** - * @file packet_parse.h - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * 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 02111-1301 USA - */ - -#ifndef _QQ_PACKET_PARSE_H_ -#define _QQ_PACKET_PARSE_H_ - -#include -#include - -/* According to "UNIX Network Programming", all TCP/IP implementations - * must support a minimum IP datagram size of 576 bytes, regardless of the MTU. - * Assuming a 20 byte IP header and 8 byte UDP header, this leaves 548 bytes - * as a safe maximum size for UDP messages. - * - * TCP allows packet 64K - */ -#define MAX_PACKET_SIZE 65535 - -#ifndef _WIN32 -#include -#else -#include "win32dep.h" -#endif - -gint qq_get8(guint8 *b, guint8 *buf); -gint qq_get16(guint16 *w, guint8 *buf); -gint qq_get32(guint32 *dw, guint8 *buf); -gint qq_getIP(struct in_addr *ip, guint8 *buf); -gint qq_getime(time_t *t, guint8 *buf); -gint qq_getdata(guint8 *data, gint datalen, guint8 *buf); - -gint qq_put8(guint8 *buf, guint8 b); -gint qq_put16(guint8 *buf, guint16 w); -gint qq_put32(guint8 *buf, guint32 dw); -gint qq_putIP(guint8* buf, struct in_addr *ip); -gint qq_putime(guint8 *buf, time_t *t); -gint qq_putdata(guint8 *buf, const guint8 *data, const int datalen); - -/* -gint read_packet_b(guint8 *buf, guint8 **cursor, gint buflen, guint8 *b); -gint read_packet_w(guint8 *buf, guint8 **cursor, gint buflen, guint16 *w); -gint read_packet_dw(guint8 *buf, guint8 **cursor, gint buflen, guint32 *dw); -gint read_packet_time(guint8 *buf, guint8 **cursor, gint buflen, time_t *t); -gint read_packet_data(guint8 *buf, guint8 **cursor, gint buflen, guint8 *data, gint datalen); - -gint create_packet_b(guint8 *buf, guint8 **cursor, guint8 b); -gint create_packet_w(guint8 *buf, guint8 **cursor, guint16 w); -gint create_packet_dw(guint8 *buf, guint8 **cursor, guint32 dw); -gint create_packet_data(guint8 *buf, guint8 **cursor, guint8 *data, gint datalen); -*/ - -#endif diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/qq/qq.c --- a/libpurple/protocols/qq/qq.c Thu May 05 03:40:29 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1171 +0,0 @@ -/** - * @file qq.c - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * 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 02111-1301 USA - */ - -#include "internal.h" - -#include "accountopt.h" -#include "debug.h" -#include "notify.h" -#include "prefs.h" -#include "prpl.h" -#include "privacy.h" -#include "request.h" -#include "roomlist.h" -#include "server.h" -#include "util.h" - -#include "buddy_info.h" -#include "buddy_memo.h" -#include "buddy_opt.h" -#include "buddy_list.h" -#include "char_conv.h" -#include "group.h" -#include "group_im.h" -#include "group_info.h" -#include "group_join.h" -#include "group_opt.h" -#include "group_internal.h" -#include "qq_define.h" -#include "im.h" -#include "qq_process.h" -#include "qq_base.h" -#include "packet_parse.h" -#include "qq.h" -#include "qq_network.h" -#include "send_file.h" -#include "utils.h" -#include "version.h" - -#define OPENQ_VERSION "0.3.2-p20" - -static GList *server_list_build(gchar select) -{ - GList *list = NULL; - - if ( select == 'T' || select == 'A') { - list = g_list_append(list, "tcpconn.tencent.com:8000"); - list = g_list_append(list, "tcpconn2.tencent.com:8000"); - list = g_list_append(list, "tcpconn3.tencent.com:8000"); - list = g_list_append(list, "tcpconn4.tencent.com:8000"); - list = g_list_append(list, "tcpconn5.tencent.com:8000"); - list = g_list_append(list, "tcpconn6.tencent.com:8000"); - } - if ( select == 'U' || select == 'A') { - list = g_list_append(list, "sz.tencent.com:8000"); - list = g_list_append(list, "sz2.tencent.com:8000"); - list = g_list_append(list, "sz3.tencent.com:8000"); - list = g_list_append(list, "sz4.tencent.com:8000"); - list = g_list_append(list, "sz5.tencent.com:8000"); - list = g_list_append(list, "sz6.tencent.com:8000"); - list = g_list_append(list, "sz7.tencent.com:8000"); - list = g_list_append(list, "sz8.tencent.com:8000"); - list = g_list_append(list, "sz9.tencent.com:8000"); - } - return list; -} - -static void server_list_create(PurpleAccount *account) -{ - PurpleConnection *gc; - qq_data *qd; - const gchar *custom_server; - - gc = purple_account_get_connection(account); - g_return_if_fail(gc != NULL && gc->proto_data != NULL); - qd = gc->proto_data; - - qd->use_tcp = purple_account_get_bool(account, "use_tcp", TRUE); - - custom_server = purple_account_get_string(account, "server", NULL); - - if (custom_server != NULL) { - purple_debug_info("QQ", "Select server '%s'\n", custom_server); - if (*custom_server != '\0' && g_ascii_strcasecmp(custom_server, "auto") != 0) { - qd->servers = g_list_append(qd->servers, g_strdup(custom_server)); - return; - } - } - - if (qd->use_tcp) { - qd->servers = server_list_build('T'); - return; - } - - qd->servers = server_list_build('U'); -} - -static void server_list_remove_all(qq_data *qd) -{ - g_return_if_fail(qd != NULL); - - purple_debug_info("QQ", "free server list\n"); - g_list_free(qd->servers); - qd->curr_server = NULL; -} - -static void qq_login(PurpleAccount *account) -{ - PurpleConnection *gc; - qq_data *qd; - PurplePresence *presence; - const gchar *version_str; - - g_return_if_fail(account != NULL); - - gc = purple_account_get_connection(account); - g_return_if_fail(gc != NULL); - - gc->flags |= PURPLE_CONNECTION_HTML | PURPLE_CONNECTION_NO_BGCOLOR | PURPLE_CONNECTION_AUTO_RESP; - - qd = g_new0(qq_data, 1); - memset(qd, 0, sizeof(qq_data)); - qd->gc = gc; - gc->proto_data = qd; - - presence = purple_account_get_presence(account); - if(purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_INVISIBLE)) { - qd->login_mode = QQ_LOGIN_MODE_HIDDEN; - } else if(purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_AWAY) - || purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_EXTENDED_AWAY)) { - qd->login_mode = QQ_LOGIN_MODE_AWAY; - } else { - qd->login_mode = QQ_LOGIN_MODE_NORMAL; - } - - server_list_create(account); - purple_debug_info("QQ", "Server list has %d\n", g_list_length(qd->servers)); - - version_str = purple_account_get_string(account, "client_version", NULL); - qd->client_tag = QQ_CLIENT_115B; /* set default as QQ2008 */ - qd->client_version = 2008; - if (version_str != NULL && strlen(version_str) != 0) { - if (strcmp(version_str, "qq2005") == 0) { - qd->client_tag = QQ_CLIENT_0D55; - qd->client_version = 2005; - } else if (strcmp(version_str, "qq2007") == 0) { - qd->client_tag = QQ_CLIENT_111D; - qd->client_version = 2007; - } - } - - qd->is_show_notice = purple_account_get_bool(account, "show_notice", TRUE); - qd->is_show_news = purple_account_get_bool(account, "show_news", TRUE); - qd->is_show_chat = purple_account_get_bool(account, "show_chat", TRUE); - - if (purple_account_get_bool(account, "default_font", FALSE)) { - qd->custom = QQ_CUSTOM_USE_DEFAULT_FONT; - } - else { - qd->custom = QQ_CUSTOM_NONE; - } - - qd->resend_times = purple_prefs_get_int("/plugins/prpl/qq/resend_times"); - if (qd->resend_times <= 1) qd->itv_config.resend = 4; - - qd->itv_config.resend = purple_prefs_get_int("/plugins/prpl/qq/resend_interval"); - if (qd->itv_config.resend <= 0) qd->itv_config.resend = 3; - purple_debug_info("QQ", "Resend interval %d, retries %d\n", - qd->itv_config.resend, qd->resend_times); - - qd->itv_config.keep_alive = purple_account_get_int(account, "keep_alive_interval", 60); - if (qd->itv_config.keep_alive < 30) qd->itv_config.keep_alive = 30; - qd->itv_config.keep_alive /= qd->itv_config.resend; - qd->itv_count.keep_alive = qd->itv_config.keep_alive; - - qd->itv_config.update = purple_account_get_int(account, "update_interval", 300); - if (qd->itv_config.update > 0) { - if (qd->itv_config.update < qd->itv_config.keep_alive) { - qd->itv_config.update = qd->itv_config.keep_alive; - } - qd->itv_config.update /= qd->itv_config.resend; - qd->itv_count.update = qd->itv_config.update; - } else { - qd->itv_config.update = 0; - } - - qd->connect_watcher = purple_timeout_add_seconds(0, qq_connect_later, gc); -} - -/* clean up the given QQ connection and free all resources */ -static void qq_close(PurpleConnection *gc) -{ - qq_data *qd; - - g_return_if_fail(gc != NULL && gc->proto_data); - qd = gc->proto_data; - - if (qd->check_watcher > 0) { - purple_timeout_remove(qd->check_watcher); - qd->check_watcher = 0; - } - - if (qd->connect_watcher > 0) { - purple_timeout_remove(qd->connect_watcher); - qd->connect_watcher = 0; - } - - /* This is cancelled by _purple_connection_destroy */ - qd->conn_data = NULL; - - qq_disconnect(gc); - - if (qd->redirect) g_free(qd->redirect); - if (qd->ld.token) g_free(qd->ld.token); - if (qd->ld.token_ex) g_free(qd->ld.token_ex); - if (qd->captcha.token) g_free(qd->captcha.token); - if (qd->captcha.data) g_free(qd->captcha.data); - - server_list_remove_all(qd); - - g_free(qd); - gc->proto_data = NULL; -} - -/* returns the icon name for a buddy or protocol */ -static const gchar *qq_list_icon(PurpleAccount *a, PurpleBuddy *b) -{ - return "qq"; -} - - -/* a short status text beside buddy icon*/ -static gchar *qq_status_text(PurpleBuddy *b) -{ - qq_buddy_data *bd; - GString *status; - - bd = purple_buddy_get_protocol_data(b); - if (bd == NULL) - return NULL; - - status = g_string_new(""); - - switch(bd->status) { - case QQ_BUDDY_OFFLINE: - g_string_append(status, _("Offline")); - break; - case QQ_BUDDY_ONLINE_NORMAL: - g_string_append(status, _("Online")); - break; - /* TODO What does this status mean? Labelling it as offline... */ - case QQ_BUDDY_CHANGE_TO_OFFLINE: - g_string_append(status, _("Offline")); - break; - case QQ_BUDDY_ONLINE_AWAY: - g_string_append(status, _("Away")); - break; - case QQ_BUDDY_ONLINE_INVISIBLE: - g_string_append(status, _("Invisible")); - break; - case QQ_BUDDY_ONLINE_BUSY: - g_string_append(status, _("Busy")); - break; - default: - g_string_printf(status, _("Unknown-%d"), bd->status); - } - - return g_string_free(status, FALSE); -} - - -/* a floating text when mouse is on the icon, show connection status here */ -static void qq_tooltip_text(PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboolean full) -{ - qq_buddy_data *bd; - gchar *tmp; - GString *str; - - g_return_if_fail(b != NULL); - - bd = purple_buddy_get_protocol_data(b); - if (bd == NULL) - return; - - /* if (PURPLE_BUDDY_IS_ONLINE(b) && bd != NULL) */ - if (bd->ip.s_addr != 0) { - str = g_string_new(NULL); - g_string_printf(str, "%s:%d", inet_ntoa(bd->ip), bd->port); - if (bd->comm_flag & QQ_COMM_FLAG_TCP_MODE) { - g_string_append(str, " TCP"); - } else { - g_string_append(str, " UDP"); - } - g_string_free(str, TRUE); - } - - tmp = g_strdup_printf("%d", bd->age); - purple_notify_user_info_add_pair(user_info, _("Age"), tmp); - g_free(tmp); - - switch (bd->gender) { - case QQ_BUDDY_GENDER_GG: - purple_notify_user_info_add_pair(user_info, _("Gender"), _("Male")); - break; - case QQ_BUDDY_GENDER_MM: - purple_notify_user_info_add_pair(user_info, _("Gender"), _("Female")); - break; - case QQ_BUDDY_GENDER_UNKNOWN: - purple_notify_user_info_add_pair(user_info, _("Gender"), _("Unknown")); - break; - default: - tmp = g_strdup_printf("Error (%d)", bd->gender); - purple_notify_user_info_add_pair(user_info, _("Gender"), tmp); - g_free(tmp); - } - - if (bd->level) { - tmp = g_strdup_printf("%d", bd->level); - purple_notify_user_info_add_pair(user_info, _("Level"), tmp); - g_free(tmp); - } - - str = g_string_new(NULL); - if (bd->comm_flag & QQ_COMM_FLAG_QQ_MEMBER) { - g_string_append( str, _("Member") ); - } - if (bd->comm_flag & QQ_COMM_FLAG_QQ_VIP) { - g_string_append( str, _(" VIP") ); - } - if (bd->comm_flag & QQ_COMM_FLAG_TCP_MODE) { - g_string_append( str, _(" TCP") ); - } - if (bd->comm_flag & QQ_COMM_FLAG_MOBILE) { - g_string_append( str, _(" FromMobile") ); - } - if (bd->comm_flag & QQ_COMM_FLAG_BIND_MOBILE) { - g_string_append( str, _(" BindMobile") ); - } - if (bd->comm_flag & QQ_COMM_FLAG_VIDEO) { - g_string_append( str, _(" Video") ); - } - - if (bd->ext_flag & QQ_EXT_FLAG_ZONE) { - g_string_append( str, _(" Zone") ); - } - purple_notify_user_info_add_pair(user_info, _("Flag"), str->str); - - g_string_free(str, TRUE); - -#ifdef DEBUG - tmp = g_strdup_printf( "%s (%04X)", - qq_get_ver_desc(bd->client_tag), - bd->client_tag ); - purple_notify_user_info_add_pair(user_info, _("Ver"), tmp); - g_free(tmp); - - tmp = g_strdup_printf( "Ext 0x%X, Comm 0x%X", - bd->ext_flag, bd->comm_flag ); - purple_notify_user_info_add_pair(user_info, _("Flag"), tmp); - g_free(tmp); -#endif -} - -/* we can show tiny icons on the four corners of buddy icon, */ -static const char *qq_list_emblem(PurpleBuddy *b) -{ - PurpleAccount *account; - qq_buddy_data *buddy; - - if (!b || !(account = purple_buddy_get_account(b)) || - !purple_account_get_connection(account)) - return NULL; - - buddy = purple_buddy_get_protocol_data(b); - if (!buddy) { - return "not-authorized"; - } - - if (buddy->comm_flag & QQ_COMM_FLAG_MOBILE) - return "mobile"; - if (buddy->comm_flag & QQ_COMM_FLAG_VIDEO) - return "video"; - if (buddy->comm_flag & QQ_COMM_FLAG_QQ_MEMBER) - return "qq_member"; - - return NULL; -} - -/* QQ away status (used to initiate QQ away packet) */ -static GList *qq_status_types(PurpleAccount *ga) -{ - PurpleStatusType *status; - GList *types = NULL; - - status = purple_status_type_new_full(PURPLE_STATUS_AVAILABLE, - "available", _("Available"), TRUE, TRUE, FALSE); - types = g_list_append(types, status); - - status = purple_status_type_new_full(PURPLE_STATUS_AWAY, - "away", _("Away"), TRUE, TRUE, FALSE); - types = g_list_append(types, status); - - status = purple_status_type_new_full(PURPLE_STATUS_INVISIBLE, - "invisible", _("Invisible"), TRUE, TRUE, FALSE); - types = g_list_append(types, status); - - status = purple_status_type_new_full(PURPLE_STATUS_UNAVAILABLE, - "busy", _("Busy"), TRUE, TRUE, FALSE); - types = g_list_append(types, status); - - status = purple_status_type_new_full(PURPLE_STATUS_OFFLINE, - "offline", _("Offline"), TRUE, TRUE, FALSE); - types = g_list_append(types, status); - - status = purple_status_type_new_full(PURPLE_STATUS_MOBILE, - "mobile", NULL, FALSE, FALSE, TRUE); - types = g_list_append(types, status); - - return types; -} - -/* initiate QQ away with proper change_status packet */ -static void qq_change_status(PurpleAccount *account, PurpleStatus *status) -{ - PurpleConnection *gc = purple_account_get_connection(account); - - qq_request_change_status(gc, 0); -} - -/* send packet to get who's detailed information */ -static void qq_show_buddy_info(PurpleConnection *gc, const gchar *who) -{ - UID uid; - qq_data *qd; - - qd = gc->proto_data; - uid = purple_name_to_uid(who); - - if (uid <= 0) { - purple_debug_error("QQ", "Not valid QQid: %s\n", who); - purple_notify_error(gc, NULL, _("Invalid name"), NULL); - return; - } - - if (qd->client_version >= 2007) { - qq_request_get_level_2007(gc, uid); - } else { - qq_request_get_level(gc, uid); - } - qq_request_buddy_info(gc, uid, 0, QQ_BUDDY_INFO_DISPLAY); -} - -static void action_update_all_rooms(PurplePluginAction *action) -{ - PurpleConnection *gc = (PurpleConnection *) action->context; - qq_data *qd; - - g_return_if_fail(NULL != gc && NULL != gc->proto_data); - qd = (qq_data *) gc->proto_data; - - if ( !qd->is_login ) { - return; - } - - qq_update_all_rooms(gc, 0, 0); -} - -static void action_change_icon(PurplePluginAction *action) -{ - PurpleConnection *gc = (PurpleConnection *) action->context; - qq_data *qd; - gchar *icon_name; - gchar *icon_path; - - g_return_if_fail(NULL != gc && NULL != gc->proto_data); - qd = (qq_data *) gc->proto_data; - - if ( !qd->is_login ) { - return; - } - - icon_name = qq_get_icon_name(qd->my_icon); - icon_path = qq_get_icon_path(icon_name); - g_free(icon_name); - - purple_debug_info("QQ", "Change prev icon %s to...\n", icon_path); - purple_request_file(action, _("Select icon..."), icon_path, - FALSE, - G_CALLBACK(qq_change_icon_cb), NULL, - purple_connection_get_account(gc), NULL, NULL, - gc); - g_free(icon_path); -} - -static void action_modify_info_base(PurplePluginAction *action) -{ - PurpleConnection *gc = (PurpleConnection *) action->context; - qq_data *qd; - - g_return_if_fail(NULL != gc && NULL != gc->proto_data); - qd = (qq_data *) gc->proto_data; - qq_request_buddy_info(gc, qd->uid, 0, QQ_BUDDY_INFO_MODIFY_BASE); -} - -static void action_modify_info_ext(PurplePluginAction *action) -{ - PurpleConnection *gc = (PurpleConnection *) action->context; - qq_data *qd; - - g_return_if_fail(NULL != gc && NULL != gc->proto_data); - qd = (qq_data *) gc->proto_data; - qq_request_buddy_info(gc, qd->uid, 0, QQ_BUDDY_INFO_MODIFY_EXT); -} - -static void action_modify_info_addr(PurplePluginAction *action) -{ - PurpleConnection *gc = (PurpleConnection *) action->context; - qq_data *qd; - - g_return_if_fail(NULL != gc && NULL != gc->proto_data); - qd = (qq_data *) gc->proto_data; - qq_request_buddy_info(gc, qd->uid, 0, QQ_BUDDY_INFO_MODIFY_ADDR); -} - -static void action_modify_info_contact(PurplePluginAction *action) -{ - PurpleConnection *gc = (PurpleConnection *) action->context; - qq_data *qd; - - g_return_if_fail(NULL != gc && NULL != gc->proto_data); - qd = (qq_data *) gc->proto_data; - qq_request_buddy_info(gc, qd->uid, 0, QQ_BUDDY_INFO_MODIFY_CONTACT); -} - -static void action_change_password(PurplePluginAction *action) -{ - PurpleConnection *gc = (PurpleConnection *) action->context; - - g_return_if_fail(NULL != gc && NULL != gc->proto_data); - purple_notify_uri(NULL, "https://password.qq.com"); -} - -/* show a brief summary of what we get from login packet */ -static void action_show_account_info(PurplePluginAction *action) -{ - PurpleConnection *gc = (PurpleConnection *) action->context; - qq_data *qd; - GString *info; - struct tm *tm_local; - int index; - - g_return_if_fail(NULL != gc && NULL != gc->proto_data); - qd = (qq_data *) gc->proto_data; - info = g_string_new(""); - - tm_local = localtime(&qd->login_time); - g_string_append_printf(info, _("Login time: %d-%d-%d, %d:%d:%d
\n"), - (1900 +tm_local->tm_year), (1 + tm_local->tm_mon), tm_local->tm_mday, - tm_local->tm_hour, tm_local->tm_min, tm_local->tm_sec); - g_string_append_printf(info, _("Total Online Buddies: %d
\n"), qd->online_total); - tm_local = localtime(&qd->online_last_update); - g_string_append_printf(info, _("Last Refresh: %d-%d-%d, %d:%d:%d
\n"), - (1900 +tm_local->tm_year), (1 + tm_local->tm_mon), tm_local->tm_mday, - tm_local->tm_hour, tm_local->tm_min, tm_local->tm_sec); - - g_string_append(info, "
"); - - g_string_append_printf(info, _("Server: %s
\n"), qd->curr_server); - g_string_append_printf(info, _("Client Tag: %s
\n"), qq_get_ver_desc(qd->client_tag)); - g_string_append_printf(info, _("Connection Mode: %s
\n"), qd->use_tcp ? "TCP" : "UDP"); - g_string_append_printf(info, _("My Internet IP: %s:%d
\n"), inet_ntoa(qd->my_ip), qd->my_port); - - g_string_append(info, "
"); - g_string_append(info, "Network Status
\n"); - g_string_append_printf(info, _("Sent: %lu
\n"), qd->net_stat.sent); - g_string_append_printf(info, _("Resend: %lu
\n"), qd->net_stat.resend); - g_string_append_printf(info, _("Lost: %lu
\n"), qd->net_stat.lost); - g_string_append_printf(info, _("Received: %lu
\n"), qd->net_stat.rcved); - g_string_append_printf(info, _("Received Duplicate: %lu
\n"), qd->net_stat.rcved_dup); - - g_string_append(info, "
"); - g_string_append(info, "Last Login Information
\n"); - - for (index = 0; index < sizeof(qd->last_login_time) / sizeof(time_t); index++) { - tm_local = localtime(&qd->last_login_time[index]); - g_string_append_printf(info, _("Time: %d-%d-%d, %d:%d:%d
\n"), - (1900 +tm_local->tm_year), (1 + tm_local->tm_mon), tm_local->tm_mday, - tm_local->tm_hour, tm_local->tm_min, tm_local->tm_sec); - } - if (qd->last_login_ip.s_addr != 0) { - g_string_append_printf(info, _("IP: %s
\n"), inet_ntoa(qd->last_login_ip)); - } - - g_string_append(info, ""); - - purple_notify_formatted(gc, NULL, _("Login Information"), NULL, info->str, NULL, NULL); - - g_string_free(info, TRUE); -} - -static void action_about_openq(PurplePluginAction *action) -{ - PurpleConnection *gc = (PurpleConnection *) action->context; - GString *info; - gchar *title; - - g_return_if_fail(NULL != gc); - - info = g_string_new(""); - g_string_append(info, _("

Original Author:
\n")); - g_string_append(info, "puzzlebird
\n"); - g_string_append(info, "
\n"); - - g_string_append(info, _("

Code Contributors:
\n")); - g_string_append(info, "gfhuang(poppyer) : patches for libpurple 2.0.0beta2, maintainer
\n"); - g_string_append(info, "Yuan Qingyun : patches for libpurple 1.5.0, maintainer
\n"); - g_string_append(info, "henryouly : file transfer, udp sock5 proxy and qq_show, maintainer
\n"); - g_string_append(info, "hzhr : maintainer
\n"); - g_string_append(info, "joymarquis : maintainer
\n"); - g_string_append(info, "arfankai : fixed bugs in char_conv.c
\n"); - g_string_append(info, "rakescar : provided filter for HTML tag
\n"); - g_string_append(info, "yyw : improved performance on PPC linux
\n"); - g_string_append(info, "lvxiang : provided ip to location original code
\n"); - g_string_append(info, "markhuetsch : OpenQ merge into libpurple, maintainer 2006-2007
\n"); - g_string_append(info, "ccpaging : maintainer since 2007
\n"); - g_string_append(info, "icesky : maintainer since 2007
\n"); - g_string_append(info, "csyfek : faces, maintainer since 2007
\n"); - g_string_append(info, "
\n"); - - g_string_append(info, _("

Lovely Patch Writers:
\n")); - g_string_append(info, "gnap : message displaying, documentation
\n"); - g_string_append(info, "manphiz : qun processing
\n"); - g_string_append(info, "moo : qun processing
\n"); - g_string_append(info, "Coly Li : qun processing
\n"); - g_string_append(info, "Emil Alexiev : captcha verification on login based on LumaQQ for MAC (2007), login, add buddy, remove buddy, message exchange and logout
\n"); - g_string_append(info, "Chengming Wang : buddy memo
\n"); - g_string_append(info, "lonicerae : chat room window bugfix, server list bugfix, buddy memo
\n"); - g_string_append(info, "
\n"); - - g_string_append(info, _("

Acknowledgement:
\n")); - g_string_append(info, "Shufeng Tan : http://sf.net/projects/perl-oicq
\n"); - g_string_append(info, "Jeff Ye : http://www.sinomac.com
\n"); - g_string_append(info, "Hu Zheng : http://forlinux.yeah.net
\n"); - g_string_append(info, "yunfan : http://www.myswear.net
\n"); - g_string_append(info, "OpenQ Team : http://openq.linuxsir.org
\n"); - g_string_append(info, "LumaQQ Team : http://lumaqq.linuxsir.org
\n"); - g_string_append(info, "Pidgin Team : http://www.pidgin.im
\n"); - g_string_append(info, "Huang Guan : http://home.xxsyzx.com
\n"); - g_string_append(info, "OpenQ Google Group : http://groups.google.com/group/openq
\n"); - g_string_append(info, "
\n"); - - g_string_append(info, _("

Scrupulous Testers:
\n")); - g_string_append(info, "yegle
\n"); - g_string_append(info, "cnzhangbx
\n"); - g_string_append(info, "casparant
\n"); - g_string_append(info, "wd
\n"); - g_string_append(info, "x6719620
\n"); - g_string_append(info, "netelk
\n"); - g_string_append(info, _("and more, please let me know... thank you!))")); - g_string_append(info, "
\n
\n"); - g_string_append(info, _("

And, all the boys in the backroom...
\n")); - g_string_append(info, _("Feel free to join us! :)")); - g_string_append(info, ""); - - title = g_strdup_printf(_("About OpenQ %s"), OPENQ_VERSION); - purple_notify_formatted(gc, title, title, NULL, info->str, NULL, NULL); - - g_free(title); - g_string_free(info, TRUE); -} - -/* - static void _qq_menu_search_or_add_permanent_group(PurplePluginAction *action) - { - purple_roomlist_show_with_account(NULL); - } -*/ - -/* - static void _qq_menu_create_permanent_group(PurplePluginAction * action) - { - PurpleConnection *gc = (PurpleConnection *) action->context; - purple_request_input(gc, _("Create QQ Qun"), - _("Input Qun name here"), - _("Only QQ members can create permanent Qun"), - "OpenQ", FALSE, FALSE, NULL, - _("Create"), G_CALLBACK(qq_create_room), _("Cancel"), NULL, gc); - } -*/ - -static void action_chat_quit(PurpleBlistNode * node) -{ - PurpleChat *chat = (PurpleChat *)node; - PurpleAccount *account = purple_chat_get_account(chat); - PurpleConnection *gc = purple_account_get_connection(account); - GHashTable *components = purple_chat_get_components(chat); - gchar *num_str; - guint32 room_id; - - g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node)); - - g_return_if_fail(components != NULL); - - num_str = g_hash_table_lookup(components, QQ_ROOM_KEY_INTERNAL_ID); - room_id = strtoul(num_str, NULL, 10); - g_return_if_fail(room_id != 0); - - qq_room_quit(gc, room_id); -} - -static void action_chat_get_info(PurpleBlistNode * node) -{ - PurpleChat *chat = (PurpleChat *)node; - PurpleAccount *account = purple_chat_get_account(chat); - PurpleConnection *gc = purple_account_get_connection(account); - GHashTable *components = purple_chat_get_components(chat); - gchar *num_str; - guint32 room_id; - - g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node)); - - g_return_if_fail(components != NULL); - - num_str = g_hash_table_lookup(components, QQ_ROOM_KEY_INTERNAL_ID); - room_id = strtoul(num_str, NULL, 10); - g_return_if_fail(room_id != 0); - - qq_send_room_cmd_mess(gc, QQ_ROOM_CMD_GET_INFO, room_id, NULL, 0, - 0, QQ_ROOM_INFO_DISPLAY); -} - -#if 0 -/* TODO: re-enable this */ -static void _qq_menu_send_file(PurpleBlistNode * node, gpointer ignored) -{ - PurpleBuddy *buddy; - PurpleConnection *gc; - qq_buddy_data *bd; - - g_return_if_fail (PURPLE_BLIST_NODE_IS_BUDDY (node)); - buddy = (PurpleBuddy *) node; - bd = (qq_buddy_data *) buddy->proto_data; - /* if (is_online (bd->status)) { */ - gc = purple_account_get_connection (buddy->account); - g_return_if_fail (gc != NULL && gc->proto_data != NULL); - qq_send_file(gc, buddy->name, NULL); - /* } */ -} -#endif - -/* protocol related menus */ -static GList *qq_actions(PurplePlugin *plugin, gpointer context) -{ - GList *m; - PurplePluginAction *act; - - m = NULL; - act = purple_plugin_action_new(_("Change Icon"), action_change_icon); - m = g_list_append(m, act); - - act = purple_plugin_action_new(_("Modify Information"), action_modify_info_base); - m = g_list_append(m, act); - - act = purple_plugin_action_new(_("Modify Extended Information"), action_modify_info_ext); - m = g_list_append(m, act); - - act = purple_plugin_action_new(_("Modify Address"), action_modify_info_addr); - m = g_list_append(m, act); - - act = purple_plugin_action_new(_("Modify Contact"), action_modify_info_contact); - m = g_list_append(m, act); - - act = purple_plugin_action_new(_("Change Password"), action_change_password); - m = g_list_append(m, act); - - act = purple_plugin_action_new(_("Account Information"), action_show_account_info); - m = g_list_append(m, act); - - act = purple_plugin_action_new(_("Update all QQ Quns"), action_update_all_rooms); - m = g_list_append(m, act); - - act = purple_plugin_action_new(_("About OpenQ"), action_about_openq); - m = g_list_append(m, act); - /* - act = purple_plugin_action_new(_("Qun: Search a permanent Qun"), _qq_menu_search_or_add_permanent_group); - m = g_list_append(m, act); - - act = purple_plugin_action_new(_("Qun: Create a permanent Qun"), _qq_menu_create_permanent_group); - m = g_list_append(m, act); - */ - - return m; -} - -static void qq_add_buddy_from_menu_cb(PurpleBlistNode *node, gpointer data) -{ - PurpleBuddy *buddy; - PurpleConnection *gc; - - g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); - - buddy = (PurpleBuddy *) node; - gc = purple_account_get_connection(purple_buddy_get_account(buddy)); - - qq_add_buddy(gc, buddy, NULL); -} - -static void qq_modify_buddy_memo_from_menu_cb(PurpleBlistNode *node, gpointer data) -{ - PurpleBuddy *buddy; - qq_buddy_data *bd; - PurpleConnection *gc; - UID bd_uid; - - g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); - - buddy = (PurpleBuddy *)node; - g_return_if_fail(NULL != buddy); - - gc = purple_account_get_connection(purple_buddy_get_account(buddy)); - g_return_if_fail(NULL != gc); - - bd = (qq_buddy_data *)purple_buddy_get_protocol_data(buddy); - g_return_if_fail(NULL != bd); - bd_uid = bd->uid; - - /* param: gc, uid, update_class, action - * here, update_class is set to bd_uid. because some memo packages returned - * without uid, which will make us confused */ - qq_request_buddy_memo(gc, bd_uid, bd_uid, QQ_BUDDY_MEMO_MODIFY); -} - -static GList *qq_buddy_menu(PurpleBuddy *buddy) -{ - GList *m = NULL; - PurpleMenuAction *act; - qq_buddy_data *bd = purple_buddy_get_protocol_data(buddy); - - if (bd == NULL) { - act = purple_menu_action_new(_("Add Buddy"), - PURPLE_CALLBACK(qq_add_buddy_from_menu_cb), - NULL, NULL); - m = g_list_append(m, act); - return m; - } - - - act = purple_menu_action_new(_("Modify Buddy Memo"), - PURPLE_CALLBACK(qq_modify_buddy_memo_from_menu_cb), - NULL, NULL); - m = g_list_append(m, act); - - - /* TODO : not working, temp commented out by gfhuang */ -#if 0 - if (bd && is_online(bd->status)) { - act = purple_menu_action_new(_("Send File"), PURPLE_CALLBACK(_qq_menu_send_file), NULL, NULL); /* add NULL by gfhuang */ - m = g_list_append(m, act); - } -#endif - return m; -} - -/* chat-related (QQ Qun) menu shown up with right-click */ -static GList *qq_chat_menu(PurpleBlistNode *node) -{ - GList *m; - PurpleMenuAction *act; - - m = NULL; - act = purple_menu_action_new(_("Get Info"), PURPLE_CALLBACK(action_chat_get_info), NULL, NULL); - m = g_list_append(m, act); - - act = purple_menu_action_new(_("Quit Qun"), PURPLE_CALLBACK(action_chat_quit), NULL, NULL); - m = g_list_append(m, act); - return m; -} - -/* buddy-related menu shown up with right-click */ -static GList *qq_blist_node_menu(PurpleBlistNode * node) -{ - if(PURPLE_BLIST_NODE_IS_CHAT(node)) - return qq_chat_menu(node); - - if(PURPLE_BLIST_NODE_IS_BUDDY(node)) - return qq_buddy_menu((PurpleBuddy *) node); - - return NULL; -} - -/* convert name displayed in a chat channel to original QQ UID */ -static gchar *chat_name_to_purple_name(const gchar *const name) -{ - const char *start; - const char *end; - gchar *ret; - - g_return_val_if_fail(name != NULL, NULL); - - /* Sample: (1234567)*/ - start = strchr(name, '('); - g_return_val_if_fail(start != NULL, NULL); - end = strchr(start, ')'); - g_return_val_if_fail(end != NULL && (end - start) > 1, NULL); - - ret = g_strndup(start + 1, end - start - 1); - - return ret; -} - -/* convert chat nickname to uid to get this buddy info */ -/* who is the nickname of buddy in QQ chat-room (Qun) */ -static void qq_get_chat_buddy_info(PurpleConnection *gc, gint channel, const gchar *who) -{ - qq_data *qd; - gchar *uid_str; - UID uid; - - purple_debug_info("QQ", "Get chat buddy info of %s\n", who); - g_return_if_fail(who != NULL); - - uid_str = chat_name_to_purple_name(who); - if (uid_str == NULL) { - return; - } - - qd = gc->proto_data; - uid = purple_name_to_uid(uid_str); - g_free(uid_str); - - if (uid <= 0) { - purple_debug_error("QQ", "Not valid chat name: %s\n", who); - purple_notify_error(gc, NULL, _("Invalid name"), NULL); - return; - } - - if (qd->client_version < 2007) { - qq_request_get_level(gc, uid); - } - qq_request_buddy_info(gc, uid, 0, QQ_BUDDY_INFO_DISPLAY); -} - -/* convert chat nickname to uid to invite individual IM to buddy */ -/* who is the nickname of buddy in QQ chat-room (Qun) */ -static gchar *qq_get_chat_buddy_real_name(PurpleConnection *gc, gint channel, const gchar *who) -{ - g_return_val_if_fail(who != NULL, NULL); - return chat_name_to_purple_name(who); -} - -static PurplePluginProtocolInfo prpl_info = -{ - OPT_PROTO_CHAT_TOPIC | OPT_PROTO_USE_POINTSIZE, - NULL, /* user_splits */ - NULL, /* protocol_options */ - {"png", 96, 96, 96, 96, 0, PURPLE_ICON_SCALE_SEND}, /* icon_spec */ - qq_list_icon, /* list_icon */ - qq_list_emblem, /* list_emblems */ - qq_status_text, /* status_text */ - qq_tooltip_text, /* tooltip_text */ - qq_status_types, /* away_states */ - qq_blist_node_menu, /* blist_node_menu */ - qq_chat_info, /* chat_info */ - qq_chat_info_defaults, /* chat_info_defaults */ - qq_login, /* open */ - qq_close, /* close */ - qq_send_im, /* send_im */ - NULL, /* set_info */ - NULL, /* send_typing */ - qq_show_buddy_info, /* get_info */ - qq_change_status, /* change status */ - NULL, /* set_idle */ - NULL, /* change_passwd */ - qq_add_buddy, /* add_buddy */ - NULL, /* add_buddies */ - qq_remove_buddy, /* remove_buddy */ - NULL, /* remove_buddies */ - NULL, /* add_permit */ - NULL, /* add_deny */ - NULL, /* rem_permit */ - NULL, /* rem_deny */ - NULL, /* set_permit_deny */ - qq_group_join, /* join_chat */ - NULL, /* reject chat invite */ - NULL, /* get_chat_name */ - NULL, /* chat_invite */ - NULL, /* chat_leave */ - NULL, /* chat_whisper */ - qq_chat_send, /* chat_send */ - NULL, /* keepalive */ - NULL, /* register_user */ - qq_get_chat_buddy_info, /* get_cb_info */ - NULL, /* get_cb_away */ - NULL, /* alias_buddy */ - NULL, /* change buddy's group */ - NULL, /* rename_group */ - NULL, /* buddy_free */ - NULL, /* convo_closed */ - NULL, /* normalize */ - qq_set_custom_icon, - NULL, /* remove_group */ - qq_get_chat_buddy_real_name, /* get_cb_real_name */ - NULL, /* set_chat_topic */ - NULL, /* find_blist_chat */ - qq_roomlist_get_list, /* roomlist_get_list */ - qq_roomlist_cancel, /* roomlist_cancel */ - NULL, /* roomlist_expand_category */ - NULL, /* can_receive_file */ - NULL, /* qq_send_file send_file */ - NULL, /* new xfer */ - NULL, /* offline_message */ - NULL, /* PurpleWhiteboardPrplOps */ - NULL, /* send_raw */ - NULL, /* roomlist_room_serialize */ - NULL, /* unregister_user */ - NULL, /* send_attention */ - NULL, /* get attention_types */ - - sizeof(PurplePluginProtocolInfo), /* struct_size */ - NULL, /* get_account_text_table */ - NULL, /* initiate_media */ - NULL, /* get_media_caps */ - NULL, /* get_moods */ - NULL, /* set_public_alias */ - NULL, /* get_public_alias */ - NULL, /* add_buddy_with_invite */ - NULL /* add_buddies_with_invite */ -}; - -static PurplePluginInfo info = { - PURPLE_PLUGIN_MAGIC, - PURPLE_MAJOR_VERSION, - PURPLE_MINOR_VERSION, - PURPLE_PLUGIN_PROTOCOL, /**< type */ - NULL, /**< ui_requirement */ - 0, /**< flags */ - NULL, /**< dependencies */ - PURPLE_PRIORITY_DEFAULT, /**< priority */ - - "prpl-qq", /**< id */ - "QQ", /**< name */ - DISPLAY_VERSION, /**< version */ - /** summary */ - N_("QQ Protocol Plugin"), - /** description */ - N_("QQ Protocol Plugin"), - NULL, /**< author */ - PURPLE_WEBSITE, /**< homepage */ - - NULL, /**< load */ - NULL, /**< unload */ - NULL, /**< destroy */ - - NULL, /**< ui_info */ - &prpl_info, /**< extra_info */ - NULL, /**< prefs_info */ - qq_actions, - - /* padding */ - NULL, - NULL, - NULL, - NULL -}; - - -static void init_plugin(PurplePlugin *plugin) -{ - PurpleAccountOption *option; - PurpleKeyValuePair *kvp; - GList *server_list = NULL; - GList *server_kv_list = NULL; - GList *it; - /* #ifdef DEBUG */ - GList *version_kv_list = NULL; - /* #endif */ - - server_list = server_list_build('A'); - - purple_prefs_remove("/plugins/prpl/qq/serverlist"); - - server_kv_list = NULL; - kvp = g_new0(PurpleKeyValuePair, 1); - kvp->key = g_strdup(_("Auto")); - kvp->value = g_strdup("auto"); - server_kv_list = g_list_append(server_kv_list, kvp); - - it = server_list; - while(it) { - if (it->data != NULL && strlen(it->data) > 0) { - kvp = g_new0(PurpleKeyValuePair, 1); - kvp->key = g_strdup(it->data); - kvp->value = g_strdup(it->data); - server_kv_list = g_list_append(server_kv_list, kvp); - } - it = it->next; - } - - g_list_free(server_list); - - option = purple_account_option_list_new(_("Select Server"), "server", server_kv_list); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); - - kvp = g_new0(PurpleKeyValuePair, 1); - kvp->key = g_strdup(_("QQ2008")); - kvp->value = g_strdup("qq2008"); - version_kv_list = g_list_append(version_kv_list, kvp); - - kvp = g_new0(PurpleKeyValuePair, 1); - kvp->key = g_strdup(_("QQ2007")); - kvp->value = g_strdup("qq2007"); - version_kv_list = g_list_append(version_kv_list, kvp); - - kvp = g_new0(PurpleKeyValuePair, 1); - kvp->key = g_strdup(_("QQ2005")); - kvp->value = g_strdup("qq2005"); - version_kv_list = g_list_append(version_kv_list, kvp); - - option = purple_account_option_list_new(_("Client Version"), "client_version", version_kv_list); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); - - option = purple_account_option_bool_new(_("Connect by TCP"), "use_tcp", TRUE); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); - - option = purple_account_option_bool_new(_("Show server notice"), "show_notice", TRUE); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); - - option = purple_account_option_bool_new(_("Show server news"), "show_news", TRUE); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); - - option = purple_account_option_bool_new(_("Show chat room when msg comes"), "show_chat", TRUE); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); - - option = purple_account_option_bool_new(_("Use default font"), "default_font", FALSE); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); - - option = purple_account_option_int_new(_("Keep alive interval (seconds)"), "keep_alive_interval", 60); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); - - option = purple_account_option_int_new(_("Update interval (seconds)"), "update_interval", 300); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); - - purple_prefs_add_none("/plugins/prpl/qq"); - purple_prefs_add_bool("/plugins/prpl/qq/show_status_by_icon", TRUE); - purple_prefs_add_bool("/plugins/prpl/qq/show_fake_video", FALSE); - purple_prefs_add_bool("/plugins/prpl/qq/auto_get_authorize_info", TRUE); - purple_prefs_add_int("/plugins/prpl/qq/resend_interval", 3); - purple_prefs_add_int("/plugins/prpl/qq/resend_times", 10); -} - -PURPLE_INIT_PLUGIN(qq, init_plugin, info); diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/qq/qq.h --- a/libpurple/protocols/qq/qq.h Thu May 05 03:40:29 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,192 +0,0 @@ -/** - * @file qq.h - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * 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 02111-1301 USA - */ - -#ifndef _QQ_QQ_H_ -#define _QQ_QQ_H_ - -#include "internal.h" -#include "ft.h" -#include "circbuffer.h" -#include "dnsquery.h" -#include "dnssrv.h" -#include "proxy.h" -#include "roomlist.h" - -#define QQ_KEY_LENGTH 16 - -/* steal from kazehakase :) */ -#define qq_strlen(s) ((s)!=NULL?strlen(s):0) -#define qq_strcmp(s1,s2) ((s1)!=NULL && (s2)!=NULL?strcmp(s1,s2):0) - -/* business logic layer */ -typedef guint32 UPDCLS; -typedef guint32 UID; - -typedef struct _qq_captcha_data { - guint8 *token; - guint16 token_len; - guint8 next_index; - guint8 *data; - guint16 data_len; -} qq_captcha_data; - -typedef struct _qq_login_data { - guint8 random_key[QQ_KEY_LENGTH]; /* first encrypt key generated by client */ - guint8 *token; /* get from server */ - guint8 token_len; - guint8 *token_ex; /* get from server */ - guint16 token_ex_len; - - guint8 pwd_md5[QQ_KEY_LENGTH]; /* password in md5 (or md5' md5) */ - guint8 pwd_twice_md5[QQ_KEY_LENGTH]; - - guint8 *login_token; - guint16 login_token_len; - guint8 login_key[QQ_KEY_LENGTH]; -} qq_login_data; - -typedef struct _qq_interval { - gint resend; - gint keep_alive; - gint update; -} qq_interval; - -typedef struct _qq_net_stat { - glong sent; - glong resend; - glong lost; - glong rcved; - glong rcved_dup; -} qq_net_stat; - -typedef struct _qq_buddy_data { - UID uid; - guint16 face; /* index: 0 - 299 */ - guint8 age; - guint8 gender; - gchar *nickname; - struct in_addr ip; - guint16 port; - guint8 status; - guint8 ext_flag; - guint8 comm_flag; /* details in qq_buddy_list.c */ - guint16 client_tag; - guint8 onlineTime; - guint16 level; - guint16 timeRemainder; - time_t signon; - time_t idle; - time_t last_update; - gchar** memo; - - gint8 role; /* role in group, used only in group->members list */ -} qq_buddy_data; - -typedef struct _qq_connection qq_connection; -struct _qq_connection { - int fd; /* socket file handler */ - int input_handler; - - /* tcp related */ - int can_write_handler; /* use in tcp_send_out */ - PurpleCircBuffer *tcp_txbuf; - guint8 *tcp_rxqueue; - int tcp_rxlen; -}; - -typedef struct _qq_data { - PurpleConnection *gc; - - GSList *openconns; - gboolean use_tcp; /* network in tcp or udp */ - PurpleProxyConnectData *conn_data; -#ifndef purple_proxy_connect_udp - PurpleDnsQueryData *udp_query_data; /* udp related */ - gint udp_can_write_handler; /* socket can_write handle, use in udp connecting and tcp send out */ -#endif - gint fd; /* socket file handler */ - qq_net_stat net_stat; - - GList *servers; - gchar *curr_server; /* point to servers->data, do not free*/ - - guint16 client_tag; - gint client_version; - - struct in_addr redirect_ip; - guint16 redirect_port; - guint8 *redirect; - guint8 redirect_len; - - guint check_watcher; - guint connect_watcher; - gint connect_retry; - - qq_interval itv_config; - qq_interval itv_count; - guint network_watcher; - gint resend_times; - - GList *transactions; /* check ack packet and resend */ - - UID uid; /* QQ number */ - - qq_login_data ld; - qq_captcha_data captcha; - - guint8 session_key[QQ_KEY_LENGTH]; /* later use this as key in this session */ - guint8 session_md5[QQ_KEY_LENGTH]; /* concatenate my uid with session_key and md5 it */ - - guint16 send_seq; /* send sequence number */ - guint8 login_mode; /* online of invisible */ - gboolean is_login; /* used by qq_add_buddy */ - - PurpleXfer *xfer; /* file transfer handler */ - - /* get from login reply packet */ - struct in_addr my_local_ip; /* my local ip address detected by server */ - guint16 my_local_port; /* my lcoal port detected by server */ - time_t login_time; - time_t last_login_time[3]; - struct in_addr last_login_ip; - /* get from keep_alive packet */ - struct in_addr my_ip; /* my ip address detected by server */ - guint16 my_port; /* my port detected by server */ - guint16 my_icon; /* my icon index */ - guint32 online_total; /* the number of online QQ users */ - time_t online_last_update; /* last time send get_friends_online packet */ - - PurpleRoomlist *roomlist; - - GList *groups; - - gboolean is_show_notice; - gboolean is_show_news; - gboolean is_show_chat; - guint32 custom; - - guint16 send_im_id; /* send IM sequence number */ -} qq_data; - -#endif diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/qq/qq_base.c --- a/libpurple/protocols/qq/qq_base.c Thu May 05 03:40:29 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1491 +0,0 @@ -/** - * @file qq_base.c - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * 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 02111-1301 USA - */ - -#include "internal.h" -#include "debug.h" -#include "server.h" -#include "cipher.h" -#include "request.h" - -#include "buddy_info.h" -#include "buddy_list.h" -#include "char_conv.h" -#include "qq_crypt.h" -#include "group.h" -#include "qq_define.h" -#include "qq_network.h" -#include "qq_base.h" -#include "packet_parse.h" -#include "qq.h" -#include "qq_network.h" -#include "utils.h" - -/* generate a md5 key using uid and session_key */ -static void get_session_md5(guint8 *session_md5, UID uid, guint8 *session_key) -{ - guint8 src[QQ_KEY_LENGTH + QQ_KEY_LENGTH]; - gint bytes = 0; - - bytes += qq_put32(src + bytes, uid); - bytes += qq_putdata(src + bytes, session_key, QQ_KEY_LENGTH); - - qq_get_md5(session_md5, QQ_KEY_LENGTH, src, bytes); -} - -/* process login reply which says OK */ -static gint8 process_login_ok(PurpleConnection *gc, guint8 *data, gint len) -{ - qq_data *qd; - gint bytes; - - guint8 ret; - UID uid; - struct in_addr ip; - guint16 port; - struct tm *tm_local; - - qd = (qq_data *) gc->proto_data; - /* qq_show_packet("Login reply", data, len); */ - - if (len < 148) { - qq_show_packet("Login reply OK, but length < 139", data, len); - purple_connection_error_reason(gc, - PURPLE_CONNECTION_ERROR_ENCRYPTION_ERROR, - _("Unable to decrypt server reply")); - return QQ_LOGIN_REPLY_ERR; - } - - bytes = 0; - bytes += qq_get8(&ret, data + bytes); - bytes += qq_getdata(qd->session_key, sizeof(qd->session_key), data + bytes); - get_session_md5(qd->session_md5, qd->uid, qd->session_key); - purple_debug_info("QQ", "Got session_key\n"); - bytes += qq_get32(&uid, data + bytes); - if (uid != qd->uid) { - purple_debug_warning("QQ", "My uid in login reply is %u, not %u\n", uid, qd->uid); - } - bytes += qq_getIP(&qd->my_ip, data + bytes); - bytes += qq_get16(&qd->my_port, data + bytes); - purple_debug_info("QQ", "Internet IP: %s, %d\n", inet_ntoa(qd->my_ip), qd->my_port); - - bytes += qq_getIP(&qd->my_local_ip, data + bytes); - bytes += qq_get16(&qd->my_local_port, data + bytes); - purple_debug_info("QQ", "Local IP: %s, %d\n", inet_ntoa(qd->my_local_ip), qd->my_local_port); - - bytes += qq_getime(&qd->login_time, data + bytes); - tm_local = localtime(&qd->login_time); - purple_debug_info("QQ", "Login time: %d-%d-%d, %d:%d:%d\n", - (1900 +tm_local->tm_year), (1 + tm_local->tm_mon), tm_local->tm_mday, - tm_local->tm_hour, tm_local->tm_min, tm_local->tm_sec); - /* skip unknown 2 bytes, 0x(03 0a) */ - bytes += 2; - /* skip unknown 24 bytes, maybe token to access Qun shared files */ - bytes += 24; - /* unknow ip and port */ - bytes += qq_getIP(&ip, data + bytes); - bytes += qq_get16(&port, data + bytes); - purple_debug_info("QQ", "Unknow IP: %s, %d\n", inet_ntoa(ip), port); - /* unknow ip and port */ - bytes += qq_getIP(&ip, data + bytes); - bytes += qq_get16(&port, data + bytes); - purple_debug_info("QQ", "Unknow IP: %s, %d\n", inet_ntoa(ip), port); - /* unknown 4 bytes, 0x(00 81 00 00)*/ - bytes += 4; - /* skip unknown 32 bytes, maybe key to access QQ Home */ - bytes += 32; - /* skip unknown 16 bytes, 0x(00 00 00 00 00 00 00 00 00 00 00 40 00 00 00 00) */ - bytes += 16; - /* time */ - bytes += qq_getime(&qd->last_login_time[0], data + bytes); - tm_local = localtime(&qd->last_login_time[0]); - purple_debug_info("QQ", "Last login time: %d-%d-%d, %d:%d:%d\n", - (1900 +tm_local->tm_year), (1 + tm_local->tm_mon), tm_local->tm_mday, - tm_local->tm_hour, tm_local->tm_min, tm_local->tm_sec); - /* unknow time */ - g_return_val_if_fail(sizeof(qd->last_login_time) / sizeof(time_t) > 1, QQ_LOGIN_REPLY_OK); - bytes += qq_getime(&qd->last_login_time[1], data + bytes); - tm_local = localtime(&qd->last_login_time[1]); - purple_debug_info("QQ", "Time: %d-%d-%d, %d:%d:%d\n", - (1900 +tm_local->tm_year), (1 + tm_local->tm_mon), tm_local->tm_mday, - tm_local->tm_hour, tm_local->tm_min, tm_local->tm_sec); - - g_return_val_if_fail(sizeof(qd->last_login_time) / sizeof(time_t) > 2, QQ_LOGIN_REPLY_OK); - bytes += qq_getime(&qd->last_login_time[2], data + bytes); - tm_local = localtime(&qd->last_login_time[2]); - purple_debug_info("QQ", "Time: %d-%d-%d, %d:%d:%d\n", - (1900 +tm_local->tm_year), (1 + tm_local->tm_mon), tm_local->tm_mday, - tm_local->tm_hour, tm_local->tm_min, tm_local->tm_sec); - /* unknow 9 bytes, 0x(00 0a 00 0a 01 00 00 0e 10) */ - - if (len > 148) { - qq_show_packet("Login reply OK, but length > 139", data, len); - } - return QQ_LOGIN_REPLY_OK; -} - -/* process login reply packet which includes redirected new server address */ -static gint8 process_login_redirect(PurpleConnection *gc, guint8 *data, gint len) -{ - qq_data *qd; - gint bytes; - struct { - guint8 result; - UID uid; - struct in_addr new_server_ip; - guint16 new_server_port; - } packet; - - - if (len < 11) { - purple_connection_error_reason(gc, - PURPLE_CONNECTION_ERROR_ENCRYPTION_ERROR, - _("Unable to decrypt server reply")); - return QQ_LOGIN_REPLY_ERR; - } - - qd = (qq_data *) gc->proto_data; - bytes = 0; - /* 000-000: reply code */ - bytes += qq_get8(&packet.result, data + bytes); - /* 001-004: login uid */ - bytes += qq_get32(&packet.uid, data + bytes); - /* 005-008: redirected new server IP */ - bytes += qq_getIP(&packet.new_server_ip, data + bytes); - /* 009-010: redirected new server port */ - bytes += qq_get16(&packet.new_server_port, data + bytes); - - if (len > 11) { - purple_debug_error("QQ", "Login redirect more than expected %d bytes, read %d bytes\n", 11, bytes); - } - - /* redirect to new server, do not disconnect or connect here - * those connect should be called at packet_process */ - qd->redirect_ip.s_addr = packet.new_server_ip.s_addr; - qd->redirect_port = packet.new_server_port; - return QQ_LOGIN_REPLY_REDIRECT; -} - -/* request before login */ -void qq_request_token(PurpleConnection *gc) -{ - qq_data *qd; - guint8 buf[16] = {0}; - gint bytes = 0; - - g_return_if_fail(gc != NULL && gc->proto_data != NULL); - qd = (qq_data *) gc->proto_data; - - bytes += qq_put8(buf + bytes, 0); - - qd->send_seq++; - qq_send_cmd_encrypted(gc, QQ_CMD_TOKEN, qd->send_seq, buf, bytes, TRUE); -} - -/* send login packet to QQ server */ -void qq_request_login(PurpleConnection *gc) -{ - qq_data *qd; - guint8 *buf, *raw_data; - gint bytes; - guint8 *encrypted; - gint encrypted_len; - - /* for QQ 2005? copy from lumaqq */ - static const guint8 login_23_51[29] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x86, 0xcc, 0x4c, 0x35, - 0x2c, 0xd3, 0x73, 0x6c, 0x14, 0xf6, 0xf6, 0xaf, - 0xc3, 0xfa, 0x33, 0xa4, 0x01 - }; - - static const guint8 login_53_68[16] = { - 0x8D, 0x8B, 0xFA, 0xEC, 0xD5, 0x52, 0x17, 0x4A, - 0x86, 0xF9, 0xA7, 0x75, 0xE6, 0x32, 0xD1, 0x6D - }; - - static const guint8 login_100_bytes[100] = { - 0x40, 0x0B, 0x04, 0x02, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x03, 0x09, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0xE9, 0x03, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xF3, 0x03, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xED, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0xEC, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0xEE, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, 0xEF, 0x03, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0xEB, 0x03, 0x00, - 0x00, 0x00, 0x00, 0x00 - }; - - g_return_if_fail(gc != NULL && gc->proto_data != NULL); - qd = (qq_data *) gc->proto_data; - - g_return_if_fail(qd->ld.token != NULL && qd->ld.token_len > 0); - - raw_data = g_newa(guint8, MAX_PACKET_SIZE - 17); - memset(raw_data, 0, MAX_PACKET_SIZE - 17); - - encrypted = g_newa(guint8, MAX_PACKET_SIZE); /* 17 bytes more */ - - bytes = 0; - /* now generate the encrypted data - * 000-015 use password_twice_md5 as key to encrypt empty string */ - encrypted_len = qq_encrypt(encrypted, (guint8 *) "", 0, qd->ld.pwd_twice_md5); - g_return_if_fail(encrypted_len == 16); - bytes += qq_putdata(raw_data + bytes, encrypted, encrypted_len); - - /* 016-016 */ - bytes += qq_put8(raw_data + bytes, 0x00); - /* 017-020, used to be IP, now zero */ - bytes += qq_put32(raw_data + bytes, 0x00000000); - /* 021-022, used to be port, now zero */ - bytes += qq_put16(raw_data + bytes, 0x0000); - /* 023-051, fixed value, unknown */ - bytes += qq_putdata(raw_data + bytes, login_23_51, 29); - /* 052-052, login mode */ - bytes += qq_put8(raw_data + bytes, qd->login_mode); - /* 053-068, fixed value, maybe related to per machine */ - bytes += qq_putdata(raw_data + bytes, login_53_68, 16); - /* 069, login token length */ - bytes += qq_put8(raw_data + bytes, qd->ld.token_len); - /* 070-093, login token, normally 24 bytes */ - bytes += qq_putdata(raw_data + bytes, qd->ld.token, qd->ld.token_len); - /* 100 bytes unknown */ - bytes += qq_putdata(raw_data + bytes, login_100_bytes, 100); - /* all zero left */ - memset(raw_data + bytes, 0, 416 - bytes); - bytes = 416; - - encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.random_key); - - buf = g_newa(guint8, MAX_PACKET_SIZE); - memset(buf, 0, MAX_PACKET_SIZE); - bytes = 0; - bytes += qq_putdata(buf + bytes, qd->ld.random_key, QQ_KEY_LENGTH); - bytes += qq_putdata(buf + bytes, encrypted, encrypted_len); - - qd->send_seq++; - qq_send_cmd_encrypted(gc, QQ_CMD_LOGIN, qd->send_seq, buf, bytes, TRUE); -} - -guint8 qq_process_token(PurpleConnection *gc, guint8 *buf, gint buf_len) -{ - qq_data *qd; - gint bytes; - guint8 ret; - guint8 token_len; - gchar *msg; - - g_return_val_if_fail(buf != NULL && buf_len != 0, QQ_LOGIN_REPLY_ERR); - - g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, QQ_LOGIN_REPLY_ERR); - qd = (qq_data *) gc->proto_data; - - bytes = 0; - bytes += qq_get8(&ret, buf + bytes); - bytes += qq_get8(&token_len, buf + bytes); - - if (ret != QQ_LOGIN_REPLY_OK) { - qq_show_packet("Failed requesting token", buf, buf_len); - - msg = g_strdup_printf( _("Failed requesting token, 0x%02X"), ret ); - purple_connection_error_reason(gc, - PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, - msg); - g_free(msg); - return QQ_LOGIN_REPLY_ERR; - } - - if (bytes + token_len < buf_len) { - msg = g_strdup_printf( _("Invalid token len, %d"), token_len); - purple_connection_error_reason(gc, - PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, - msg); - g_free(msg); - return QQ_LOGIN_REPLY_ERR; - } - - if (bytes + token_len > buf_len) { - purple_debug_info("QQ", "Extra token data, %d %d\n", token_len, buf_len - bytes); - } - /* qq_show_packet("Got token", buf + bytes, buf_len - bytes); */ - - if (qd->ld.token != NULL) { - g_free(qd->ld.token); - qd->ld.token = NULL; - qd->ld.token_len = 0; - } - qd->ld.token = g_new0(guint8, token_len); - qd->ld.token_len = token_len; - g_memmove(qd->ld.token, buf + 2, qd->ld.token_len); - return ret; -} - -/* send logout packets to QQ server */ -void qq_request_logout(PurpleConnection *gc) -{ - gint i; - qq_data *qd; - - qd = (qq_data *) gc->proto_data; - for (i = 0; i < 4; i++) - qq_send_cmd(gc, QQ_CMD_LOGOUT, qd->ld.pwd_twice_md5, QQ_KEY_LENGTH); - - qd->is_login = FALSE; /* update login status AFTER sending logout packets */ -} - -/* for QQ 2003iii 0117, fixed value */ -/* static const guint8 login_23_51[29] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xbf, 0x14, 0x11, 0x20, - 0x03, 0x9d, 0xb2, 0xe6, 0xb3, 0x11, 0xb7, 0x13, - 0x95, 0x67, 0xda, 0x2c, 0x01 -}; */ - -/* for QQ 2003iii 0304, fixed value */ -/* -static const guint8 login_23_51[29] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x9a, 0x93, 0xfe, 0x85, - 0xd3, 0xd9, 0x2a, 0x41, 0xc8, 0x0d, 0xff, 0xb6, - 0x40, 0xb8, 0xac, 0x32, 0x01 -}; -*/ - -/* fixed value, not affected by version, or mac address */ -/* -static const guint8 login_53_68[16] = { - 0x82, 0x2a, 0x91, 0xfd, 0xa5, 0xca, 0x67, 0x4c, - 0xac, 0x81, 0x1f, 0x6f, 0x52, 0x05, 0xa7, 0xbf -}; -*/ - -/* process the login reply packet */ -guint8 qq_process_login( PurpleConnection *gc, guint8 *data, gint data_len) -{ - guint8 ret = data[0]; - gchar *msg, *msg_utf8; - gchar *error; - PurpleConnectionError reason = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED; - - g_return_val_if_fail(data != NULL && data_len != 0, QQ_LOGIN_REPLY_ERR); - - switch (ret) { - case QQ_LOGIN_REPLY_OK: - purple_debug_info("QQ", "Login OK\n"); - return process_login_ok(gc, data, data_len); - case QQ_LOGIN_REPLY_REDIRECT: - purple_debug_info("QQ", "Redirect new server\n"); - return process_login_redirect(gc, data, data_len); - - case 0x0A: /* extend redirect used in QQ2006 */ - error = g_strdup( _("Redirect_EX is not currently supported") ); - reason = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED; - break; - case 0x05: /* invalid password */ - if (!purple_account_get_remember_password(gc->account)) { - purple_account_set_password(gc->account, NULL); - } - error = g_strdup( _("Incorrect password")); - reason = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED; - break; - case 0x06: /* need activation */ - error = g_strdup( _("Activation required")); - reason = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED; - break; - - default: - qq_hex_dump(PURPLE_DEBUG_WARNING, "QQ", data, data_len, - ">>> [default] decrypt and dump"); - error = g_strdup_printf( - _("Unknown reply code when logging in (0x%02X)"), - ret ); - reason = PURPLE_CONNECTION_ERROR_OTHER_ERROR; - break; - } - - msg = g_strndup((gchar *)data + 1, data_len - 1); - msg_utf8 = qq_to_utf8(msg, QQ_CHARSET_DEFAULT); - - purple_debug_error("QQ", "%s: %s\n", error, msg_utf8); - purple_connection_error_reason(gc, reason, msg_utf8); - - g_free(error); - g_free(msg); - g_free(msg_utf8); - return QQ_LOGIN_REPLY_ERR; -} - -/* send keep-alive packet to QQ server (it is a heart-beat) */ -void qq_request_keep_alive(PurpleConnection *gc) -{ - qq_data *qd; - guint8 raw_data[16] = {0}; - gint bytes= 0; - - qd = (qq_data *) gc->proto_data; - - /* In fact, we can send whatever we like to server - * with this command, server return the same result including - * the amount of online QQ users, my ip and port */ - bytes += qq_put32(raw_data + bytes, qd->uid); - qq_send_cmd(gc, QQ_CMD_KEEP_ALIVE, raw_data, bytes); -} - -/* parse the return ofqq_process_keep_alive keep-alive packet, it includes some system information */ -gboolean qq_process_keep_alive(guint8 *data, gint data_len, PurpleConnection *gc) -{ - qq_data *qd; - gchar **segments; - - g_return_val_if_fail(data != NULL, FALSE); - g_return_val_if_fail(data_len != 0, FALSE); - - qd = (qq_data *) gc->proto_data; - - /* qq_show_packet("Keep alive reply packet", data, len); */ - - /* the last one is 60, don't know what it is */ - segments = split_data(data, data_len, "\x1f", 6); - if (segments == NULL) - return TRUE; - - /* segments[0] and segment[1] are all 0x30 ("0") */ - qd->online_total = strtol(segments[2], NULL, 10); - if(0 == qd->online_total) { - purple_connection_error_reason(gc, - PURPLE_CONNECTION_ERROR_NETWORK_ERROR, - _("Lost connection with server")); - } - qd->my_ip.s_addr = inet_addr(segments[3]); - qd->my_port = strtol(segments[4], NULL, 10); - - purple_debug_info("QQ", "keep alive, %s:%d\n", - inet_ntoa(qd->my_ip), qd->my_port); - - g_strfreev(segments); - return TRUE; -} - -void qq_request_keep_alive_2007(PurpleConnection *gc) -{ - qq_data *qd; - guint8 raw_data[32] = {0}; - gint bytes= 0; - gchar *uid_str; - - qd = (qq_data *) gc->proto_data; - - /* In fact, we can send whatever we like to server - * with this command, server return the same result including - * the amount of online QQ users, my ip and port */ - uid_str = g_strdup_printf("%u", qd->uid); - bytes += qq_putdata(raw_data + bytes, (guint8 *)uid_str, strlen(uid_str)); - qq_send_cmd(gc, QQ_CMD_KEEP_ALIVE, raw_data, bytes); - - g_free(uid_str); -} - -gboolean qq_process_keep_alive_2007(guint8 *data, gint data_len, PurpleConnection *gc) -{ - qq_data *qd; - gint bytes= 0; - guint8 ret; - - g_return_val_if_fail(data != NULL && data_len != 0, FALSE); - - qd = (qq_data *) gc->proto_data; - - /* qq_show_packet("Keep alive reply packet", data, len); */ - - bytes = 0; - bytes += qq_get8(&ret, data + bytes); - bytes += qq_get32(&qd->online_total, data + bytes); - if(0 == qd->online_total) { - purple_connection_error_reason(gc, - PURPLE_CONNECTION_ERROR_NETWORK_ERROR, - _("Lost connection with server")); - } - - bytes += qq_getIP(&qd->my_ip, data + bytes); - bytes += qq_get16(&qd->my_port, data + bytes); - return TRUE; -} - -void qq_request_keep_alive_2008(PurpleConnection *gc) -{ - qq_data *qd; - guint8 raw_data[16] = {0}; - gint bytes= 0; - - qd = (qq_data *) gc->proto_data; - - /* In fact, we can send whatever we like to server - * with this command, server return the same result including - * the amount of online QQ users, my ip and port */ - bytes += qq_put32(raw_data + bytes, qd->uid); - bytes += qq_putime(raw_data + bytes, &qd->login_time); - qq_send_cmd(gc, QQ_CMD_KEEP_ALIVE, raw_data, bytes); -} - -gboolean qq_process_keep_alive_2008(guint8 *data, gint data_len, PurpleConnection *gc) -{ - qq_data *qd; - gint bytes= 0; - guint8 ret; - time_t server_time; - struct tm *tm_local; - - g_return_val_if_fail(data != NULL && data_len != 0, FALSE); - - qd = (qq_data *) gc->proto_data; - - /* qq_show_packet("Keep alive reply packet", data, len); */ - - bytes = 0; - bytes += qq_get8(&ret, data + bytes); - bytes += qq_get32(&qd->online_total, data + bytes); - if(0 == qd->online_total) { - purple_connection_error_reason(gc, - PURPLE_CONNECTION_ERROR_NETWORK_ERROR, - _("Lost connection with server")); - } - - bytes += qq_getIP(&qd->my_ip, data + bytes); - bytes += qq_get16(&qd->my_port, data + bytes); - /* skip 2 byytes, 0x(00 3c) */ - bytes += 2; - bytes += qq_getime(&server_time, data + bytes); - /* skip 5 bytes, all are 0 */ - - purple_debug_info("QQ", "keep alive, %s:%d\n", - inet_ntoa(qd->my_ip), qd->my_port); - - tm_local = localtime(&server_time); - - if (tm_local != NULL) - purple_debug_info("QQ", "Server time: %d-%d-%d, %d:%d:%d\n", - (1900 +tm_local->tm_year), (1 + tm_local->tm_mon), tm_local->tm_mday, - tm_local->tm_hour, tm_local->tm_min, tm_local->tm_sec); - else - purple_debug_error("QQ", "Server time could not be parsed\n"); - - return TRUE; -} - -/* For QQ2007/2008 */ -void qq_request_get_server(PurpleConnection *gc) -{ - qq_data *qd; - guint8 *buf, *raw_data; - gint bytes; - guint8 *encrypted; - gint encrypted_len; - - g_return_if_fail(gc != NULL && gc->proto_data != NULL); - qd = (qq_data *) gc->proto_data; - - raw_data = g_newa(guint8, 128); - memset(raw_data, 0, 128); - - encrypted = g_newa(guint8, 128 + 17); /* 17 bytes more */ - - bytes = 0; - if (qd->redirect == NULL) { - /* first packet to get server */ - qd->redirect_len = 15; - qd->redirect = g_realloc(qd->redirect, qd->redirect_len); - memset(qd->redirect, 0, qd->redirect_len); - } - bytes += qq_putdata(raw_data + bytes, qd->redirect, qd->redirect_len); - - encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.random_key); - - buf = g_newa(guint8, MAX_PACKET_SIZE); - memset(buf, 0, MAX_PACKET_SIZE); - bytes = 0; - bytes += qq_putdata(buf + bytes, qd->ld.random_key, QQ_KEY_LENGTH); - bytes += qq_putdata(buf + bytes, encrypted, encrypted_len); - - qd->send_seq++; - qq_send_cmd_encrypted(gc, QQ_CMD_GET_SERVER, qd->send_seq, buf, bytes, TRUE); -} - -guint16 qq_process_get_server(PurpleConnection *gc, guint8 *data, gint data_len) -{ - qq_data *qd; - gint bytes; - guint16 ret; - - g_return_val_if_fail (gc != NULL && gc->proto_data != NULL, QQ_LOGIN_REPLY_ERR); - qd = (qq_data *) gc->proto_data; - - g_return_val_if_fail (data != NULL, QQ_LOGIN_REPLY_ERR); - - /* qq_show_packet("Get Server", data, data_len); */ - bytes = 0; - bytes += qq_get16(&ret, data + bytes); - if (ret == 0) { - /* Notice: do not clear redirect_data here. It will be used in login*/ - qd->redirect_ip.s_addr = 0; - return QQ_LOGIN_REPLY_OK; - } - - if (data_len < 15) { - purple_connection_error_reason(gc, - PURPLE_CONNECTION_ERROR_ENCRYPTION_ERROR, - _("Unable to decrypt server reply")); - return QQ_LOGIN_REPLY_ERR; - } - - qd->redirect_len = data_len; - qd->redirect = g_realloc(qd->redirect, qd->redirect_len); - qq_getdata(qd->redirect, qd->redirect_len, data); - /* qq_show_packet("Redirect to", qd->redirect, qd->redirect_len); */ - - qq_getIP(&qd->redirect_ip, data + 11); - purple_debug_info("QQ", "Get server %s\n", inet_ntoa(qd->redirect_ip)); - return QQ_LOGIN_REPLY_REDIRECT; -} - -void qq_request_token_ex(PurpleConnection *gc) -{ - qq_data *qd; - guint8 *buf, *raw_data; - gint bytes; - guint8 *encrypted; - gint encrypted_len; - - g_return_if_fail(gc != NULL && gc->proto_data != NULL); - qd = (qq_data *) gc->proto_data; - - g_return_if_fail(qd->ld.token != NULL && qd->ld.token_len > 0); - - raw_data = g_newa(guint8, MAX_PACKET_SIZE - 17); - memset(raw_data, 0, MAX_PACKET_SIZE - 17); - - encrypted = g_newa(guint8, MAX_PACKET_SIZE); /* 17 bytes more */ - - bytes = 0; - bytes += qq_put8(raw_data + bytes, qd->ld.token_len); - bytes += qq_putdata(raw_data + bytes, qd->ld.token, qd->ld.token_len); - bytes += qq_put8(raw_data + bytes, 3); /* Subcommand */ - bytes += qq_put16(raw_data + bytes, 5); - bytes += qq_put32(raw_data + bytes, 0); - bytes += qq_put8(raw_data + bytes, 0); /* fragment index */ - bytes += qq_put16(raw_data + bytes, 0); /* captcha token */ - - encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.random_key); - - buf = g_newa(guint8, MAX_PACKET_SIZE); - memset(buf, 0, MAX_PACKET_SIZE); - bytes = 0; - bytes += qq_putdata(buf + bytes, qd->ld.random_key, QQ_KEY_LENGTH); - bytes += qq_putdata(buf + bytes, encrypted, encrypted_len); - - qd->send_seq++; - qq_send_cmd_encrypted(gc, QQ_CMD_TOKEN_EX, qd->send_seq, buf, bytes, TRUE); -} - -void qq_request_token_ex_next(PurpleConnection *gc) -{ - qq_data *qd; - guint8 *buf, *raw_data; - gint bytes; - guint8 *encrypted; - gint encrypted_len; - - g_return_if_fail(gc != NULL && gc->proto_data != NULL); - qd = (qq_data *) gc->proto_data; - - g_return_if_fail(qd->ld.token != NULL && qd->ld.token_len > 0); - - raw_data = g_newa(guint8, MAX_PACKET_SIZE - 17); - memset(raw_data, 0, MAX_PACKET_SIZE - 17); - - encrypted = g_newa(guint8, MAX_PACKET_SIZE); /* 17 bytes more */ - - bytes = 0; - bytes += qq_put8(raw_data + bytes, qd->ld.token_len); - bytes += qq_putdata(raw_data + bytes, qd->ld.token, qd->ld.token_len); - bytes += qq_put8(raw_data + bytes, 3); /* Subcommand */ - bytes += qq_put16(raw_data + bytes, 5); - bytes += qq_put32(raw_data + bytes, 0); - bytes += qq_put8(raw_data + bytes, qd->captcha.next_index); /* fragment index */ - bytes += qq_put16(raw_data + bytes, qd->captcha.token_len); /* captcha token */ - bytes += qq_putdata(raw_data + bytes, qd->captcha.token, qd->captcha.token_len); - - encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.random_key); - - buf = g_newa(guint8, MAX_PACKET_SIZE); - memset(buf, 0, MAX_PACKET_SIZE); - bytes = 0; - bytes += qq_putdata(buf + bytes, qd->ld.random_key, QQ_KEY_LENGTH); - bytes += qq_putdata(buf + bytes, encrypted, encrypted_len); - - qd->send_seq++; - qq_send_cmd_encrypted(gc, QQ_CMD_TOKEN_EX, qd->send_seq, buf, bytes, TRUE); - - purple_connection_update_progress(gc, _("Requesting captcha"), 3, QQ_CONNECT_STEPS); -} - -static void request_token_ex_code(PurpleConnection *gc, - guint8 *token, guint16 token_len, guint8 *code, guint16 code_len) -{ - qq_data *qd; - guint8 *buf, *raw_data; - gint bytes; - guint8 *encrypted; - gint encrypted_len; - - g_return_if_fail(gc != NULL && gc->proto_data != NULL); - qd = (qq_data *) gc->proto_data; - - g_return_if_fail(qd->ld.token != NULL && qd->ld.token_len > 0); - g_return_if_fail(code != NULL && code_len > 0); - - raw_data = g_newa(guint8, MAX_PACKET_SIZE - 17); - memset(raw_data, 0, MAX_PACKET_SIZE - 17); - - encrypted = g_newa(guint8, MAX_PACKET_SIZE); /* 17 bytes more */ - - bytes = 0; - bytes += qq_put8(raw_data + bytes, qd->ld.token_len); - bytes += qq_putdata(raw_data + bytes, qd->ld.token, qd->ld.token_len); - bytes += qq_put8(raw_data + bytes, 4); /* Subcommand */ - bytes += qq_put16(raw_data + bytes, 5); - bytes += qq_put32(raw_data + bytes, 0); - bytes += qq_put16(raw_data + bytes, code_len); - bytes += qq_putdata(raw_data + bytes, code, code_len); - bytes += qq_put16(raw_data + bytes, qd->ld.token_ex_len); /* login token ex */ - bytes += qq_putdata(raw_data + bytes, qd->ld.token_ex, qd->ld.token_ex_len); - - encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.random_key); - - buf = g_newa(guint8, MAX_PACKET_SIZE); - memset(buf, 0, MAX_PACKET_SIZE); - bytes = 0; - bytes += qq_putdata(buf + bytes, qd->ld.random_key, QQ_KEY_LENGTH); - bytes += qq_putdata(buf + bytes, encrypted, encrypted_len); - - qd->send_seq++; - qq_send_cmd_encrypted(gc, QQ_CMD_TOKEN_EX, qd->send_seq, buf, bytes, TRUE); - - purple_connection_update_progress(gc, _("Checking captcha"), 3, QQ_CONNECT_STEPS); -} - -typedef struct { - PurpleConnection *gc; - guint8 *token; - guint16 token_len; -} qq_captcha_request; - -static void captcha_request_destory(qq_captcha_request *captcha_req) -{ - g_return_if_fail(captcha_req != NULL); - if (captcha_req->token) g_free(captcha_req->token); - g_free(captcha_req); -} - -static void captcha_input_cancel_cb(qq_captcha_request *captcha_req, - PurpleRequestFields *fields) -{ - purple_connection_error_reason(captcha_req->gc, - PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, - _("Failed captcha verification")); - - captcha_request_destory(captcha_req); -} - -static void captcha_input_ok_cb(qq_captcha_request *captcha_req, - PurpleRequestFields *fields) -{ - gchar *code; - - g_return_if_fail(captcha_req != NULL && captcha_req->gc != NULL); - - code = utf8_to_qq( - purple_request_fields_get_string(fields, "captcha_code"), - QQ_CHARSET_DEFAULT); - - if (strlen(code) <= 0) { - captcha_input_cancel_cb(captcha_req, fields); - return; - } - - request_token_ex_code(captcha_req->gc, - captcha_req->token, captcha_req->token_len, - (guint8 *)code, strlen(code)); - - captcha_request_destory(captcha_req); -} - -void qq_captcha_input_dialog(PurpleConnection *gc,qq_captcha_data *captcha) -{ - PurpleAccount *account; - PurpleRequestFields *fields; - PurpleRequestFieldGroup *group; - PurpleRequestField *field; - qq_captcha_request *captcha_req; - - g_return_if_fail(captcha->token != NULL && captcha->token_len > 0); - g_return_if_fail(captcha->data != NULL && captcha->data_len > 0); - - captcha_req = g_new0(qq_captcha_request, 1); - captcha_req->gc = gc; - captcha_req->token = g_new0(guint8, captcha->token_len); - g_memmove(captcha_req->token, captcha->token, captcha->token_len); - captcha_req->token_len = captcha->token_len; - - account = purple_connection_get_account(gc); - - fields = purple_request_fields_new(); - group = purple_request_field_group_new(NULL); - purple_request_fields_add_group(fields, group); - - field = purple_request_field_image_new("captcha_img", - _("Captcha Image"), (char *)captcha->data, captcha->data_len); - purple_request_field_group_add_field(group, field); - - field = purple_request_field_string_new("captcha_code", - _("Enter code"), "", FALSE); - purple_request_field_string_set_masked(field, FALSE); - purple_request_field_group_add_field(group, field); - - purple_request_fields(account, - _("QQ Captcha Verification"), - _("QQ Captcha Verification"), - _("Enter the text from the image"), - fields, - _("OK"), G_CALLBACK(captcha_input_ok_cb), - _("Cancel"), G_CALLBACK(captcha_input_cancel_cb), - purple_connection_get_account(gc), NULL, NULL, - captcha_req); -} - -guint8 qq_process_token_ex(PurpleConnection *gc, guint8 *data, gint data_len) -{ - qq_data *qd; - int bytes; - guint8 ret; - guint8 sub_cmd; - guint8 reply; - guint16 captcha_len; - guint8 curr_index; - - g_return_val_if_fail(data != NULL && data_len != 0, QQ_LOGIN_REPLY_ERR); - - g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, QQ_LOGIN_REPLY_ERR); - qd = (qq_data *) gc->proto_data; - - ret = data[0]; - - bytes = 0; - bytes += qq_get8(&sub_cmd, data + bytes); /* 03: ok; 04: need verifying */ - bytes += 2; /* 0x(00 05) */ - bytes += qq_get8(&reply, data + bytes); - - bytes += qq_get16(&(qd->ld.token_ex_len), data + bytes); - qd->ld.token_ex = g_realloc(qd->ld.token_ex, qd->ld.token_ex_len); - bytes += qq_getdata(qd->ld.token_ex, qd->ld.token_ex_len, data + bytes); - /* qq_show_packet("Get token ex", qd->ld.token_ex, qd->ld.token_ex_len); */ - - if(reply != 1) - { - purple_debug_info("QQ", "Captcha verified, result %d\n", reply); - return QQ_LOGIN_REPLY_OK; - } - - bytes += qq_get16(&captcha_len, data + bytes); - - qd->captcha.data = g_realloc(qd->captcha.data, qd->captcha.data_len + captcha_len); - bytes += qq_getdata(qd->captcha.data + qd->captcha.data_len, captcha_len, data + bytes); - qd->captcha.data_len += captcha_len; - - bytes += qq_get8(&curr_index, data + bytes); - bytes += qq_get8(&qd->captcha.next_index, data + bytes); - - bytes += qq_get16(&qd->captcha.token_len, data + bytes); - qd->captcha.token = g_realloc(qd->captcha.token, qd->captcha.token_len); - bytes += qq_getdata(qd->captcha.token, qd->captcha.token_len, data + bytes); - /* qq_show_packet("Get captcha token", qd->captcha.token, qd->captcha.token_len); */ - - purple_debug_info("QQ", "Request next captcha %d, new %d, total %d\n", - qd->captcha.next_index, captcha_len, qd->captcha.data_len); - if(qd->captcha.next_index > 0) - { - return QQ_LOGIN_REPLY_NEXT_TOKEN_EX; - } - - return QQ_LOGIN_REPLY_CAPTCHA_DLG; -} - -/* source copy from gg's common.c */ -static guint32 crc32_table[256]; -static int crc32_initialized = 0; - -static void crc32_make_table() -{ - guint32 h = 1; - unsigned int i, j; - - memset(crc32_table, 0, sizeof(crc32_table)); - - for (i = 128; i; i >>= 1) { - h = (h >> 1) ^ ((h & 1) ? 0xedb88320L : 0); - - for (j = 0; j < 256; j += 2 * i) - crc32_table[i + j] = crc32_table[j] ^ h; - } - - crc32_initialized = 1; -} - -static guint32 crc32(guint32 crc, const guint8 *buf, int len) -{ - if (!crc32_initialized) - crc32_make_table(); - - if (!buf || len < 0) - return crc; - - crc ^= 0xffffffffL; - - while (len--) - crc = (crc >> 8) ^ crc32_table[(crc ^ *buf++) & 0xff]; - - return crc ^ 0xffffffffL; -} - -void qq_request_check_pwd(PurpleConnection *gc) -{ - qq_data *qd; - guint8 *buf, *raw_data; - gint bytes; - guint8 *encrypted; - gint encrypted_len; - static guint8 header[] = { - 0x00, 0x5F, 0x00, 0x00, 0x08, 0x04, 0x01, 0xE0 - }; - static guint8 unknown[] = { - 0xDB, 0xB9, 0xF3, 0x0B, 0xF9, 0x13, 0x87, 0xB2, - 0xE6, 0x20, 0x43, 0xBE, 0x53, 0xCA, 0x65, 0x03 - }; - - g_return_if_fail(gc != NULL && gc->proto_data != NULL); - qd = (qq_data *) gc->proto_data; - - g_return_if_fail(qd->ld.token_ex != NULL && qd->ld.token_ex_len > 0); - - raw_data = g_newa(guint8, MAX_PACKET_SIZE - 17); - memset(raw_data, 0, MAX_PACKET_SIZE - 17); - - encrypted = g_newa(guint8, MAX_PACKET_SIZE); /* 17 bytes more */ - - /* Encrypted password and put in encrypted */ - bytes = 0; - bytes += qq_putdata(raw_data + bytes, qd->ld.pwd_md5, sizeof(qd->ld.pwd_md5)); - bytes += qq_put16(raw_data + bytes, 0); - bytes += qq_put16(raw_data + bytes, rand() & 0xffff); - - encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.pwd_twice_md5); - - /* create packet */ - bytes = 0; - bytes += qq_putdata(raw_data + bytes, header, sizeof(header)); - /* token get from qq_request_token_ex */ - bytes += qq_put8(raw_data + bytes, (guint8)(qd->ld.token_ex_len & 0xff)); - bytes += qq_putdata(raw_data + bytes, qd->ld.token_ex, qd->ld.token_ex_len); - /* password encrypted */ - bytes += qq_put16(raw_data + bytes, encrypted_len); - bytes += qq_putdata(raw_data + bytes, encrypted, encrypted_len); - /* len of unknown + len of CRC32 */ - bytes += qq_put16(raw_data + bytes, sizeof(unknown) + 4); - bytes += qq_putdata(raw_data + bytes, unknown, sizeof(unknown)); - bytes += qq_put32( - raw_data + bytes, crc32(0xFFFFFFFF, unknown, sizeof(unknown))); - - /* put length into first 2 bytes */ - qq_put8(raw_data + 1, bytes - 2); - - /* tail */ - bytes += qq_put16(raw_data + bytes, 0x0003); - bytes += qq_put8(raw_data + bytes, 0); - bytes += qq_put8(raw_data + bytes, qd->ld.pwd_md5[1]); - bytes += qq_put8(raw_data + bytes, qd->ld.pwd_md5[2]); - - /* qq_show_packet("Check password", raw_data, bytes); */ - /* Encrypted by random key*/ - encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.random_key); - - buf = g_newa(guint8, MAX_PACKET_SIZE); - memset(buf, 0, MAX_PACKET_SIZE); - bytes = 0; - bytes += qq_putdata(buf + bytes, qd->ld.random_key, QQ_KEY_LENGTH); - bytes += qq_putdata(buf + bytes, encrypted, encrypted_len); - - qd->send_seq++; - qq_send_cmd_encrypted(gc, QQ_CMD_CHECK_PWD, qd->send_seq, buf, bytes, TRUE); -} - -guint8 qq_process_check_pwd( PurpleConnection *gc, guint8 *data, gint data_len) -{ - qq_data *qd; - int bytes; - guint8 ret; - gchar *error = NULL; - guint16 unknow_token_len; - gchar *msg, *msg_utf8; - guint16 msg_len; - PurpleConnectionError reason = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED; - - g_return_val_if_fail(data != NULL && data_len != 0, QQ_LOGIN_REPLY_ERR); - - g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, QQ_LOGIN_REPLY_ERR); - qd = (qq_data *) gc->proto_data; - - /* qq_show_packet("Check password reply", data, data_len); */ - - bytes = 0; - bytes += qq_get16(&unknow_token_len, data + bytes); /* maybe total length */ - bytes += qq_get8(&ret, data + bytes); - bytes += 4; /* 0x(00 00 6d b9) */ - /* unknow_token_len may 0 when not reply ok*/ - bytes += qq_get16(&unknow_token_len, data + bytes); /* 0x0020 */ - bytes += unknow_token_len; - bytes += qq_get16(&unknow_token_len, data + bytes); /* 0x0020 */ - bytes += unknow_token_len; - - if (ret == 0) { - /* get login_token */ - bytes += qq_get16(&qd->ld.login_token_len, data + bytes); - if (qd->ld.login_token != NULL) g_free(qd->ld.login_token); - qd->ld.login_token = g_new0(guint8, qd->ld.login_token_len); - bytes += qq_getdata(qd->ld.login_token, qd->ld.login_token_len, data + bytes); - /* qq_show_packet("Get login token", qd->ld.login_token, qd->ld.login_token_len); */ - - /* get login_key */ - bytes += qq_getdata(qd->ld.login_key, sizeof(qd->ld.login_key), data + bytes); - /* qq_show_packet("Get login key", qd->ld.login_key, sizeof(qd->ld.login_key)); */ - return QQ_LOGIN_REPLY_OK; - } - - switch (ret) - { - case 0x34: /* invalid password */ - if (!purple_account_get_remember_password(gc->account)) { - purple_account_set_password(gc->account, NULL); - } - error = g_strdup(_("Incorrect password")); - reason = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED; - break; - case 0x33: /* need activation */ - case 0x51: /* need activation */ - error = g_strdup(_("Activation required")); - reason = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED; - break; - case 0xBF: /* uid is not exist */ - error = g_strdup(_("Username does not exist")); - reason = PURPLE_CONNECTION_ERROR_INVALID_USERNAME; - break; - default: - qq_hex_dump(PURPLE_DEBUG_WARNING, "QQ", data, data_len, - ">>> [default] decrypt and dump"); - error = g_strdup_printf( - _("Unknown reply when checking password (0x%02X)"), - ret ); - reason = PURPLE_CONNECTION_ERROR_OTHER_ERROR; - break; - } - - bytes += qq_get16(&msg_len, data + bytes); - - msg = g_strndup((gchar *)data + bytes, msg_len); - msg_utf8 = qq_to_utf8(msg, QQ_CHARSET_DEFAULT); - - purple_debug_error("QQ", "%s: %s\n", error, msg_utf8); - purple_connection_error_reason(gc, reason, msg_utf8); - - g_free(error); - g_free(msg); - g_free(msg_utf8); - return QQ_LOGIN_REPLY_ERR; -} - -void qq_request_login_2007(PurpleConnection *gc) -{ - qq_data *qd; - guint8 *buf, *raw_data; - gint bytes; - guint8 *encrypted; - gint encrypted_len; - static const guint8 login_1_16[] = { - 0x56, 0x4E, 0xC8, 0xFB, 0x0A, 0x4F, 0xEF, 0xB3, - 0x7A, 0x5D, 0xD8, 0x86, 0x0F, 0xAC, 0xE5, 0x1A - }; - static const guint8 login_2_16[] = { - 0x5E, 0x22, 0x3A, 0xBE, 0x13, 0xBF, 0xDA, 0x4C, - 0xA9, 0xB7, 0x0B, 0x43, 0x63, 0x51, 0x8E, 0x28 - }; - static const guint8 login_3_83[] = { - 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x40, 0x01, 0x01, 0x58, 0x83, - 0xD0, 0x00, 0x10, 0x9D, 0x14, 0x64, 0x0A, 0x2E, - 0xE2, 0x11, 0xF7, 0x90, 0xF0, 0xB5, 0x5F, 0x16, - 0xFB, 0x41, 0x5D, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x76, 0x3C, 0xEE, - 0x4A, 0x00, 0x10, 0x86, 0x81, 0xAD, 0x1F, 0xC8, - 0xC9, 0xCC, 0xCF, 0xCA, 0x9F, 0xFF, 0x88, 0xC0, - 0x5C, 0x88, 0xD5 - }; - g_return_if_fail(gc != NULL && gc->proto_data != NULL); - qd = (qq_data *) gc->proto_data; - - g_return_if_fail(qd->ld.token != NULL && qd->ld.token_len > 0); - - raw_data = g_newa(guint8, MAX_PACKET_SIZE - 17); - memset(raw_data, 0, MAX_PACKET_SIZE - 17); - - encrypted = g_newa(guint8, MAX_PACKET_SIZE); /* 17 bytes more */ - - /* Encrypted password and put in encrypted */ - bytes = 0; - bytes += qq_putdata(raw_data + bytes, qd->ld.pwd_md5, sizeof(qd->ld.pwd_md5)); - bytes += qq_put16(raw_data + bytes, 0); - bytes += qq_put16(raw_data + bytes, 0xffff); - - encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.pwd_twice_md5); - - /* create packet */ - bytes = 0; - bytes += qq_put16(raw_data + bytes, 0); /* Unknow */ - /* password encrypted */ - bytes += qq_put16(raw_data + bytes, encrypted_len); - bytes += qq_putdata(raw_data + bytes, encrypted, encrypted_len); - /* put data which NULL string encrypted by key pwd_twice_md5 */ - encrypted_len = qq_encrypt(encrypted, (guint8 *) "", 0, qd->ld.pwd_twice_md5); - g_return_if_fail(encrypted_len == 16); - bytes += qq_putdata(raw_data + bytes, encrypted, encrypted_len); - /* unknow fill 0 */ - memset(raw_data + bytes, 0, 19); - bytes += 19; - bytes += qq_putdata(raw_data + bytes, login_1_16, sizeof(login_1_16)); - - bytes += qq_put8(raw_data + bytes, rand() & 0xff); - bytes += qq_put8(raw_data + bytes, qd->login_mode); - /* unknow 10 bytes zero filled*/ - memset(raw_data + bytes, 0, 10); - bytes += 10; - /* redirect data, 15 bytes */ - /* qq_show_packet("Redirect", qd->redirect, qd->redirect_len); */ - bytes += qq_putdata(raw_data + bytes, qd->redirect, qd->redirect_len); - /* unknow fill */ - bytes += qq_putdata(raw_data + bytes, login_2_16, sizeof(login_2_16)); - /* captcha token get from qq_process_token_ex */ - bytes += qq_put8(raw_data + bytes, (guint8)(qd->ld.token_ex_len & 0xff)); - bytes += qq_putdata(raw_data + bytes, qd->ld.token_ex, qd->ld.token_ex_len); - /* unknow fill */ - bytes += qq_putdata(raw_data + bytes, login_3_83, sizeof(login_3_83)); - memset(raw_data + bytes, 0, 332 - sizeof(login_3_83)); - bytes += 332 - sizeof(login_3_83); - - /* qq_show_packet("Login", raw_data, bytes); */ - - encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.login_key); - - buf = g_newa(guint8, MAX_PACKET_SIZE); - memset(buf, 0, MAX_PACKET_SIZE); - bytes = 0; - /* logint token get from qq_process_check_pwd_2007 */ - bytes += qq_put16(buf + bytes, qd->ld.login_token_len); - bytes += qq_putdata(buf + bytes, qd->ld.login_token, qd->ld.login_token_len); - bytes += qq_putdata(buf + bytes, encrypted, encrypted_len); - - qd->send_seq++; - qq_send_cmd_encrypted(gc, QQ_CMD_LOGIN, qd->send_seq, buf, bytes, TRUE); -} - -/* process the login reply packet */ -guint8 qq_process_login_2007( PurpleConnection *gc, guint8 *data, gint data_len) -{ - qq_data *qd; - gint bytes; - guint8 ret; - UID uid; - gchar *error; - gchar *msg; - gchar *msg_utf8; - - g_return_val_if_fail(data != NULL && data_len != 0, QQ_LOGIN_REPLY_ERR); - - qd = (qq_data *) gc->proto_data; - - bytes = 0; - bytes += qq_get8(&ret, data + bytes); - if (ret != 0) { - msg = g_strndup((gchar *)data + bytes, data_len - bytes); - msg_utf8 = qq_to_utf8(msg, QQ_CHARSET_DEFAULT); - g_free(msg); - - switch (ret) { - case 0x05: - purple_debug_error("QQ", "Server busy for %s\n", msg_utf8); - return QQ_LOGIN_REPLY_REDIRECT; - case 0x0A: - /* 0a 2d 9a 4b 9a 01 01 00 00 00 05 00 00 00 00 79 0e 5f fd */ - /* Missing get server before login*/ - default: - error = g_strdup_printf( - _("Unknown reply code when logging in (0x%02X):\n%s"), - ret, msg_utf8); - break; - } - - purple_debug_error("QQ", "%s\n", error); - purple_connection_error_reason(gc, - PURPLE_CONNECTION_ERROR_OTHER_ERROR, - error); - - qq_hex_dump(PURPLE_DEBUG_WARNING, "QQ", data, data_len, error); - - g_free(error); - g_free(msg_utf8); - return QQ_LOGIN_REPLY_ERR; - } - - bytes += qq_getdata(qd->session_key, sizeof(qd->session_key), data + bytes); - purple_debug_info("QQ", "Got session_key\n"); - get_session_md5(qd->session_md5, qd->uid, qd->session_key); - - bytes += qq_get32(&uid, data + bytes); - if (uid != qd->uid) { - purple_debug_warning("QQ", "My uid in login reply is %u, not %u\n", uid, qd->uid); - } - bytes += qq_getIP(&qd->my_ip, data + bytes); - bytes += qq_get16(&qd->my_port, data + bytes); - bytes += qq_getIP(&qd->my_local_ip, data + bytes); - bytes += qq_get16(&qd->my_local_port, data + bytes); - bytes += qq_getime(&qd->login_time, data + bytes); - /* skip unknow 50 byte */ - bytes += 50; - /* skip client key 32 byte */ - bytes += 32; - /* skip unknow 12 byte */ - bytes += 12; - /* last login */ - bytes += qq_getIP(&qd->last_login_ip, data + bytes); - bytes += qq_getime(&qd->last_login_time[0], data + bytes); - purple_debug_info("QQ", "Last Login: %s, %s\n", - inet_ntoa(qd->last_login_ip), ctime(&qd->last_login_time[0])); - return QQ_LOGIN_REPLY_OK; -} - -void qq_request_login_2008(PurpleConnection *gc) -{ - qq_data *qd; - guint8 *buf, *raw_data; - gint bytes; - guint8 *encrypted; - gint encrypted_len; - guint8 index, count; - - static const guint8 login_1_16[] = { - 0xD2, 0x41, 0x75, 0x12, 0xC2, 0x86, 0x57, 0x10, - 0x78, 0x57, 0xDC, 0x24, 0x8C, 0xAA, 0x8F, 0x4E - }; - - static const guint8 login_2_16[] = { - 0x94, 0x0B, 0x73, 0x7A, 0xA2, 0x51, 0xF0, 0x4B, - 0x95, 0x2F, 0xC6, 0x0A, 0x5B, 0xF6, 0x76, 0x52 - }; - static const guint8 login_3_18[] = { - 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x40, 0x01, 0x1b, 0x02, 0x84, - 0x50, 0x00 - }; - static const guint8 login_4_16[] = { - 0x2D, 0x49, 0x15, 0x55, 0x78, 0xFC, 0xF3, 0xD4, - 0x53, 0x55, 0x60, 0x9C, 0x37, 0x9F, 0xE9, 0x59 - }; - static const guint8 login_5_6[] = { - 0x02, 0x68, 0xe8, 0x07, 0x83, 0x00 - }; - static const guint8 login_6_16[] = { - 0x3B, 0xCE, 0x43, 0xF1, 0x8B, 0xA4, 0x2B, 0xB5, - 0xB3, 0x51, 0x57, 0xF7, 0x06, 0x4B, 0x18, 0xFC - }; - g_return_if_fail(gc != NULL && gc->proto_data != NULL); - qd = (qq_data *) gc->proto_data; - - g_return_if_fail(qd->ld.token != NULL && qd->ld.token_len > 0); - - raw_data = g_newa(guint8, MAX_PACKET_SIZE - 17); - memset(raw_data, 0, MAX_PACKET_SIZE - 17); - - encrypted = g_newa(guint8, MAX_PACKET_SIZE); /* 17 bytes more */ - - /* Encrypted password and put in encrypted */ - bytes = 0; - bytes += qq_putdata(raw_data + bytes, qd->ld.pwd_md5, sizeof(qd->ld.pwd_md5)); - bytes += qq_put16(raw_data + bytes, 0); - bytes += qq_put16(raw_data + bytes, 0xffff); - - encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.pwd_twice_md5); - - /* create packet */ - bytes = 0; - bytes += qq_put16(raw_data + bytes, 0); /* Unknow */ - /* password encrypted */ - bytes += qq_put16(raw_data + bytes, encrypted_len); - bytes += qq_putdata(raw_data + bytes, encrypted, encrypted_len); - /* put data which NULL string encrypted by key pwd_twice_md5 */ - encrypted_len = qq_encrypt(encrypted, (guint8 *) "", 0, qd->ld.pwd_twice_md5); - g_return_if_fail(encrypted_len == 16); - bytes += qq_putdata(raw_data + bytes, encrypted, encrypted_len); - /* unknow 19 bytes zero filled*/ - memset(raw_data + bytes, 0, 19); - bytes += 19; - bytes += qq_putdata(raw_data + bytes, login_1_16, sizeof(login_1_16)); - - index = rand() % 3; /* can be set as 1 */ - for( count = 0; count < encrypted_len; count++ ) - index ^= encrypted[count]; - for( count = 0; count < sizeof(login_1_16); count++ ) - index ^= login_1_16[count]; - bytes += qq_put8(raw_data + bytes, index); /* random in QQ 2007*/ - - bytes += qq_put8(raw_data + bytes, qd->login_mode); - /* unknow 10 bytes zero filled*/ - memset(raw_data + bytes, 0, 10); - bytes += 10; - /* redirect data, 15 bytes */ - bytes += qq_putdata(raw_data + bytes, qd->redirect, qd->redirect_len); - /* unknow fill */ - bytes += qq_putdata(raw_data + bytes, login_2_16, sizeof(login_2_16)); - /* captcha token get from qq_process_token_ex */ - bytes += qq_put8(raw_data + bytes, (guint8)(qd->ld.token_ex_len & 0xff)); - bytes += qq_putdata(raw_data + bytes, qd->ld.token_ex, qd->ld.token_ex_len); - /* unknow fill */ - bytes += qq_putdata(raw_data + bytes, login_3_18, sizeof(login_3_18)); - bytes += qq_put8(raw_data + bytes , sizeof(login_4_16)); - bytes += qq_putdata(raw_data + bytes, login_4_16, sizeof(login_4_16)); - /* unknow 10 bytes zero filled*/ - memset(raw_data + bytes, 0, 10); - bytes += 10; - /* redirect data, 15 bytes */ - bytes += qq_putdata(raw_data + bytes, qd->redirect, qd->redirect_len); - /* unknow fill */ - bytes += qq_putdata(raw_data + bytes, login_5_6, sizeof(login_5_6)); - bytes += qq_put8(raw_data + bytes , sizeof(login_6_16)); - bytes += qq_putdata(raw_data + bytes, login_6_16, sizeof(login_6_16)); - /* unknow 249 bytes zero filled*/ - memset(raw_data + bytes, 0, 249); - bytes += 249; - - /* qq_show_packet("Login request", raw_data, bytes); */ - encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.login_key); - - buf = g_newa(guint8, MAX_PACKET_SIZE); - memset(buf, 0, MAX_PACKET_SIZE); - bytes = 0; - /* logint token get from qq_process_check_pwd_2007 */ - bytes += qq_put16(buf + bytes, qd->ld.login_token_len); - bytes += qq_putdata(buf + bytes, qd->ld.login_token, qd->ld.login_token_len); - bytes += qq_putdata(buf + bytes, encrypted, encrypted_len); - - qd->send_seq++; - qq_send_cmd_encrypted(gc, QQ_CMD_LOGIN, qd->send_seq, buf, bytes, TRUE); -} - -guint8 qq_process_login_2008( PurpleConnection *gc, guint8 *data, gint data_len) -{ - qq_data *qd; - gint bytes; - guint8 ret; - UID uid; - gchar *error; - gchar *msg; - gchar *msg_utf8; - - g_return_val_if_fail(data != NULL && data_len != 0, QQ_LOGIN_REPLY_ERR); - - qd = (qq_data *) gc->proto_data; - - bytes = 0; - bytes += qq_get8(&ret, data + bytes); - if (ret != 0) { - msg = g_strndup((gchar *)data + bytes, data_len - bytes); - msg_utf8 = qq_to_utf8(msg, QQ_CHARSET_DEFAULT); - g_free(msg); - - switch (ret) { - case 0x05: - purple_debug_error("QQ", "Server busy for %s\n", msg_utf8); - return QQ_LOGIN_REPLY_REDIRECT; - break; - default: - error = g_strdup_printf( - _("Unknown reply code when logging in (0x%02X):\n%s"), - ret, msg_utf8); - break; - } - - purple_debug_error("QQ", "%s\n", error); - purple_connection_error_reason(gc, - PURPLE_CONNECTION_ERROR_OTHER_ERROR, - error); - - qq_hex_dump(PURPLE_DEBUG_WARNING, "QQ", data, data_len, error); - - g_free(error); - g_free(msg_utf8); - return QQ_LOGIN_REPLY_ERR; - } - - bytes += qq_getdata(qd->session_key, sizeof(qd->session_key), data + bytes); - purple_debug_info("QQ", "Got session_key\n"); - get_session_md5(qd->session_md5, qd->uid, qd->session_key); - - bytes += qq_get32(&uid, data + bytes); - if (uid != qd->uid) { - purple_debug_warning("QQ", "My uid in login reply is %u, not %u\n", uid, qd->uid); - } - bytes += qq_getIP(&qd->my_ip, data + bytes); - bytes += qq_get16(&qd->my_port, data + bytes); - bytes += qq_getIP(&qd->my_local_ip, data + bytes); - bytes += qq_get16(&qd->my_local_port, data + bytes); - bytes += qq_getime(&qd->login_time, data + bytes); - /* skip 1 byte, always 0x03 */ - /* skip 1 byte, login mode */ - bytes = 131; - bytes += qq_getIP(&qd->last_login_ip, data + bytes); - bytes += qq_getime(&qd->last_login_time[0], data + bytes); - purple_debug_info("QQ", "Last Login: %s, %s\n", - inet_ntoa(qd->last_login_ip), ctime(&qd->last_login_time[0])); - return QQ_LOGIN_REPLY_OK; -} diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/qq/qq_base.h --- a/libpurple/protocols/qq/qq_base.h Thu May 05 03:40:29 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,79 +0,0 @@ -/** - * file qq_base.h - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * 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 02111-1301 USA - */ - -#ifndef _QQ_BASE_H_ -#define _QQ_BASE_H_ - -#include -#include "connection.h" - -#define QQ_LOGIN_REPLY_OK 0x00 -#define QQ_LOGIN_REPLY_REDIRECT 0x01 -/* defined by myself */ -#define QQ_LOGIN_REPLY_CAPTCHA_DLG 0xfd -#define QQ_LOGIN_REPLY_NEXT_TOKEN_EX 0xfe -#define QQ_LOGIN_REPLY_ERR 0xff - -#define QQ_LOGIN_MODE_NORMAL 0x0a -#define QQ_LOGIN_MODE_AWAY 0x1e -#define QQ_LOGIN_MODE_HIDDEN 0x28 - -#define QQ_UPDATE_ONLINE_INTERVAL 300 /* in sec */ - -void qq_request_token(PurpleConnection *gc); -guint8 qq_process_token(PurpleConnection *gc, guint8 *buf, gint buf_len); - -void qq_request_login(PurpleConnection *gc); -guint8 qq_process_login( PurpleConnection *gc, guint8 *data, gint data_len); - -void qq_request_logout(PurpleConnection *gc); - -void qq_request_keep_alive(PurpleConnection *gc); -gboolean qq_process_keep_alive(guint8 *data, gint data_len, PurpleConnection *gc); - -void qq_request_keep_alive_2007(PurpleConnection *gc); -gboolean qq_process_keep_alive_2007(guint8 *data, gint data_len, PurpleConnection *gc); - -void qq_request_keep_alive_2008(PurpleConnection *gc); -gboolean qq_process_keep_alive_2008(guint8 *data, gint data_len, PurpleConnection *gc); - -/* for QQ2007/2008 */ -void qq_request_get_server(PurpleConnection *gc); -guint16 qq_process_get_server(PurpleConnection *gc, guint8 *rcved, gint rcved_len); - -void qq_request_token_ex(PurpleConnection *gc); -void qq_request_token_ex_next(PurpleConnection *gc); -guint8 qq_process_token_ex(PurpleConnection *gc, guint8 *buf, gint buf_len); -void qq_captcha_input_dialog(PurpleConnection *gc,qq_captcha_data *captcha); - -void qq_request_check_pwd(PurpleConnection *gc); -guint8 qq_process_check_pwd( PurpleConnection *gc, guint8 *data, gint data_len); - -void qq_request_login_2007(PurpleConnection *gc); -guint8 qq_process_login_2007( PurpleConnection *gc, guint8 *data, gint data_len); - -void qq_request_login_2008(PurpleConnection *gc); -guint8 qq_process_login_2008( PurpleConnection *gc, guint8 *data, gint data_len); -#endif - diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/qq/qq_crypt.c --- a/libpurple/protocols/qq/qq_crypt.c Thu May 05 03:40:29 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,337 +0,0 @@ -/** - * @file qq_crypt.c - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * 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 - * - * - * QQ encryption algorithm - * Convert from ASM code provided by PerlOICQ - * - * Puzzlebird, Nov-Dec 2002 - */ - -/* Notes: (QQ uses 16 rounds, and modified something...) - -IN : 64 bits of data in v[0] - v[1]. -OUT: 64 bits of data in w[0] - w[1]. -KEY: 128 bits of key in k[0] - k[3]. - -delta is chosen to be the real part of -the golden ratio: Sqrt(5/4) - 1/2 ~ 0.618034 multiplied by 2^32. - -0x61C88647 is what we can track on the ASM codes.!! -*/ - -#include - -#include "debug.h" -#include "qq_crypt.h" - -#if 0 -void show_binary(char *psztitle, const guint8 *const buffer, gint bytes) -{ - printf("== %s %d ==\r\n", psztitle, bytes); - gint i, j, ch; - for (i = 0; i < bytes; i += 16) { - /* length label */ - printf("%07x: ", i); - - /* dump hex value */ - for (j = 0; j < 16; j++) { - if (j == 8) { - printf(" -"); - } - if ((i + j) < bytes) - printf(" %02x", buffer[i + j]); - else - printf(" "); - } - - printf(" "); - - - /* dump ascii value */ - for (j = 0; j < 16 && (i + j) < bytes; j++) { - ch = buffer[i + j] & 127; - if (ch < ' ' || ch == 127) - printf("."); - else - printf("%c", ch); - } - printf("\r\n"); - } - printf("========\r\n"); -} -#else - -#define show_binary(args... ) /* nothing */ - -#endif - -/******************************************************************** - * encryption - *******************************************************************/ - -/* Tiny Encryption Algorithm (TEA) */ -static inline void qq_encipher(guint32 *const v, const guint32 *const k, guint32 *const w) -{ - register guint32 - y = g_ntohl(v[0]), - z = g_ntohl(v[1]), - a = g_ntohl(k[0]), - b = g_ntohl(k[1]), - c = g_ntohl(k[2]), - d = g_ntohl(k[3]), - n = 0x10, - sum = 0, - delta = 0x9E3779B9; /* 0x9E3779B9 - 0x100000000 = -0x61C88647 */ - - while (n-- > 0) { - sum += delta; - y += ((z << 4) + a) ^ (z + sum) ^ ((z >> 5) + b); - z += ((y << 4) + c) ^ (y + sum) ^ ((y >> 5) + d); - } - - w[0] = g_htonl(y); - w[1] = g_htonl(z); -} - -/* it can be the real random seed function */ -/* override with number, convenient for debug */ -#ifdef DEBUG -static gint crypt_rand(void) { - return 0xdead; -} -#else -#include -#define crypt_rand() rand() -#endif - -/* 64-bit blocks and some kind of feedback mode of operation */ -static inline void encrypt_out(guint8 *crypted, const gint crypted_len, const guint8 *key) -{ - /* ships in encipher */ - guint32 plain32[2]; - guint32 p32_prev[2]; - guint32 key32[4]; - guint32 crypted32[2]; - guint32 c32_prev[2]; - - guint8 *crypted_ptr; - gint count64; - - /* prepare at first */ - crypted_ptr = crypted; - - memcpy(crypted32, crypted_ptr, sizeof(crypted32)); - c32_prev[0] = crypted32[0]; c32_prev[1] = crypted32[1]; - - p32_prev[0] = 0; p32_prev[1] = 0; - plain32[0] = crypted32[0] ^ p32_prev[0]; plain32[1] = crypted32[1] ^ p32_prev[1]; - - g_memmove(key32, key, 16); - count64 = crypted_len / 8; - while (count64-- > 0){ - /* encrypt it */ - qq_encipher(plain32, key32, crypted32); - - crypted32[0] ^= p32_prev[0]; crypted32[1] ^= p32_prev[1]; - - /* store curr 64 bits crypted */ - g_memmove(crypted_ptr, crypted32, sizeof(crypted32)); - - /* set prev */ - p32_prev[0] = plain32[0]; p32_prev[1] = plain32[1]; - c32_prev[0] = crypted32[0]; c32_prev[1] = crypted32[1]; - - /* set next 64 bits want to crypt*/ - if (count64 > 0) { - crypted_ptr += 8; - memcpy(crypted32, crypted_ptr, sizeof(crypted32)); - plain32[0] = crypted32[0] ^ c32_prev[0]; plain32[1] = crypted32[1] ^ c32_prev[1]; - } - } -} - -/* length of crypted buffer must be plain_len + 17*/ -/* - * The above comment used to say "plain_len + 16", but based on the - * behavior of the function that is wrong. If you give this function - * a plain string with len%8 = 7 then the returned length is len+17 - */ -gint qq_encrypt(guint8* crypted, const guint8* const plain, const gint plain_len, const guint8* const key) -{ - guint8 *crypted_ptr = crypted; /* current position of dest */ - gint pos, padding; - - padding = (plain_len + 10) % 8; - if (padding) { - padding = 8 - padding; - } - - pos = 0; - - /* set first byte as padding len */ - crypted_ptr[pos] = (rand() & 0xf8) | padding; - pos++; - - /* extra 2 bytes */ - padding += 2; - - /* faster a little - memset(crypted_ptr + pos, rand() & 0xff, padding); - pos += padding; - */ - - /* more random */ - while (padding--) { - crypted_ptr[pos++] = rand() & 0xff; - } - - g_memmove(crypted_ptr + pos, plain, plain_len); - pos += plain_len; - - /* header padding len + plain len must be multiple of 8 - * tail pading len is always 8 - (1st byte) - */ - memset(crypted_ptr + pos, 0x00, 7); - pos += 7; - - show_binary("After padding", crypted, pos); - - encrypt_out(crypted, pos, key); - - show_binary("Encrypted", crypted, pos); - return pos; -} - -/******************************************************************** - * decryption - ********************************************************************/ - -static inline void qq_decipher(guint32 *const v, const guint32 *const k, guint32 *const w) -{ - register guint32 - y = g_ntohl(v[0]), - z = g_ntohl(v[1]), - a = g_ntohl(k[0]), - b = g_ntohl(k[1]), - c = g_ntohl(k[2]), - d = g_ntohl(k[3]), - n = 0x10, - sum = 0xE3779B90, /* why this ? must be related with n value */ - delta = 0x9E3779B9; - - /* sum = delta<<5, in general sum = delta * n */ - while (n-- > 0) { - z -= ((y << 4) + c) ^ (y + sum) ^ ((y >> 5) + d); - y -= ((z << 4) + a) ^ (z + sum) ^ ((z >> 5) + b); - sum -= delta; - } - - w[0] = g_htonl(y); - w[1] = g_htonl(z); -} - -static inline gint decrypt_out(guint8 *dest, gint crypted_len, const guint8* const key) -{ - gint plain_len; - guint32 key32[4]; - guint32 crypted32[2]; - guint32 c32_prev[2]; - guint32 plain32[2]; - guint32 p32_prev[2]; - gint count64; - gint padding; - guint8 *crypted_ptr = dest; - - /* decrypt first 64 bit */ - memcpy(key32, key, sizeof(key32)); - memcpy(crypted32, crypted_ptr, sizeof(crypted32)); - c32_prev[0] = crypted32[0]; c32_prev[1] = crypted32[1]; - - qq_decipher(crypted32, key32, p32_prev); - memcpy(crypted_ptr, p32_prev, sizeof(p32_prev)); - - /* check padding len */ - padding = 2 + (crypted_ptr[0] & 0x7); - if (padding < 2) { - padding += 8; - } - plain_len = crypted_len - 1 - padding - 7; - if( plain_len < 0 ) { - return -2; - } - - count64 = crypted_len / 8; - while (--count64 > 0){ - c32_prev[0] = crypted32[0]; c32_prev[1] = crypted32[1]; - crypted_ptr += 8; - - memcpy(crypted32, crypted_ptr, sizeof(crypted32)); - p32_prev[0] ^= crypted32[0]; p32_prev[1] ^= crypted32[1]; - - qq_decipher(p32_prev, key32, p32_prev); - - plain32[0] = p32_prev[0] ^ c32_prev[0]; plain32[1] = p32_prev[1] ^ c32_prev[1]; - memcpy(crypted_ptr, plain32, sizeof(plain32)); - } - - return plain_len; -} - -/* length of plain buffer must be equal to crypted_len */ -gint qq_decrypt(guint8 *plain, const guint8* const crypted, const gint crypted_len, const guint8* const key) -{ - gint plain_len = 0; - gint hdr_padding; - gint pos; - - /* at least 16 bytes and %8 == 0 */ - if ((crypted_len % 8) || (crypted_len < 16)) { - return -1; - } - - memcpy(plain, crypted, crypted_len); - - plain_len = decrypt_out(plain, crypted_len, key); - if (plain_len < 0) { - return plain_len; /* invalid first 64 bits */ - } - - show_binary("Decrypted with padding", plain, crypted_len); - - /* check last 7 bytes is zero or not? */ - for (pos = crypted_len - 1; pos > crypted_len - 8; pos--) { - if (plain[pos] != 0) { - return -3; - } - } - if (plain_len == 0) { - return plain_len; - } - - hdr_padding = crypted_len - plain_len - 7; - g_memmove(plain, plain + hdr_padding, plain_len); - - return plain_len; -} - diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/qq/qq_crypt.h --- a/libpurple/protocols/qq/qq_crypt.h Thu May 05 03:40:29 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,33 +0,0 @@ - /** - * @file qq_crypt.h - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * 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 - */ - -#ifndef _QQ_CRYPT_H_ -#define _QQ_CRYPT_H_ - -#include - -gint qq_encrypt(guint8* crypted, const guint8* const plain, const gint plain_len, const guint8* const key); - -gint qq_decrypt(guint8 *plain, const guint8* const crypted, const gint crypted_len, const guint8* const key); -#endif diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/qq/qq_define.c --- a/libpurple/protocols/qq/qq_define.c Thu May 05 03:40:29 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,270 +0,0 @@ -/** - * @file qq_define.c - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * 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 02111-1301 USA - */ - -#include "internal.h" - -#include "qq_define.h" - -#define QQ_CLIENT_062E 0x062e /* GB QQ2000c build 0630 */ -#define QQ_CLIENT_072E 0x072e /* EN QQ2000c build 0305 */ -#define QQ_CLIENT_0801 0x0801 /* EN QQ2000c build 0630 */ -#define QQ_CLIENT_0A1D 0x0a1d /* GB QQ2003c build 0808 */ -#define QQ_CLIENT_0B07 0x0b07 /* GB QQ2003c build 0925 */ -#define QQ_CLIENT_0B2F 0x0b2f /* GB QQ2003iii build 0117 */ -#define QQ_CLIENT_0B35 0x0b35 /* GB QQ2003iii build 0304 (offical release) */ -#define QQ_CLIENT_0B37 0x0b37 /* GB QQ2003iii build 0304 (April 05 updates) */ -#define QQ_CLIENT_0E1B 0x0e1b /* QQ2005 ? */ -#define QQ_CLIENT_0E35 0x0e35 /* EN QQ2005 V05.0.200.020 */ -#define QQ_CLIENT_0F15 0x0f15 /* QQ2006 Spring Festival build */ -#define QQ_CLIENT_0F5F 0x0f5f /* QQ2006 final build */ - -#define QQ_CLIENT_0C0B 0x0C0B /* QQ2004 */ -#define QQ_CLIENT_0C0D 0x0C0D /* QQ2004 preview*/ -#define QQ_CLIENT_0C21 0x0C21 /* QQ2004 */ -#define QQ_CLIENT_0C49 0x0C49 /* QQ2004II */ -#define QQ_CLIENT_0D05 0x0D05 /* QQ2005 beta1 */ -#define QQ_CLIENT_0D51 0x0D51 /* QQ2005 beta2 */ -#define QQ_CLIENT_0D61 0x0D61 /* QQ2005 */ -#define QQ_CLIENT_05A5 0x05A5 /* ? */ -#define QQ_CLIENT_05F1 0x0F15 /* QQ2006 Spring Festival */ -#define QQ_CLIENT_0F4B 0x0F4B /* QQ2006 Beta 3 */ - -#define QQ_CLIENT_1105 0x1105 /* QQ2007 beta4*/ -#define QQ_CLIENT_1203 0x1203 /* QQ2008 */ -#define QQ_CLIENT_1205 0x1205 /* QQ2008 Qi Fu */ -#define QQ_CLIENT_120B 0x120B /* QQ2008 July 8.0.978.400 */ -#define QQ_CLIENT_1412 0x1412 /* QQMac 1.0 preview1 build 670 */ -#define QQ_CLIENT_1441 0x1441 /* QQ2009 preview2 */ - -#define QQ_SERVER_0100 0x0100 /* server */ - - -/* given source tag, return its description accordingly */ -const gchar *qq_get_ver_desc(gint source) -{ - switch (source) { - case QQ_CLIENT_062E: - return "GB QQ2000c build 0630"; - case QQ_CLIENT_072E: - return "En QQ2000c build 0305"; - case QQ_CLIENT_0801: - return "En QQ2000c build 0630"; - case QQ_CLIENT_0A1D: - return "GB QQ2003ii build 0808"; - case QQ_CLIENT_0B07: - return "GB QQ2003ii build 0925"; - case QQ_CLIENT_0B2F: - return "GB QQ2003iii build 0117"; - case QQ_CLIENT_0B35: - return "GB QQ2003iii build 0304"; - case QQ_CLIENT_0B37: - return "GB QQ2003iii build 0304 (April 5 update)"; - case QQ_CLIENT_0C0B: - return "QQ2004"; - case QQ_CLIENT_0C0D: - return "QQ2004 preview"; - case QQ_CLIENT_0C21: - return "QQ2004"; - case QQ_CLIENT_0C49: - return "QQ2004II"; - case QQ_CLIENT_0D05: - return "QQ2005 beta1"; - case QQ_CLIENT_0D51: - return "QQ2005 beta2"; - case QQ_CLIENT_0D55: - case QQ_CLIENT_0D61: - return "QQ2005"; - case QQ_CLIENT_0E1B: - return "QQ2005 or QQ2006"; - case QQ_CLIENT_0E35: - return "En QQ2005 V05.0.200.020"; - case QQ_CLIENT_0F15: - return "QQ2006 Spring Festival"; - case QQ_CLIENT_0F4B: - return "QQ2006 beta3"; - case QQ_CLIENT_0F5F: - return "QQ2006 final build"; - case QQ_CLIENT_1105: - return "QQ2007 beta4"; - case QQ_CLIENT_111D: - return "QQ2007"; - case QQ_CLIENT_115B: - case QQ_CLIENT_1203: - case QQ_CLIENT_1205: - case QQ_CLIENT_120B: - return "QQ2008"; - case QQ_CLIENT_1412: - return "QQMac 1.0 preview1 build 670"; - case QQ_CLIENT_1441: - return "QQ2009 preview2"; - case QQ_CLIENT_1663: - return "QQ2009"; - case QQ_SERVER_0100: - return "QQ Server 0100"; - default: - return "Unknown Version"; - } -} - -/* given command alias, return the command name accordingly */ -const gchar *qq_get_cmd_desc(gint cmd) -{ - switch (cmd) { - case QQ_CMD_LOGOUT: - return "QQ_CMD_LOGOUT"; - case QQ_CMD_KEEP_ALIVE: - return "CMD_KEEP_ALIVE"; - case QQ_CMD_UPDATE_INFO: - return "CMD_UPDATE_INFO"; - case QQ_CMD_SEARCH_USER: - return "CMD_SEARCH_USER"; - case QQ_CMD_GET_BUDDY_INFO: - return "CMD_GET_BUDDY_INFO"; - case QQ_CMD_ADD_BUDDY_NO_AUTH: - return "CMD_ADD_BUDDY_NO_AUTH"; - case QQ_CMD_REMOVE_BUDDY: - return "CMD_REMOVE_BUDDY"; - case QQ_CMD_ADD_BUDDY_AUTH: - return "CMD_ADD_BUDDY_AUTH"; - case QQ_CMD_CHANGE_STATUS: - return "CMD_CHANGE_STATUS"; - case QQ_CMD_ACK_SYS_MSG: - return "CMD_ACK_SYS_MSG"; - case QQ_CMD_SEND_IM: - return "CMD_SEND_IM"; - case QQ_CMD_RECV_IM: - return "CMD_RECV_IM"; - case QQ_CMD_REMOVE_ME: - return "CMD_REMOVE_ME"; - case QQ_CMD_LOGIN: - return "CMD_LOGIN"; - case QQ_CMD_GET_BUDDIES_LIST: - return "CMD_GET_BUDDIES_LIST"; - case QQ_CMD_GET_BUDDIES_ONLINE: - return "CMD_GET_BUDDIES_ONLINE"; - case QQ_CMD_ROOM: - return "CMD_ROOM"; - case QQ_CMD_GET_BUDDIES_AND_ROOMS: - return "CMD_GET_BUDDIES_AND_ROOMS"; - case QQ_CMD_GET_LEVEL: - return "CMD_GET_LEVEL"; - case QQ_CMD_TOKEN: - return "CMD_TOKEN"; - case QQ_CMD_RECV_MSG_SYS: - return "CMD_RECV_MSG_SYS"; - case QQ_CMD_BUDDY_CHANGE_STATUS: - return "CMD_BUDDY_CHANGE_STATUS"; - case QQ_CMD_GET_SERVER: - return "CMD_GET_SERVER"; - case QQ_CMD_TOKEN_EX: - return "CMD_TOKEN_EX"; - case QQ_CMD_CHECK_PWD: - return "CMD_CHECK_PWD"; - case QQ_CMD_AUTH_CODE: - return "CMD_AUTH_CODE"; - case QQ_CMD_ADD_BUDDY_NO_AUTH_EX: - return "CMD_ADD_BUDDY_NO_AUTH_EX"; - case QQ_CMD_ADD_BUDDY_AUTH_EX: - return "CMD_BUDDY_ADD_AUTH_EX"; - case QQ_CMD_BUDDY_CHECK_CODE: - return "CMD_BUDDY_CHECK_CODE"; - case QQ_CMD_BUDDY_QUESTION: - return "CMD_BUDDY_QUESTION"; - case QQ_CMD_BUDDY_MEMO: - return "CMD_BUDDY_MEMO"; - default: - return "CMD_UNKNOW"; - } -} - -const gchar *qq_get_room_cmd_desc(gint room_cmd) -{ - switch (room_cmd) { - case QQ_ROOM_CMD_CREATE: - return "ROOM_CMD_CREATE"; - case QQ_ROOM_CMD_MEMBER_OPT: - return "ROOM_CMD_MEMBER_OPT"; - case QQ_ROOM_CMD_CHANGE_INFO: - return "ROOM_CMD_CHANGE_INFO"; - case QQ_ROOM_CMD_GET_INFO: - return "ROOM_CMD_GET_INFO"; - case QQ_ROOM_CMD_ACTIVATE: - return "ROOM_CMD_ACTIVATE"; - case QQ_ROOM_CMD_SEARCH: - return "ROOM_CMD_SEARCH"; - case QQ_ROOM_CMD_JOIN: - return "ROOM_CMD_JOIN"; - case QQ_ROOM_CMD_AUTH: - return "ROOM_CMD_AUTH"; - case QQ_ROOM_CMD_QUIT: - return "ROOM_CMD_QUIT"; - case QQ_ROOM_CMD_SEND_IM: - return "ROOM_CMD_SEND_IM"; - case QQ_ROOM_CMD_GET_ONLINES: - return "ROOM_CMD_GET_ONLINES"; - case QQ_ROOM_CMD_GET_BUDDIES: - return "ROOM_CMD_GET_BUDDIES"; - case QQ_ROOM_CMD_CHANGE_CARD: - return "ROOM_CMD_CHANGE_CARD"; - case QQ_ROOM_CMD_GET_REALNAMES: - return "ROOM_CMD_GET_REALNAMES"; - case QQ_ROOM_CMD_GET_CARD: - return "ROOM_CMD_GET_CARD"; - case QQ_ROOM_CMD_SEND_IM_EX: - return "ROOM_CMD_SEND_IM_EX"; - case QQ_ROOM_CMD_ADMIN: - return "ROOM_CMD_ADMIN"; - case QQ_ROOM_CMD_TRANSFER: - return "ROOM_CMD_TRANSFER"; - case QQ_ROOM_CMD_TEMP_CREATE: - return "ROOM_CMD_TEMP_CREATE"; - case QQ_ROOM_CMD_TEMP_CHANGE_MEMBER: - return "ROOM_CMD_TEMP_CHANGE_MEMBER"; - case QQ_ROOM_CMD_TEMP_QUIT: - return "ROOM_CMD_TEMP_QUIT"; - case QQ_ROOM_CMD_TEMP_GET_INFO: - return "ROOM_CMD_TEMP_GET_INFO"; - case QQ_ROOM_CMD_TEMP_SEND_IM: - return "ROOM_CMD_TEMP_SEND_IM"; - case QQ_ROOM_CMD_TEMP_GET_MEMBERS: - return "ROOM_CMD_TEMP_GET_MEMBERS"; - default: - return "ROOM_CMD_UNKNOW"; - } -} - -/* check if status means online or offline */ -gboolean is_online(guint8 status) -{ - switch(status) { - case QQ_BUDDY_ONLINE_NORMAL: - case QQ_BUDDY_ONLINE_AWAY: - case QQ_BUDDY_ONLINE_INVISIBLE: - case QQ_BUDDY_ONLINE_BUSY: - return TRUE; - case QQ_BUDDY_CHANGE_TO_OFFLINE: - return FALSE; - } - return FALSE; -} diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/qq/qq_define.h --- a/libpurple/protocols/qq/qq_define.h Thu May 05 03:40:29 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,141 +0,0 @@ -/** - * @file qq_define.h - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * 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 02111-1301 USA - */ - -#ifndef _QQ_HEADER_INFO_H_ -#define _QQ_HEADER_INFO_H_ - -#include - -#define QQ_UDP_HEADER_LENGTH 7 -#define QQ_TCP_HEADER_LENGTH 9 - -#define QQ_PACKET_TAG 0x02 /* all QQ text packets starts with it */ -#define QQ_PACKET_TAIL 0x03 /* all QQ text packets end with it */ - -#define QQ_CLIENT_0D55 0x0d55 /* QQ2005 used by openq before */ -#define QQ_CLIENT_111D 0x111D /* QQ2007 */ -#define QQ_CLIENT_115B 0x115B /* QQ2008 He Sui */ -#define QQ_CLIENT_1663 0x1663 /* QQ2009 Release */ -#define QQ_CLIENT_1801 0x1801 /* QQ2009 International Beta1 */ - -const gchar *qq_get_ver_desc(gint source); - -/* list of known QQ commands */ -enum { - QQ_CMD_LOGOUT = 0x0001, /* log out */ - QQ_CMD_KEEP_ALIVE = 0x0002, /* get onlines from tencent */ - QQ_CMD_UPDATE_INFO = 0x0004, /* update information */ - QQ_CMD_SEARCH_USER = 0x0005, /* search for user */ - QQ_CMD_GET_BUDDY_INFO = 0x0006, /* get user information */ - QQ_CMD_ADD_BUDDY_NO_AUTH = 0x0009, /* add buddy without auth */ - QQ_CMD_REMOVE_BUDDY = 0x000a, /* delete a buddy */ - QQ_CMD_ADD_BUDDY_AUTH = 0x000b, /* buddy authentication */ - QQ_CMD_CHANGE_STATUS = 0x000d, /* change my online status */ - QQ_CMD_ACK_SYS_MSG = 0x0012, /* ack system message */ - QQ_CMD_SEND_IM = 0x0016, /* send message */ - QQ_CMD_RECV_IM = 0x0017, /* receive message */ - QQ_CMD_REMOVE_ME = 0x001c, /* remove self */ - QQ_CMD_REQUEST_KEY = 0x001d, /* request key for file transfer */ - QQ_CMD_CELL_PHONE_1 = 0x0021, /* cell phone 1 */ - QQ_CMD_LOGIN = 0x0022, /* login */ - QQ_CMD_GET_BUDDIES_LIST = 0x0026, /* get buddies list */ - QQ_CMD_GET_BUDDIES_ONLINE = 0x0027, /* get online buddies list */ - QQ_CMD_CELL_PHONE_2 = 0x0029, /* cell phone 2 */ - QQ_CMD_ROOM = 0x0030, /* room command */ - QQ_CMD_GET_BUDDIES_AND_ROOMS = 0x0058, - QQ_CMD_GET_LEVEL = 0x005C, /* get level for one or more buddies */ - QQ_CMD_TOKEN = 0x0062, /* get login token */ - QQ_CMD_RECV_MSG_SYS = 0x0080, /* receive a system message */ - QQ_CMD_BUDDY_CHANGE_STATUS = 0x0081, /* buddy change status */ - QQ_CMD_BUDDY_MEMO = 0x003E, /* the message about buddy memo */ - - /* for QQ2007*/ - QQ_CMD_GET_SERVER = 0x0091, /* select login server */ - QQ_CMD_TOKEN_EX = 0x00BA, /* get LOGIN token */ - QQ_CMD_CHECK_PWD = 0x00DD, /* Password verify */ - QQ_CMD_AUTH_CODE = 0x00AE, /* the request verification of information */ - QQ_CMD_ADD_BUDDY_NO_AUTH_EX = 0x00A7, /* add friend without auth */ - QQ_CMD_ADD_BUDDY_AUTH_EX = 0x00A8, /* add buddy with auth */ - QQ_CMD_BUDDY_CHECK_CODE = 0x00B5, - QQ_CMD_BUDDY_QUESTION = 0x00B7 -}; - -const gchar *qq_get_cmd_desc(gint type); - -enum { - QQ_ROOM_CMD_CREATE = 0x01, - QQ_ROOM_CMD_MEMBER_OPT = 0x02, - QQ_ROOM_CMD_CHANGE_INFO = 0x03, - QQ_ROOM_CMD_GET_INFO = 0x04, - QQ_ROOM_CMD_ACTIVATE = 0x05, - QQ_ROOM_CMD_SEARCH = 0x06, - QQ_ROOM_CMD_JOIN = 0x07, - QQ_ROOM_CMD_AUTH = 0x08, - QQ_ROOM_CMD_QUIT = 0x09, - QQ_ROOM_CMD_SEND_IM = 0x0a, - QQ_ROOM_CMD_GET_ONLINES = 0x0b, - QQ_ROOM_CMD_GET_BUDDIES = 0x0c, - - QQ_ROOM_CMD_CHANGE_CARD = 0x0E, - QQ_ROOM_CMD_GET_REALNAMES = 0x0F, - QQ_ROOM_CMD_GET_CARD = 0x10, - QQ_ROOM_CMD_SEND_IM_EX = 0x1A, - QQ_ROOM_CMD_ADMIN = 0x1B, - QQ_ROOM_CMD_TRANSFER = 0x1C, - QQ_ROOM_CMD_TEMP_CREATE = 0x30, - QQ_ROOM_CMD_TEMP_CHANGE_MEMBER = 0x31, - QQ_ROOM_CMD_TEMP_QUIT = 0x32, - QQ_ROOM_CMD_TEMP_GET_INFO = 0x33, - QQ_ROOM_CMD_TEMP_SEND_IM = 0x35, - QQ_ROOM_CMD_TEMP_GET_MEMBERS = 0x37 -}; - -const gchar *qq_get_room_cmd_desc(gint room_cmd); - -enum { - QQ_SERVER_BUDDY_ADDED = 1, - QQ_SERVER_BUDDY_ADD_REQUEST = 2, - QQ_SERVER_BUDDY_ADDED_ME = 3, - QQ_SERVER_BUDDY_REJECTED_ME = 4, - QQ_SERVER_NOTICE= 6, - QQ_SERVER_NEW_CLIENT = 9, - QQ_SERVER_BUDDY_ADDING_EX = 40, - QQ_SERVER_BUDDY_ADD_REQUEST_EX = 41, - QQ_SERVER_BUDDY_ADDED_ANSWER = 42, - QQ_SERVER_BUDDY_ADDED_EX = 43 -}; - -enum { - QQ_BUDDY_OFFLINE = 0x00, - QQ_BUDDY_ONLINE_NORMAL = 10, - QQ_BUDDY_CHANGE_TO_OFFLINE = 20, - QQ_BUDDY_ONLINE_AWAY = 30, - QQ_BUDDY_ONLINE_INVISIBLE = 40, - QQ_BUDDY_ONLINE_BUSY = 50 -}; - - -gboolean is_online(guint8 status); - -#endif diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/qq/qq_network.c --- a/libpurple/protocols/qq/qq_network.c Thu May 05 03:40:29 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1322 +0,0 @@ -/** - * @file qq_network.c - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * 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 02111-1301 USA - */ - -#include "internal.h" -#include "cipher.h" -#include "debug.h" - -#include "buddy_info.h" -#include "group_info.h" -#include "group_internal.h" -#include "qq_crypt.h" -#include "qq_define.h" -#include "qq_base.h" -#include "buddy_list.h" -#include "packet_parse.h" -#include "qq_network.h" -#include "qq_trans.h" -#include "utils.h" -#include "qq_process.h" - -#define QQ_DEFAULT_PORT 8000 - -/* set QQ_CONNECT_MAX to 1, when test reconnecting */ -#define QQ_CONNECT_MAX 3 -#define QQ_CONNECT_INTERVAL 2 -#define QQ_CONNECT_CHECK 5 -#define QQ_KEEP_ALIVE_INTERVAL 60 -#define QQ_TRANS_INTERVAL 10 - -gboolean connect_to_server(PurpleConnection *gc, gchar *server, gint port); - -static qq_connection *connection_find(qq_data *qd, int fd) { - qq_connection *ret = NULL; - GSList *entry = qd->openconns; - while(entry) { - ret = entry->data; - if(ret->fd == fd) return ret; - entry = entry->next; - } - return NULL; -} - -static qq_connection *connection_create(qq_data *qd, int fd) { - qq_connection *ret = g_new0(qq_connection, 1); - g_return_val_if_fail(ret != NULL, NULL); - ret->fd = fd; - qd->openconns = g_slist_append(qd->openconns, ret); - return ret; -} - -static void connection_remove(qq_data *qd, int fd) { - qq_connection *conn = connection_find(qd, fd); - qd->openconns = g_slist_remove(qd->openconns, conn); - - g_return_if_fail( conn != NULL ); - - purple_debug_info("QQ", "Close socket %d\n", conn->fd); - if(conn->input_handler > 0) purple_input_remove(conn->input_handler); - if(conn->can_write_handler > 0) purple_input_remove(conn->can_write_handler); - - if (conn->fd >= 0) close(conn->fd); - if(conn->tcp_txbuf != NULL) purple_circ_buffer_destroy(conn->tcp_txbuf); - if (conn->tcp_rxqueue != NULL) g_free(conn->tcp_rxqueue); - - g_free(conn); -} - -static void connection_free_all(qq_data *qd) { - qq_connection *ret = NULL; - GSList *entry = qd->openconns; - while(entry) { - ret = entry->data; - connection_remove(qd, ret->fd); - entry = qd->openconns; - } -} -static gboolean set_new_server(qq_data *qd) -{ - gint count; - gint index; - GList *it = NULL; - - g_return_val_if_fail(qd != NULL, FALSE); - - if (qd->servers == NULL) { - purple_debug_info("QQ", "Server list is NULL\n"); - return FALSE; - } - - /* remove server used before */ - if (qd->curr_server != NULL) { - purple_debug_info("QQ", - "Remove current [%s] from server list\n", qd->curr_server); - qd->servers = g_list_remove(qd->servers, qd->curr_server); - qd->curr_server = NULL; - } - - count = g_list_length(qd->servers); - purple_debug_info("QQ", "Server list has %d\n", count); - if (count <= 0) { - /* no server left, disconnect when result is false */ - qd->servers = NULL; - return FALSE; - } - - /* get new server */ - index = rand() % count; - it = g_list_nth(qd->servers, index); - qd->curr_server = it->data; /* do not free server_name */ - if (qd->curr_server == NULL || strlen(qd->curr_server) <= 0 ) { - purple_debug_info("QQ", "Server name at %d is empty\n", index); - return FALSE; - } - - purple_debug_info("QQ", "set new server to %s\n", qd->curr_server); - return TRUE; -} - -static gint packet_get_header(guint8 *header_tag, guint16 *source_tag, - guint16 *cmd, guint16 *seq, guint8 *buf) -{ - gint bytes = 0; - bytes += qq_get8(header_tag, buf + bytes); - bytes += qq_get16(source_tag, buf + bytes); - bytes += qq_get16(cmd, buf + bytes); - bytes += qq_get16(seq, buf + bytes); - return bytes; -} - -static gboolean connect_check(gpointer data) -{ - PurpleConnection *gc = (PurpleConnection *) data; - qq_data *qd; - - g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, FALSE); - qd = (qq_data *) gc->proto_data; - - if (qd->connect_watcher > 0) { - purple_timeout_remove(qd->connect_watcher); - qd->connect_watcher = 0; - } - - if (qd->fd >= 0 && qd->ld.token != NULL && qd->ld.token_len > 0) { - purple_debug_info("QQ", "Connect ok\n"); - return FALSE; - } - - qd->connect_watcher = purple_timeout_add_seconds(0, qq_connect_later, gc); - return FALSE; -} - -/* Warning: qq_connect_later destory all connection - * Any function should be care of use qq_data after call this function - * Please conside tcp_pending and udp_pending */ -gboolean qq_connect_later(gpointer data) -{ - PurpleConnection *gc; - char *tmp_server; - int port; - gchar **segments; - qq_data *qd; - - gc = (PurpleConnection *) data; - g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, FALSE); - qd = (qq_data *) gc->proto_data; - tmp_server = NULL; - - if (qd->check_watcher > 0) { - purple_timeout_remove(qd->check_watcher); - qd->check_watcher = 0; - } - qq_disconnect(gc); - - if (qd->redirect_ip.s_addr != 0) { - /* redirect to new server */ - tmp_server = g_strdup_printf("%s:%d", inet_ntoa(qd->redirect_ip), qd->redirect_port); - qd->servers = g_list_append(qd->servers, tmp_server); - - qd->curr_server = tmp_server; - tmp_server = NULL; - - qd->redirect_ip.s_addr = 0; - qd->redirect_port = 0; - qd->connect_retry = QQ_CONNECT_MAX; - } - - if (qd->curr_server == NULL || strlen (qd->curr_server) == 0 || qd->connect_retry <= 0) { - if ( set_new_server(qd) != TRUE) { - purple_connection_error_reason(gc, - PURPLE_CONNECTION_ERROR_NETWORK_ERROR, - _("Unable to connect")); - return FALSE; - } - qd->connect_retry = QQ_CONNECT_MAX; - } - - segments = g_strsplit_set(qd->curr_server, ":", 0); - tmp_server = g_strdup(segments[0]); - if (NULL != segments[1]) { - port = atoi(segments[1]); - if (port <= 0) { - purple_debug_info("QQ", "Port not define in %s, use default.\n", qd->curr_server); - port = QQ_DEFAULT_PORT; - } - } else { - purple_debug_info("QQ", "Error splitting server string: %s, setting port to default.\n", qd->curr_server); - port = QQ_DEFAULT_PORT; - } - - g_strfreev(segments); - - qd->connect_retry--; - if ( !connect_to_server(gc, tmp_server, port) ) { - purple_connection_error_reason(gc, - PURPLE_CONNECTION_ERROR_NETWORK_ERROR, - _("Unable to connect")); - } - - g_free(tmp_server); - tmp_server = NULL; - - qd->check_watcher = purple_timeout_add_seconds(QQ_CONNECT_CHECK, connect_check, gc); - return FALSE; /* timeout callback stops */ -} - -static void redirect_server(PurpleConnection *gc) -{ - qq_data *qd; - qd = (qq_data *) gc->proto_data; - - if (qd->check_watcher > 0) { - purple_timeout_remove(qd->check_watcher); - qd->check_watcher = 0; - } - if (qd->connect_watcher > 0) purple_timeout_remove(qd->connect_watcher); - qd->connect_watcher = purple_timeout_add_seconds(QQ_CONNECT_INTERVAL, qq_connect_later, gc); -} - -/* process the incoming packet from qq_pending */ -static gboolean packet_process(PurpleConnection *gc, guint8 *buf, gint buf_len) -{ - qq_data *qd; - gint bytes, bytes_not_read; - - guint8 header_tag; - guint16 source_tag; - guint16 cmd; - guint16 seq; /* May be ack_seq or send_seq, depends on cmd */ - guint8 room_cmd; - guint32 room_id; - UPDCLS update_class; - guint32 ship32; - int ret; - - qq_transaction *trans; - - g_return_val_if_fail(buf != NULL && buf_len > 0, TRUE); - - qd = (qq_data *) gc->proto_data; - - qd->net_stat.rcved++; - if (qd->net_stat.rcved <= 0) memset(&(qd->net_stat), 0, sizeof(qd->net_stat)); - - /* Len, header and tail tag have been checked before */ - bytes = 0; - bytes += packet_get_header(&header_tag, &source_tag, &cmd, &seq, buf + bytes); - -#if 1 - purple_debug_info("QQ", "==> [%05d] %s 0x%04X, source tag 0x%04X len %d\n", - seq, qq_get_cmd_desc(cmd), cmd, source_tag, buf_len); -#endif - /* this is the length of all the encrypted data (also remove tail tag) */ - bytes_not_read = buf_len - bytes - 1; - - /* ack packet, we need to update send tranactions */ - /* we do not check duplication for server ack */ - trans = qq_trans_find_rcved(gc, cmd, seq); - if (trans == NULL) { - /* new server command */ - if ( !qd->is_login ) { - qq_trans_add_remain(gc, cmd, seq, buf + bytes, bytes_not_read); - } else { - qq_trans_add_server_cmd(gc, cmd, seq, buf + bytes, bytes_not_read); - qq_proc_server_cmd(gc, cmd, seq, buf + bytes, bytes_not_read); - } - return TRUE; - } - - if (qq_trans_is_dup(trans)) { - qd->net_stat.rcved_dup++; - purple_debug_info("QQ", "dup [%05d] %s, discard...\n", seq, qq_get_cmd_desc(cmd)); - return TRUE; - } - - update_class = qq_trans_get_class(trans); - ship32 = qq_trans_get_ship(trans); - if (update_class != 0 || ship32 != 0) { - purple_debug_info("QQ", "Update class %d, ship32 %d\n", update_class, ship32); - } - - switch (cmd) { - case QQ_CMD_TOKEN: - case QQ_CMD_GET_SERVER: - case QQ_CMD_TOKEN_EX: - case QQ_CMD_CHECK_PWD: - case QQ_CMD_LOGIN: - ret = qq_proc_login_cmds(gc, cmd, seq, buf + bytes, bytes_not_read, update_class, ship32); - if (ret != QQ_LOGIN_REPLY_OK) { - if (ret == QQ_LOGIN_REPLY_REDIRECT) { - redirect_server(gc); - } - return FALSE; /* do nothing after this function and return now */ - } - break; - case QQ_CMD_ROOM: - room_cmd = qq_trans_get_room_cmd(trans); - room_id = qq_trans_get_room_id(trans); - qq_proc_room_cmds(gc, seq, room_cmd, room_id, buf + bytes, bytes_not_read, update_class, ship32); - break; - default: - qq_proc_client_cmds(gc, cmd, seq, buf + bytes, bytes_not_read, update_class, ship32); - break; - } - - return TRUE; -} - -static void tcp_pending(gpointer data, gint source, PurpleInputCondition cond) -{ - PurpleConnection *gc = (PurpleConnection *) data; - qq_data *qd; - qq_connection *conn; - guint8 buf[1024]; /* set to 16 when test tcp_rxqueue */ - gint buf_len; - gint bytes; - - guint8 *pkt; - guint16 pkt_len; - - gchar *error_msg; - guint8 *jump; - gint jump_len; - - g_return_if_fail(gc != NULL && gc->proto_data != NULL); - qd = (qq_data *) gc->proto_data; - - if(cond != PURPLE_INPUT_READ) { - purple_connection_error_reason(gc, - PURPLE_CONNECTION_ERROR_NETWORK_ERROR, - _("Socket error")); - return; - } - - conn = connection_find(qd, source); - g_return_if_fail(conn != NULL); - - /* test code, not using tcp_rxqueue - memset(pkt,0, sizeof(pkt)); - buf_len = read(qd->fd, pkt, sizeof(pkt)); - if (buf_len > 2) { - packet_process(gc, pkt + 2, buf_len - 2); - } - return; - */ - - buf_len = read(source, buf, sizeof(buf)); - if (buf_len < 0) { - if (errno == EAGAIN) - /* No worries */ - return; - - error_msg = g_strdup_printf(_("Lost connection with server: %s"), g_strerror(errno)); - purple_connection_error_reason(gc, - PURPLE_CONNECTION_ERROR_NETWORK_ERROR, - error_msg); - g_free(error_msg); - return; - } else if (buf_len == 0) { - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, - _("Server closed the connection")); - return; - } - - /* keep alive will be sent in 30 seconds since last_receive - * QQ need a keep alive packet in every 60 seconds - gc->last_received = time(NULL); - */ - /* purple_debug_info("TCP_PENDING", "Read %d bytes, rxlen is %d\n", buf_len, conn->tcp_rxlen); */ - conn->tcp_rxqueue = g_realloc(conn->tcp_rxqueue, buf_len + conn->tcp_rxlen); - memcpy(conn->tcp_rxqueue + conn->tcp_rxlen, buf, buf_len); - conn->tcp_rxlen += buf_len; - - pkt = g_newa(guint8, MAX_PACKET_SIZE); - while (PURPLE_CONNECTION_IS_VALID(gc)) { - if (qd->openconns == NULL) { - break; - } - if (conn->tcp_rxqueue == NULL) { - conn->tcp_rxlen = 0; - break; - } - if (conn->tcp_rxlen < QQ_TCP_HEADER_LENGTH) { - break; - } - - bytes = 0; - bytes += qq_get16(&pkt_len, conn->tcp_rxqueue + bytes); - if (conn->tcp_rxlen < pkt_len) { - break; - } - - /* purple_debug_info("TCP_PENDING", "Packet len=%d, rxlen=%d\n", pkt_len, conn->tcp_rxlen); */ - if ( pkt_len < QQ_TCP_HEADER_LENGTH - || *(conn->tcp_rxqueue + bytes) != QQ_PACKET_TAG - || *(conn->tcp_rxqueue + pkt_len - 1) != QQ_PACKET_TAIL) { - /* HEY! This isn't even a QQ. What are you trying to pull? */ - purple_debug_warning("TCP_PENDING", "Packet error, no header or tail tag\n"); - - jump = memchr(conn->tcp_rxqueue + 1, QQ_PACKET_TAIL, conn->tcp_rxlen - 1); - if ( !jump ) { - purple_debug_warning("TCP_PENDING", "Failed to find next tail, clear receive buffer\n"); - g_free(conn->tcp_rxqueue); - conn->tcp_rxqueue = NULL; - conn->tcp_rxlen = 0; - return; - } - - /* jump and over QQ_PACKET_TAIL */ - jump_len = (jump - conn->tcp_rxqueue) + 1; - purple_debug_warning("TCP_PENDING", "Find next tail at %d, jump %d\n", jump_len, jump_len + 1); - g_memmove(conn->tcp_rxqueue, jump, conn->tcp_rxlen - jump_len); - conn->tcp_rxlen -= jump_len; - continue; - } - - memset(pkt, 0, MAX_PACKET_SIZE); - g_memmove(pkt, conn->tcp_rxqueue + bytes, pkt_len - bytes); - - /* jump to next packet */ - conn->tcp_rxlen -= pkt_len; - if (conn->tcp_rxlen) { - /* purple_debug_info("TCP_PENDING", "shrink tcp_rxqueue to %d\n", conn->tcp_rxlen); */ - jump = g_memdup(conn->tcp_rxqueue + pkt_len, conn->tcp_rxlen); - g_free(conn->tcp_rxqueue); - conn->tcp_rxqueue = jump; - } else { - /* purple_debug_info("TCP_PENDING", "free tcp_rxqueue\n"); */ - g_free(conn->tcp_rxqueue); - conn->tcp_rxqueue = NULL; - } - - /* packet_process may call disconnect and destory data like conn - * do not call packet_process before jump, - * break if packet_process return FALSE */ - if (packet_process(gc, pkt, pkt_len - bytes) == FALSE) { - purple_debug_info("TCP_PENDING", "Connection has been destory\n"); - break; - } - } -} - -static void udp_pending(gpointer data, gint source, PurpleInputCondition cond) -{ - PurpleConnection *gc = NULL; - guint8 *buf; - gint buf_len; - - gc = (PurpleConnection *) data; - g_return_if_fail(gc != NULL); - - if(cond != PURPLE_INPUT_READ) { - purple_connection_error_reason(gc, - PURPLE_CONNECTION_ERROR_NETWORK_ERROR, - _("Socket error")); - return; - } - - buf = g_newa(guint8, MAX_PACKET_SIZE); - - /* here we have UDP proxy suppport */ - buf_len = read(source, buf, MAX_PACKET_SIZE); - if (buf_len <= 0) { - purple_connection_error_reason(gc, - PURPLE_CONNECTION_ERROR_NETWORK_ERROR, - _("Unable to read from socket")); - return; - } - - /* keep alive will be sent in 30 seconds since last_receive - * QQ need a keep alive packet in every 60 seconds - gc->last_received = time(NULL); - */ - - if (buf_len < QQ_UDP_HEADER_LENGTH) { - if (buf[0] != QQ_PACKET_TAG || buf[buf_len - 1] != QQ_PACKET_TAIL) { - qq_hex_dump(PURPLE_DEBUG_ERROR, "UDP_PENDING", - buf, buf_len, - "Received packet is too short, or no header and tail tag"); - return; - } - } - - /* packet_process may call disconnect and destory data like conn - * do not call packet_process before jump, - * break if packet_process return FALSE */ - packet_process(gc, buf, buf_len); -} - -static gint udp_send_out(PurpleConnection *gc, guint8 *data, gint data_len) -{ - qq_data *qd; - gint ret; - - g_return_val_if_fail(data != NULL && data_len > 0, -1); - - g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, -1); - qd = (qq_data *) gc->proto_data; - -#if 0 - purple_debug_info("UDP_SEND_OUT", "Send %d bytes to socket %d\n", data_len, qd->fd); -#endif - - errno = 0; - ret = send(qd->fd, data, data_len, 0); - if (ret < 0 && errno == EAGAIN) { - return ret; - } - - if (ret < 0) { - /* TODO: what to do here - do we really have to disconnect? */ - purple_debug_error("UDP_SEND_OUT", "Send failed: %d, %s\n", errno, g_strerror(errno)); - purple_connection_error_reason(gc, - PURPLE_CONNECTION_ERROR_NETWORK_ERROR, - g_strerror(errno)); - } - return ret; -} - -static void tcp_can_write(gpointer data, gint source, PurpleInputCondition cond) -{ - PurpleConnection *gc = (PurpleConnection *) data; - qq_data *qd; - qq_connection *conn; - int ret, writelen; - - g_return_if_fail(gc != NULL && gc->proto_data != NULL); - qd = (qq_data *) gc->proto_data; - - conn = connection_find(qd, source); - g_return_if_fail(conn != NULL); - - writelen = purple_circ_buffer_get_max_read(conn->tcp_txbuf); - if (writelen == 0) { - purple_input_remove(conn->can_write_handler); - conn->can_write_handler = 0; - return; - } - - ret = write(source, conn->tcp_txbuf->outptr, writelen); - purple_debug_info("TCP_CAN_WRITE", "total %d bytes is sent %d\n", writelen, ret); - - if (ret < 0 && errno == EAGAIN) - return; - else if (ret < 0) { - /* TODO: what to do here - do we really have to disconnect? */ - gchar *tmp = g_strdup_printf(_("Lost connection with server: %s"), - g_strerror(errno)); - purple_connection_error_reason(gc, - PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp); - g_free(tmp); - return; - } - - purple_circ_buffer_mark_read(conn->tcp_txbuf, ret); -} - -static gint tcp_send_out(PurpleConnection *gc, guint8 *data, gint data_len) -{ - qq_data *qd; - qq_connection *conn; - gint ret; - - g_return_val_if_fail(data != NULL && data_len > 0, -1); - - g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, -1); - qd = (qq_data *) gc->proto_data; - - conn = connection_find(qd, qd->fd); - g_return_val_if_fail(conn, -1); - -#if 0 - purple_debug_info("TCP_SEND_OUT", "Send %d bytes to socket %d\n", data_len, qd->fd); -#endif - - if (conn->can_write_handler == 0) { - ret = write(qd->fd, data, data_len); - } else { - ret = -1; - errno = EAGAIN; - } - - /* - purple_debug_info("TCP_SEND_OUT", - "Socket %d, total %d bytes is sent %d\n", qd->fd, data_len, ret); - */ - if (ret < 0 && errno == EAGAIN) { - /* socket is busy, send later */ - purple_debug_info("TCP_SEND_OUT", "Socket is busy and send later\n"); - ret = 0; - } else if (ret <= 0) { - /* TODO: what to do here - do we really have to disconnect? */ - gchar *tmp = g_strdup_printf(_("Lost connection with server: %s"), - g_strerror(errno)); - purple_debug_error("TCP_SEND_OUT", - "Send to socket %d failed: %d, %s\n", qd->fd, errno, g_strerror(errno)); - purple_connection_error_reason(gc, - PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp); - g_free(tmp); - return ret; - } - - if (ret < data_len) { - purple_debug_info("TCP_SEND_OUT", "Add %d bytes to buffer\n", data_len - ret); - if (conn->can_write_handler == 0) { - conn->can_write_handler = purple_input_add(qd->fd, PURPLE_INPUT_WRITE, tcp_can_write, gc); - } - if (conn->tcp_txbuf == NULL) { - conn->tcp_txbuf = purple_circ_buffer_new(4096); - } - purple_circ_buffer_append(conn->tcp_txbuf, data + ret, data_len - ret); - } - return ret; -} - -static gboolean network_timeout(gpointer data) -{ - PurpleConnection *gc = (PurpleConnection *) data; - qq_data *qd; - gboolean is_lost_conn; - - g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, TRUE); - qd = (qq_data *) gc->proto_data; - - is_lost_conn = qq_trans_scan(gc); - if (is_lost_conn) { - purple_connection_error_reason(gc, - PURPLE_CONNECTION_ERROR_NETWORK_ERROR, - _("Lost connection with server")); - return TRUE; - } - - if ( !qd->is_login ) { - return TRUE; - } - - qd->itv_count.keep_alive--; - if (qd->itv_count.keep_alive <= 0) { - qd->itv_count.keep_alive = qd->itv_config.keep_alive; - if (qd->client_version >= 2008) { - qq_request_keep_alive_2008(gc); - } else if (qd->client_version >= 2007) { - qq_request_keep_alive_2007(gc); - } else { - qq_request_keep_alive(gc); - } - return TRUE; - } - - if (qd->itv_config.update <= 0) { - return TRUE; - } - - qd->itv_count.update--; - if (qd->itv_count.update <= 0) { - qd->itv_count.update = qd->itv_config.update; - qq_update_online(gc, 0); - return TRUE; - } - - return TRUE; /* if return FALSE, timeout callback stops */ -} - -static void set_all_keys(PurpleConnection *gc) -{ - qq_data *qd; - const gchar *passwd; - guint8 *dest; - int dest_len = QQ_KEY_LENGTH; -#ifndef DEBUG - int bytes; -#endif - /* _qq_show_socket("Got login socket", source); */ - - g_return_if_fail(gc != NULL && gc->proto_data != NULL); - qd = (qq_data *) gc->proto_data; - - /* QQ use random seq, to minimize duplicated packets */ - srand(time(NULL)); - qd->send_seq = rand() & 0xffff; - - qd->is_login = FALSE; - qd->uid = strtoul(purple_account_get_username(purple_connection_get_account(gc)), NULL, 10); - -#ifdef DEBUG - memset(qd->ld.random_key, 0x01, sizeof(qd->ld.random_key)); -#else - for (bytes = 0; bytes < sizeof(qd->ld.random_key); bytes++) { - qd->ld.random_key[bytes] = (guint8) (rand() & 0xff); - } -#endif - - /* now generate md5 processed passwd */ - passwd = purple_account_get_password(purple_connection_get_account(gc)); - - /* use twice-md5 of user password as session key since QQ 2003iii */ - dest = qd->ld.pwd_md5; - qq_get_md5(dest, dest_len, (guint8 *)passwd, strlen(passwd)); - - dest = qd->ld.pwd_twice_md5; - qq_get_md5(dest, dest_len, qd->ld.pwd_md5, dest_len); -} - -/* the callback function after socket is built - * we setup the qq protocol related configuration here */ -static void connect_cb(gpointer data, gint source, const gchar *error_message) -{ - PurpleConnection *gc; - qq_data *qd; - qq_connection *conn; - - gc = (PurpleConnection *) data; - g_return_if_fail(gc != NULL && gc->proto_data != NULL); - - qd = (qq_data *) gc->proto_data; - - /* conn_data will be destoryed */ - qd->conn_data = NULL; - - if (!PURPLE_CONNECTION_IS_VALID(gc)) { - purple_debug_info("QQ_CONN", "Invalid connection\n"); - close(source); - return; - } - - if (source < 0) { /* socket returns -1 */ - purple_debug_info("QQ_CONN", - "Could not establish a connection with the server:\n%s\n", - error_message); - if (qd->connect_watcher > 0) purple_timeout_remove(qd->connect_watcher); - qd->connect_watcher = purple_timeout_add_seconds(QQ_CONNECT_INTERVAL, qq_connect_later, gc); - return; - } - - /* _qq_show_socket("Got login socket", source); */ - /* ok, already connected to the server */ - qd->fd = source; - conn = connection_create(qd, source); - g_return_if_fail( conn != NULL ); - - if (qd->use_tcp) { - /* events which match "PURPLE_INPUT_READ" of - * "source" would trigger the callback function */ - conn->input_handler = purple_input_add(source, PURPLE_INPUT_READ, tcp_pending, gc); - } else { - conn->input_handler = purple_input_add(source, PURPLE_INPUT_READ, udp_pending, gc); - } - - g_return_if_fail(qd->network_watcher == 0); - qd->network_watcher = purple_timeout_add_seconds(qd->itv_config.resend, network_timeout, gc); - - set_all_keys( gc ); - - if (qd->client_version >= 2007) { - purple_connection_update_progress(gc, _("Getting server"), 2, QQ_CONNECT_STEPS); - qq_request_get_server(gc); - return; - } - - purple_connection_update_progress(gc, _("Requesting token"), 2, QQ_CONNECT_STEPS); - qq_request_token(gc); -} - -#ifndef purple_proxy_connect_udp -static void udp_can_write(gpointer data, gint source, PurpleInputCondition cond) -{ - PurpleConnection *gc; - qq_data *qd; - socklen_t len; - int error=0, ret; - - gc = (PurpleConnection *) data; - g_return_if_fail(gc != NULL && gc->proto_data != NULL); - - qd = (qq_data *) gc->proto_data; - - - purple_debug_info("proxy", "Connected.\n"); - - /* - * getsockopt after a non-blocking connect returns -1 if something is - * really messed up (bad descriptor, usually). Otherwise, it returns 0 and - * error holds what connect would have returned if it blocked until now. - * Thus, error == 0 is success, error == EINPROGRESS means "try again", - * and anything else is a real error. - * - * (error == EINPROGRESS can happen after a select because the kernel can - * be overly optimistic sometimes. select is just a hint that you might be - * able to do something.) - */ - len = sizeof(error); - ret = getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len); - if (ret == 0 && error == EINPROGRESS) - return; /* we'll be called again later */ - - purple_input_remove(qd->udp_can_write_handler); - qd->udp_can_write_handler = 0; - if (ret < 0 || error != 0) { - if(ret != 0) - error = errno; - - close(source); - - purple_debug_error("proxy", "getsockopt SO_ERROR check: %s\n", g_strerror(error)); - - connect_cb(gc, -1, _("Unable to connect")); - return; - } - - connect_cb(gc, source, NULL); -} - -static void udp_host_resolved(GSList *hosts, gpointer data, const char *error_message) { - PurpleConnection *gc; - qq_data *qd; - struct sockaddr server_addr; - int addr_size; - gint fd = -1; - int flags; - - gc = (PurpleConnection *) data; - g_return_if_fail(gc != NULL && gc->proto_data != NULL); - - qd = (qq_data *) gc->proto_data; - - /* udp_query_data must be set as NULL. - * Otherwise purple_dnsquery_destroy in qq_disconnect cause glib double free error */ - qd->udp_query_data = NULL; - - if (!hosts || !hosts->data) { - purple_connection_error_reason(gc, - PURPLE_CONNECTION_ERROR_NETWORK_ERROR, - _("Unable to resolve hostname")); - return; - } - - addr_size = GPOINTER_TO_INT(hosts->data); - hosts = g_slist_remove(hosts, hosts->data); - memcpy(&server_addr, hosts->data, addr_size); - g_free(hosts->data); - - hosts = g_slist_remove(hosts, hosts->data); - while(hosts) { - hosts = g_slist_remove(hosts, hosts->data); - g_free(hosts->data); - hosts = g_slist_remove(hosts, hosts->data); - } - - fd = socket(PF_INET, SOCK_DGRAM, 0); - if (fd < 0) { - purple_debug_error("QQ", - "Unable to create socket: %s\n", g_strerror(errno)); - return; - } - - /* we use non-blocking mode to speed up connection */ - flags = fcntl(fd, F_GETFL); - fcntl(fd, F_SETFL, flags | O_NONBLOCK); -#ifndef _WIN32 - fcntl(fd, F_SETFD, FD_CLOEXEC); -#endif - - /* From Unix-socket-FAQ: http://www.faqs.org/faqs/unix-faq/socket/ - * - * If a UDP socket is unconnected, which is the normal state after a - * bind() call, then send() or write() are not allowed, since no - * destination is available; only sendto() can be used to send data. - * - * Calling connect() on the socket simply records the specified address - * and port number as being the desired communications partner. That - * means that send() or write() are now allowed; they use the destination - * address and port given on the connect call as the destination of packets. - */ - if (connect(fd, &server_addr, addr_size) >= 0) { - purple_debug_info("QQ", "Connected.\n"); - flags = fcntl(fd, F_GETFL); - fcntl(fd, F_SETFL, flags & ~O_NONBLOCK); - connect_cb(gc, fd, NULL); - return; - } - - /* [EINPROGRESS] - * The socket is marked as non-blocking and the connection cannot be - * completed immediately. It is possible to select for completion by - * selecting the socket for writing. - * [EINTR] - * A signal interrupted the call. - * The connection is established asynchronously. - */ - if ((errno == EINPROGRESS) || (errno == EINTR)) { - purple_debug_warning( "QQ", "Connect in asynchronous mode.\n"); - qd->udp_can_write_handler = purple_input_add(fd, PURPLE_INPUT_WRITE, udp_can_write, gc); - return; - } - - purple_debug_error("QQ", "Connection failed: %s\n", g_strerror(errno)); - close(fd); -} -#endif - -gboolean connect_to_server(PurpleConnection *gc, gchar *server, gint port) -{ - PurpleAccount *account ; - qq_data *qd; - - g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, FALSE); - account = purple_connection_get_account(gc); - qd = (qq_data *) gc->proto_data; - - if (server == NULL || server[0] == '\0' || port == 0) { - purple_connection_error_reason(gc, - PURPLE_CONNECTION_ERROR_NETWORK_ERROR, - _("Invalid server or port")); - return FALSE; - } - - purple_connection_update_progress(gc, _("Connecting to server"), 1, QQ_CONNECT_STEPS); - - purple_debug_info("QQ", "Connect to %s:%d\n", server, port); - - if (qd->conn_data != NULL) { - purple_proxy_connect_cancel(qd->conn_data); - qd->conn_data = NULL; - } - -#ifdef purple_proxy_connect_udp - if (qd->use_tcp) { - qd->conn_data = purple_proxy_connect(gc, account, server, port, connect_cb, gc); - } else { - qd->conn_data = purple_proxy_connect_udp(gc, account, server, port, connect_cb, gc); - } - if ( qd->conn_data == NULL ) { - purple_debug_error("QQ", "Couldn't create socket\n"); - return FALSE; - } -#else - /* QQ connection via UDP/TCP. - * Now use Purple proxy function to provide TCP proxy support, - * and qq_udp_proxy.c to add UDP proxy support (thanks henry) */ - if(qd->use_tcp) { - qd->conn_data = purple_proxy_connect(gc, account, server, port, connect_cb, gc); - if ( qd->conn_data == NULL ) { - purple_debug_error("QQ", "Unable to connect.\n"); - return FALSE; - } - return TRUE; - } - - purple_debug_info("QQ", "UDP Connect to %s:%d\n", server, port); - qd->udp_query_data = purple_dnsquery_a(server, port, udp_host_resolved, gc); - if ( qd->udp_query_data == NULL ) { - purple_debug_error("QQ", "Could not resolve hostname\n"); - return FALSE; - } -#endif - return TRUE; -} - -/* clean up qq_data structure and all its components - * always used before a redirectly connection */ -void qq_disconnect(PurpleConnection *gc) -{ - qq_data *qd; - - g_return_if_fail(gc != NULL && gc->proto_data != NULL); - qd = (qq_data *) gc->proto_data; - - purple_debug_info("QQ", "Disconnecting...\n"); - - if (qd->network_watcher > 0) { - purple_debug_info("QQ", "Remove network watcher\n"); - purple_timeout_remove(qd->network_watcher); - qd->network_watcher = 0; - } - - /* finish all I/O */ - if (qd->fd >= 0 && qd->is_login) { - qq_request_logout(gc); - } - - /* not connected */ - if (qd->conn_data != NULL) { - purple_debug_info("QQ", "Connect cancel\n"); - purple_proxy_connect_cancel(qd->conn_data); - qd->conn_data = NULL; - } -#ifndef purple_proxy_connect_udp - if (qd->udp_can_write_handler) { - purple_input_remove(qd->udp_can_write_handler); - qd->udp_can_write_handler = 0; - } - if (qd->udp_query_data != NULL) { - purple_debug_info("QQ", "destroy udp_query_data\n"); - purple_dnsquery_destroy(qd->udp_query_data); - qd->udp_query_data = NULL; - } -#endif - connection_free_all(qd); - qd->fd = -1; - - qq_trans_remove_all(gc); - - memset(qd->ld.random_key, 0, sizeof(qd->ld.random_key)); - memset(qd->ld.pwd_md5, 0, sizeof(qd->ld.pwd_md5)); - memset(qd->ld.pwd_twice_md5, 0, sizeof(qd->ld.pwd_twice_md5)); - memset(qd->ld.login_key, 0, sizeof(qd->ld.login_key)); - memset(qd->session_key, 0, sizeof(qd->session_key)); - memset(qd->session_md5, 0, sizeof(qd->session_md5)); - - qd->my_local_ip.s_addr = 0; - qd->my_local_port = 0; - qd->my_ip.s_addr = 0; - qd->my_port = 0; - - qq_room_data_free_all(gc); - qq_buddy_data_free_all(gc); -} - -static gint packet_encap(qq_data *qd, guint8 *buf, gint maxlen, guint16 cmd, guint16 seq, - guint8 *data, gint data_len) -{ - gint bytes = 0; - g_return_val_if_fail(qd != NULL && buf != NULL && maxlen > 0, -1); - g_return_val_if_fail(data != NULL && data_len > 0, -1); - - /* QQ TCP packet has two bytes in the begining defines packet length - * so leave room here to store packet size */ - if (qd->use_tcp) { - bytes += qq_put16(buf + bytes, 0x0000); - } - /* now comes the normal QQ packet as UDP */ - bytes += qq_put8(buf + bytes, QQ_PACKET_TAG); - bytes += qq_put16(buf + bytes, qd->client_tag); - bytes += qq_put16(buf + bytes, cmd); - - bytes += qq_put16(buf + bytes, seq); - - bytes += qq_put32(buf + bytes, qd->uid); - bytes += qq_putdata(buf + bytes, data, data_len); - bytes += qq_put8(buf + bytes, QQ_PACKET_TAIL); - - /* set TCP packet length at begin of the packet */ - if (qd->use_tcp) { - qq_put16(buf, bytes); - } - - return bytes; -} - -/* data has been encrypted before */ -static gint packet_send_out(PurpleConnection *gc, guint16 cmd, guint16 seq, guint8 *data, gint data_len) -{ - qq_data *qd; - guint8 *buf; - gint buf_len; - gint bytes_sent; - - g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, -1); - qd = (qq_data *)gc->proto_data; - g_return_val_if_fail(data != NULL && data_len > 0, -1); - - buf = g_newa(guint8, MAX_PACKET_SIZE); - memset(buf, 0, MAX_PACKET_SIZE); - buf_len = packet_encap(qd, buf, MAX_PACKET_SIZE, cmd, seq, data, data_len); - if (buf_len <= 0) { - return -1; - } - - qd->net_stat.sent++; - if (qd->use_tcp) { - bytes_sent = tcp_send_out(gc, buf, buf_len); - } else { - bytes_sent = udp_send_out(gc, buf, buf_len); - } - - return bytes_sent; -} - -gint qq_send_cmd_encrypted(PurpleConnection *gc, guint16 cmd, guint16 seq, - guint8 *encrypted, gint encrypted_len, gboolean is_save2trans) -{ - gint sent_len; - -#if 1 - /* qq_show_packet("qq_send_cmd_encrypted", data, data_len); */ - purple_debug_info("QQ", "<== [%05d] %s(0x%04X), datalen %d\n", - seq, qq_get_cmd_desc(cmd), cmd, encrypted_len); -#endif - - sent_len = packet_send_out(gc, cmd, seq, encrypted, encrypted_len); - if (is_save2trans) { - qq_trans_add_client_cmd(gc, cmd, seq, encrypted, encrypted_len, 0, 0); - } - return sent_len; -} - -/* Encrypt data with session_key, and send packet out */ -static gint send_cmd_detail(PurpleConnection *gc, guint16 cmd, guint16 seq, - guint8 *data, gint data_len, gboolean is_save2trans, - UPDCLS update_class, guint32 ship32) -{ - qq_data *qd; - guint8 *encrypted; - gint encrypted_len; - gint bytes_sent; - - g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, -1); - qd = (qq_data *)gc->proto_data; - g_return_val_if_fail(data != NULL && data_len > 0, -1); - - /* at most 17 bytes more */ - encrypted = g_newa(guint8, data_len + 17); - encrypted_len = qq_encrypt(encrypted, data, data_len, qd->session_key); - if (encrypted_len < 16) { - purple_debug_error("QQ_ENCRYPT", "Error len %d: [%05d] 0x%04X %s\n", - encrypted_len, seq, cmd, qq_get_cmd_desc(cmd)); - return -1; - } - - bytes_sent = packet_send_out(gc, cmd, seq, encrypted, encrypted_len); - - if (is_save2trans) { - qq_trans_add_client_cmd(gc, cmd, seq, encrypted, encrypted_len, - update_class, ship32); - } - return bytes_sent; -} - -gint qq_send_cmd_mess(PurpleConnection *gc, guint16 cmd, guint8 *data, gint data_len, - UPDCLS update_class, guint32 ship32) -{ - qq_data *qd; - guint16 seq; - - g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, -1); - qd = (qq_data *) gc->proto_data; - g_return_val_if_fail(data != NULL && data_len > 0, -1); - - seq = ++qd->send_seq; -#if 1 - purple_debug_info("QQ", "<== [%05d] %s(0x%04X), datalen %d\n", - seq, qq_get_cmd_desc(cmd), cmd, data_len); -#endif - return send_cmd_detail(gc, cmd, seq, data, data_len, TRUE, update_class, ship32); -} - -/* set seq and is_save2trans, then call send_cmd_detail */ -gint qq_send_cmd(PurpleConnection *gc, guint16 cmd, guint8 *data, gint data_len) -{ - qq_data *qd; - guint16 seq; - gboolean is_save2trans; - - g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, -1); - qd = (qq_data *) gc->proto_data; - g_return_val_if_fail(data != NULL && data_len > 0, -1); - - if (cmd != QQ_CMD_LOGOUT) { - seq = ++qd->send_seq; - is_save2trans = TRUE; - } else { - seq = 0xFFFF; - is_save2trans = FALSE; - } -#if 1 - purple_debug_info("QQ", "<== [%05d] %s(0x%04X), datalen %d\n", - seq, qq_get_cmd_desc(cmd), cmd, data_len); -#endif - return send_cmd_detail(gc, cmd, seq, data, data_len, is_save2trans, 0, 0); -} - -/* set seq and is_save2trans, then call send_cmd_detail */ -gint qq_send_server_reply(PurpleConnection *gc, guint16 cmd, guint16 seq, guint8 *data, gint data_len) -{ - qq_data *qd; - guint8 *encrypted; - gint encrypted_len; - gint bytes_sent; - - g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, -1); - qd = (qq_data *)gc->proto_data; - g_return_val_if_fail(data != NULL && data_len > 0, -1); - -#if 1 - purple_debug_info("QQ", "<== [SRV-%05d] %s(0x%04X), datalen %d\n", - seq, qq_get_cmd_desc(cmd), cmd, data_len); -#endif - /* at most 17 bytes more */ - encrypted = g_newa(guint8, data_len + 17); - encrypted_len = qq_encrypt(encrypted, data, data_len, qd->session_key); - if (encrypted_len < 16) { - purple_debug_error("QQ_ENCRYPT", "Error len %d: [%05d] 0x%04X %s\n", - encrypted_len, seq, cmd, qq_get_cmd_desc(cmd)); - return -1; - } - - bytes_sent = packet_send_out(gc, cmd, seq, encrypted, encrypted_len); - qq_trans_add_server_reply(gc, cmd, seq, encrypted, encrypted_len); - - return bytes_sent; -} - -static gint send_room_cmd(PurpleConnection *gc, guint8 room_cmd, guint32 room_id, - guint8 *data, gint data_len, UPDCLS update_class, guint32 ship32) -{ - qq_data *qd; - guint8 *buf; - gint buf_len; - guint8 *encrypted; - gint encrypted_len; - gint bytes_sent; - guint16 seq; - - g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, -1); - qd = (qq_data *) gc->proto_data; - - buf = g_newa(guint8, MAX_PACKET_SIZE); - memset(buf, 0, MAX_PACKET_SIZE); - - /* encap room_cmd and room id to buf*/ - buf_len = 0; - buf_len += qq_put8(buf + buf_len, room_cmd); - if (room_id != 0) { - /* id 0 is for QQ Demo Group, now they are closed*/ - buf_len += qq_put32(buf + buf_len, room_id); - } - if (data != NULL && data_len > 0) { - buf_len += qq_putdata(buf + buf_len, data, data_len); - } - - qd->send_seq++; - seq = qd->send_seq; - - /* Encrypt to encrypted with session_key */ - /* at most 17 bytes more */ - encrypted = g_newa(guint8, buf_len + 17); - encrypted_len = qq_encrypt(encrypted, buf, buf_len, qd->session_key); - if (encrypted_len < 16) { - purple_debug_error("QQ_ENCRYPT", "Error len %d: [%05d] %s (0x%02X)\n", - encrypted_len, seq, qq_get_room_cmd_desc(room_cmd), room_cmd); - return -1; - } - - bytes_sent = packet_send_out(gc, QQ_CMD_ROOM, seq, encrypted, encrypted_len); -#if 1 - /* qq_show_packet("send_room_cmd", buf, buf_len); */ - purple_debug_info("QQ", - "<== [%05d] %s (0x%02X) to room %d, datalen %d\n", - seq, qq_get_room_cmd_desc(room_cmd), room_cmd, room_id, buf_len); -#endif - - qq_trans_add_room_cmd(gc, seq, room_cmd, room_id, encrypted, encrypted_len, - update_class, ship32); - return bytes_sent; -} - -gint qq_send_room_cmd_mess(PurpleConnection *gc, guint8 room_cmd, guint32 room_id, - guint8 *data, gint data_len, UPDCLS update_class, guint32 ship32) -{ - g_return_val_if_fail(room_cmd > 0, -1); - return send_room_cmd(gc, room_cmd, room_id, data, data_len, update_class, ship32); -} - -gint qq_send_room_cmd(PurpleConnection *gc, guint8 room_cmd, guint32 room_id, - guint8 *data, gint data_len) -{ - g_return_val_if_fail(room_cmd > 0 && room_id > 0, -1); - return send_room_cmd(gc, room_cmd, room_id, data, data_len, 0, 0); -} - -gint qq_send_room_cmd_noid(PurpleConnection *gc, guint8 room_cmd, - guint8 *data, gint data_len) -{ - g_return_val_if_fail(room_cmd > 0, -1); - return send_room_cmd(gc, room_cmd, 0, data, data_len, 0, 0); -} - -gint qq_send_room_cmd_only(PurpleConnection *gc, guint8 room_cmd, guint32 room_id) -{ - g_return_val_if_fail(room_cmd > 0 && room_id > 0, -1); - return send_room_cmd(gc, room_cmd, room_id, NULL, 0, 0, 0); -} diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/qq/qq_network.h --- a/libpurple/protocols/qq/qq_network.h Thu May 05 03:40:29 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -/** - * @file qq_network.h - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * 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 02111-1301 USA - */ - -#ifndef _QQ_NETWORK_H -#define _QQ_NETWORK_H - -#include -#include "connection.h" - -#include "qq.h" - -#define QQ_CONNECT_STEPS 4 /* steps in connection */ - -gboolean qq_connect_later(gpointer data); -void qq_disconnect(PurpleConnection *gc); - -gint qq_send_cmd_encrypted(PurpleConnection *gc, guint16 cmd, guint16 seq, - guint8 *encrypted_data, gint encrypted_len, gboolean is_save2trans); -gint qq_send_cmd(PurpleConnection *gc, guint16 cmd, guint8 *data, gint datalen); -gint qq_send_cmd_mess(PurpleConnection *gc, guint16 cmd, guint8 *data, gint data_len, - UPDCLS update_class, guint32 ship32); - -gint qq_send_server_reply(PurpleConnection *gc, guint16 cmd, guint16 seq, - guint8 *data, gint data_len); - -gint qq_send_room_cmd(PurpleConnection *gc, guint8 room_cmd, guint32 room_id, - guint8 *data, gint data_len); -gint qq_send_room_cmd_mess(PurpleConnection *gc, guint8 room_cmd, guint32 room_id, - guint8 *data, gint data_len, UPDCLS update_class, guint32 ship32); -gint qq_send_room_cmd_only(PurpleConnection *gc, guint8 room_cmd, guint32 room_id); -gint qq_send_room_cmd_noid(PurpleConnection *gc, guint8 room_cmd, - guint8 *data, gint data_len); -#endif diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/qq/qq_process.c --- a/libpurple/protocols/qq/qq_process.c Thu May 05 03:40:29 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1157 +0,0 @@ -/** - * @file qq_network.c - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * 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 02111-1301 USA - */ - -#include "internal.h" -#include "cipher.h" -#include "debug.h" - -#include "buddy_info.h" -#include "buddy_list.h" -#include "buddy_opt.h" -#include "group_info.h" -#include "char_conv.h" -#include "qq_crypt.h" - -#include "group_internal.h" -#include "group_im.h" -#include "group_info.h" -#include "group_join.h" -#include "group_opt.h" - -#include "qq_define.h" -#include "qq_base.h" -#include "im.h" -#include "qq_process.h" -#include "packet_parse.h" -#include "qq_network.h" -#include "qq_trans.h" -#include "utils.h" -#include "buddy_memo.h" - -enum { - QQ_ROOM_CMD_REPLY_OK = 0x00, - QQ_ROOM_CMD_REPLY_SEARCH_ERROR = 0x02, - QQ_ROOM_CMD_REPLY_NOT_MEMBER = 0x0a -}; - -/* default process, decrypt and dump */ -static void process_unknow_cmd(PurpleConnection *gc,const gchar *title, guint8 *data, gint data_len, guint16 cmd, guint16 seq) -{ - gchar *msg; - - g_return_if_fail(data != NULL && data_len != 0); - - qq_show_packet(title, data, data_len); - - qq_hex_dump(PURPLE_DEBUG_WARNING, "QQ", - data, data_len, - ">>> [%d] %s -> [default] decrypt and dump", - seq, qq_get_cmd_desc(cmd)); - - msg = g_strdup_printf("Unknow command 0x%02X, %s", cmd, qq_get_cmd_desc(cmd)); - purple_notify_info(gc, _("QQ Error"), title, msg); - g_free(msg); -} - -/* parse the reply to send_im */ -static void do_im_ack(guint8 *data, gint data_len, PurpleConnection *gc) -{ - g_return_if_fail(data != NULL && data_len != 0); - - if (data[0] != 0) { - purple_debug_warning("QQ", "Failed sent IM\n"); - purple_notify_error(gc, _("Error"), _("Unable to send message."), NULL); - return; - } - - purple_debug_info("QQ", "OK sent IM\n"); -} - -static void do_server_news(PurpleConnection *gc, guint8 *data, gint data_len) -{ - qq_data *qd = (qq_data *) gc->proto_data; - gint bytes; - gchar *title, *brief, *url; - gchar *content; - - g_return_if_fail(data != NULL && data_len != 0); - - /* qq_show_packet("Rcv news", data, data_len); */ - - bytes = 4; /* skip unknown 4 bytes */ - - bytes += qq_get_vstr(&title, QQ_CHARSET_DEFAULT, data + bytes); - bytes += qq_get_vstr(&brief, QQ_CHARSET_DEFAULT, data + bytes); - bytes += qq_get_vstr(&url, QQ_CHARSET_DEFAULT, data + bytes); - - content = g_strdup_printf(_("Server News:\n%s\n%s\n%s"), title, brief, url); - - if (qd->is_show_news) { - qq_got_message(gc, content); - } else { - purple_debug_info("QQ", "QQ Server news:\n%s\n", content); - } - g_free(title); - g_free(brief); - g_free(url); - g_free(content); -} - -static void do_got_sms(PurpleConnection *gc, guint8 *data, gint data_len) -{ - gint bytes; - gchar *mobile = NULL; - gchar *msg = NULL; - gchar *msg_utf8 = NULL; - gchar *msg_formated; - - g_return_if_fail(data != NULL && data_len > 26); - - qq_show_packet("Rcv sms", data, data_len); - - bytes = 0; - bytes += 1; /* skip 0x00 */ - mobile = g_strndup((gchar *)data + bytes, 20); - bytes += 20; - bytes += 5; /* skip 0x(49 11 98 d5 03)*/ - if (bytes < data_len) { - msg = g_strndup((gchar *)data + bytes, data_len - bytes); - msg_utf8 = qq_to_utf8(msg, QQ_CHARSET_DEFAULT); - g_free(msg); - } else { - msg_utf8 = g_strdup(""); - } - - msg_formated = g_strdup_printf(_("%s:%s"), mobile, msg_utf8); - - qq_got_message(gc, msg_formated); - - g_free(msg_formated); - g_free(msg_utf8); - g_free(mobile); -} - -static void do_msg_sys_30(PurpleConnection *gc, guint8 *data, gint data_len) -{ - gint len; - guint8 reply; - gchar **segments, *msg_utf8; - - g_return_if_fail(data != NULL && data_len != 0); - - len = data_len; - - if (NULL == (segments = split_data(data, len, "\x2f", 2))) - return; - - reply = strtol(segments[0], NULL, 10); - if (reply == 1) - purple_debug_warning("QQ", "We are kicked out by QQ server\n"); - - msg_utf8 = qq_to_utf8(segments[1], QQ_CHARSET_DEFAULT); - qq_got_message(gc, msg_utf8); -} - -static void do_msg_sys_4c(PurpleConnection *gc, guint8 *data, gint data_len) -{ - gint bytes; - gint msg_len; - GString *content; - gchar *msg = NULL; - - g_return_if_fail(data != NULL && data_len > 0); - - bytes = 6; /* skip 0x(06 00 01 1e 01 1c)*/ - - content = g_string_new(""); - while (bytes < data_len) { - msg_len = qq_get_vstr(&msg, QQ_CHARSET_DEFAULT, data + bytes); - g_string_append(content, msg); - g_string_append(content, "\n"); - g_free(msg); - - if (msg_len <= 1) { - break; - } - bytes += msg_len; - } - if (bytes != data_len) { - purple_debug_warning("QQ", "Failed to read QQ_MSG_SYS_4C\n"); - qq_show_packet("do_msg_sys_4c", data, data_len); - } - qq_got_message(gc, content->str); - g_string_free(content, FALSE); -} - -static const gchar *get_im_type_desc(gint type) -{ - switch (type) { - case QQ_MSG_TO_BUDDY: - return "QQ_MSG_TO_BUDDY"; - case QQ_MSG_TO_UNKNOWN: - return "QQ_MSG_TO_UNKNOWN"; - case QQ_MSG_QUN_IM_UNKNOWN: - return "QQ_MSG_QUN_IM_UNKNOWN"; - case QQ_MSG_ADD_TO_QUN: - return "QQ_MSG_ADD_TO_QUN"; - case QQ_MSG_DEL_FROM_QUN: - return "QQ_MSG_DEL_FROM_QUN"; - case QQ_MSG_APPLY_ADD_TO_QUN: - return "QQ_MSG_APPLY_ADD_TO_QUN"; - case QQ_MSG_CREATE_QUN: - return "QQ_MSG_CREATE_QUN"; - case QQ_MSG_SYS_30: - return "QQ_MSG_SYS_30"; - case QQ_MSG_SYS_4C: - return "QQ_MSG_SYS_4C"; - case QQ_MSG_APPROVE_APPLY_ADD_TO_QUN: - return "QQ_MSG_APPROVE_APPLY_ADD_TO_QUN"; - case QQ_MSG_REJCT_APPLY_ADD_TO_QUN: - return "QQ_MSG_REJCT_APPLY_ADD_TO_QUN"; - case QQ_MSG_TEMP_QUN_IM: - return "QQ_MSG_TEMP_QUN_IM"; - case QQ_MSG_QUN_IM: - return "QQ_MSG_QUN_IM"; - case QQ_MSG_NEWS: - return "QQ_MSG_NEWS"; - case QQ_MSG_SMS: - return "QQ_MSG_SMS"; - case QQ_MSG_EXTEND: - return "QQ_MSG_EXTEND"; - case QQ_MSG_EXTEND_85: - return "QQ_MSG_EXTEND_85"; - default: - return "QQ_MSG_UNKNOWN"; - } -} - -/* I receive a message, mainly it is text msg, - * but we need to proess other types (group etc) */ -static void process_private_msg(guint8 *data, gint data_len, guint16 seq, PurpleConnection *gc) -{ - qq_data *qd; - gint bytes; - - struct { - UID uid_from; - UID uid_to; - guint32 seq; - struct in_addr ip_from; - guint16 port_from; - guint16 msg_type; - } header; - - g_return_if_fail(data != NULL && data_len != 0); - - qd = (qq_data *) gc->proto_data; - - if (data_len < 16) { /* we need to ack with the first 16 bytes */ - purple_debug_error("QQ", "MSG is too short\n"); - return; - } else { - /* when we receive a message, - * we send an ACK which is the first 16 bytes of incoming packet */ - qq_send_server_reply(gc, QQ_CMD_RECV_IM, seq, data, 16); - } - - /* check len first */ - if (data_len < 20) { /* length of im_header */ - purple_debug_error("QQ", "Invald MSG header, len %d < 20\n", data_len); - return; - } - - bytes = 0; - bytes += qq_get32(&(header.uid_from), data + bytes); - bytes += qq_get32(&(header.uid_to), data + bytes); - bytes += qq_get32(&(header.seq), data + bytes); - /* if the message is delivered via server, it is server IP/port */ - bytes += qq_getIP(&(header.ip_from), data + bytes); - bytes += qq_get16(&(header.port_from), data + bytes); - bytes += qq_get16(&(header.msg_type), data + bytes); - /* im_header prepared */ - - if (header.uid_to != qd->uid) { /* should not happen */ - purple_debug_error("QQ", "MSG to %u, NOT me\n", header.uid_to); - return; - } - - /* check bytes */ - if (bytes >= data_len - 1) { - purple_debug_warning("QQ", "Empty MSG\n"); - return; - } - - switch (header.msg_type) { - case QQ_MSG_NEWS: - do_server_news(gc, data + bytes, data_len - bytes); - break; - case QQ_MSG_SMS: - do_got_sms(gc, data + bytes, data_len - bytes); - break; - case QQ_MSG_EXTEND: - case QQ_MSG_EXTEND_85: - purple_debug_info("QQ", "MSG from buddy [%d]\n", header.uid_from); - qq_process_extend_im(gc, data + bytes, data_len - bytes); - break; - case QQ_MSG_TO_UNKNOWN: - case QQ_MSG_TO_BUDDY: - purple_debug_info("QQ", "MSG from buddy [%d]\n", header.uid_from); - qq_process_im(gc, data + bytes, data_len - bytes); - break; - case QQ_MSG_QUN_IM_UNKNOWN: - case QQ_MSG_TEMP_QUN_IM: - case QQ_MSG_QUN_IM: - purple_debug_info("QQ", "MSG from room [%d]\n", header.uid_from); - qq_process_room_im(data + bytes, data_len - bytes, header.uid_from, gc, header.msg_type); - break; - case QQ_MSG_ADD_TO_QUN: - purple_debug_info("QQ", "Notice from [%d], Added\n", header.uid_from); - /* uid_from is group id - * we need this to create a dummy group and add to blist */ - qq_process_room_buddy_joined(data + bytes, data_len - bytes, header.uid_from, gc); - break; - case QQ_MSG_DEL_FROM_QUN: - purple_debug_info("QQ", "Notice from room [%d], Removed\n", header.uid_from); - /* uid_from is group id */ - qq_process_room_buddy_removed(data + bytes, data_len - bytes, header.uid_from, gc); - break; - case QQ_MSG_APPLY_ADD_TO_QUN: - purple_debug_info("QQ", "Notice from room [%d], Joined\n", header.uid_from); - /* uid_from is group id */ - qq_process_room_buddy_request_join(data + bytes, data_len - bytes, header.uid_from, gc); - break; - case QQ_MSG_APPROVE_APPLY_ADD_TO_QUN: - purple_debug_info("QQ", "Notice from room [%d], Confirm add in\n", - header.uid_from); - /* uid_from is group id */ - qq_process_room_buddy_approved(data + bytes, data_len - bytes, header.uid_from, gc); - break; - case QQ_MSG_REJCT_APPLY_ADD_TO_QUN: - purple_debug_info("QQ", "Notice from room [%d], Refuse add in\n", - header.uid_from); - /* uid_from is group id */ - qq_process_room_buddy_rejected(data + bytes, data_len - bytes, header.uid_from, gc); - break; - case QQ_MSG_SYS_30: - do_msg_sys_30(gc, data + bytes, data_len - bytes); - break; - case QQ_MSG_SYS_4C: - do_msg_sys_4c(gc, data + bytes, data_len - bytes); - break; - default: - purple_debug_warning("QQ", "MSG from %u, unknown type %s [0x%04X]\n", - header.uid_from, get_im_type_desc(header.msg_type), header.msg_type); - qq_show_packet("MSG header", data, bytes); - if (data_len - bytes > 0) { - qq_show_packet("MSG data", data + bytes, data_len - bytes); - } - break; - } -} - -/* Send ACK if the sys message needs an ACK */ -static void request_server_ack(PurpleConnection *gc, gchar *funct_str, gchar *from, guint16 seq) -{ - guint8 *raw_data; - gint bytes; - guint8 bar; - - g_return_if_fail(funct_str != NULL && from != NULL); - - bar = 0x1e; - raw_data = g_newa(guint8, strlen(funct_str) + strlen(from) + 16); - - bytes = 0; - bytes += qq_putdata(raw_data + bytes, (guint8 *)funct_str, strlen(funct_str)); - bytes += qq_put8(raw_data + bytes, bar); - bytes += qq_putdata(raw_data + bytes, (guint8 *)from, strlen(from)); - bytes += qq_put8(raw_data + bytes, bar); - bytes += qq_put16(raw_data + bytes, seq); - - qq_send_server_reply(gc, QQ_CMD_ACK_SYS_MSG, 0, raw_data, bytes); -} - -static void do_server_notice(PurpleConnection *gc, gchar *from, gchar *to, - guint8 *data, gint data_len) -{ - qq_data *qd = (qq_data *) gc->proto_data; - gchar *msg, *msg_utf8; - gchar *title, *content; - - g_return_if_fail(from != NULL && to != NULL && data_len > 0); - - msg = g_strndup((gchar *)data, data_len); - msg_utf8 = qq_to_utf8(msg, QQ_CHARSET_DEFAULT); - g_free(msg); - if (msg_utf8 == NULL) { - purple_debug_error("QQ", "Recv NULL sys msg from %s to %s, discard\n", - from, to); - return; - } - - title = g_strdup_printf(_("From %s:"), from); - content = g_strdup_printf(_("Server notice From %s: \n%s"), from, msg_utf8); - - if (qd->is_show_notice) { - qq_got_message(gc, content); - } else { - purple_debug_info("QQ", "QQ Server notice from %s:\n%s\n", from, msg_utf8); - } - g_free(msg_utf8); - g_free(title); - g_free(content); -} - -static void process_server_msg(PurpleConnection *gc, guint8 *data, gint data_len, guint16 seq) -{ - qq_data *qd; - guint8 *data_str, i = 0; - gchar **segments, **seg; - gchar *funct_str, *from, *to; - gint bytes, funct; - - g_return_if_fail(data != NULL && data_len != 0); - - qd = (qq_data *) gc->proto_data; - - data_str = g_newa(guint8, data_len + 1); - g_memmove(data_str, data, data_len); - data_str[data_len] = 0x00; - - segments = g_strsplit((gchar *) data_str, "\x1f", 0); - g_return_if_fail(segments != NULL); - for (seg = segments; *seg != NULL; seg++) - i++; - if (i < 3) { - purple_debug_warning("QQ", "Server message segments is less than 3\n"); - g_strfreev(segments); - return; - } - - bytes = 0; - funct_str = segments[0]; - bytes += strlen(funct_str) + 1; - from = segments[1]; - bytes += strlen(from) + 1; - to = segments[2]; - bytes += strlen(to) + 1; - - request_server_ack(gc, funct_str, from, seq); - - /* qq_show_packet("Server MSG", data, data_len); */ - if (strtoul(to, NULL, 10) != qd->uid) { /* not to me */ - purple_debug_error("QQ", "Recv sys msg to [%s], not me!, discard\n", to); - g_strfreev(segments); - return; - } - - funct = strtol(funct_str, NULL, 10); - switch (funct) { - case QQ_SERVER_BUDDY_ADDED: - case QQ_SERVER_BUDDY_ADD_REQUEST: - case QQ_SERVER_BUDDY_ADDED_ME: - case QQ_SERVER_BUDDY_REJECTED_ME: - case QQ_SERVER_BUDDY_ADD_REQUEST_EX: - case QQ_SERVER_BUDDY_ADDING_EX: - case QQ_SERVER_BUDDY_ADDED_ANSWER: - case QQ_SERVER_BUDDY_ADDED_EX: - qq_process_buddy_from_server(gc, funct, from, to, data + bytes, data_len - bytes); - break; - case QQ_SERVER_NOTICE: - do_server_notice(gc, from, to, data + bytes, data_len - bytes); - break; - case QQ_SERVER_NEW_CLIENT: - purple_debug_warning("QQ", "QQ Server has newer client version\n"); - break; - default: - qq_show_packet("Unknown sys msg", data, data_len); - purple_debug_warning("QQ", "Recv unknown sys msg code: %s\n", funct_str); - break; - } - g_strfreev(segments); -} - -void qq_proc_server_cmd(PurpleConnection *gc, guint16 cmd, guint16 seq, guint8 *rcved, gint rcved_len) -{ - qq_data *qd; - - guint8 *data; - gint data_len; - - g_return_if_fail (gc != NULL && gc->proto_data != NULL); - qd = (qq_data *) gc->proto_data; - - data = g_newa(guint8, rcved_len); - data_len = qq_decrypt(data, rcved, rcved_len, qd->session_key); - if (data_len < 0) { - purple_debug_warning("QQ", - "Can not decrypt server cmd by session key, [%05d], 0x%04X %s, len %d\n", - seq, cmd, qq_get_cmd_desc(cmd), rcved_len); - qq_show_packet("Can not decrypted", rcved, rcved_len); - return; - } - - if (data_len <= 0) { - purple_debug_warning("QQ", - "Server cmd decrypted is empty, [%05d], 0x%04X %s, len %d\n", - seq, cmd, qq_get_cmd_desc(cmd), rcved_len); - return; - } - - /* now process the packet */ - switch (cmd) { - case QQ_CMD_RECV_IM: - process_private_msg(data, data_len, seq, gc); - break; - case QQ_CMD_RECV_MSG_SYS: - process_server_msg(gc, data, data_len, seq); - break; - case QQ_CMD_BUDDY_CHANGE_STATUS: - qq_process_buddy_change_status(data, data_len, gc); - break; - default: - process_unknow_cmd(gc, _("Unknown SERVER CMD"), data, data_len, cmd, seq); - break; - } -} - -static void process_room_cmd_notify(PurpleConnection *gc, - guint8 room_cmd, guint8 room_id, guint8 reply, guint8 *data, gint data_len) -{ - gchar *prim; - gchar *msg, *msg_utf8; - g_return_if_fail(data != NULL && data_len > 0); - - msg = g_strndup((gchar *) data, data_len); /* it will append 0x00 */ - msg_utf8 = qq_to_utf8(msg, QQ_CHARSET_DEFAULT); - g_free(msg); - - prim = g_strdup_printf(_("Error reply of %s(0x%02X)\nRoom %u, reply 0x%02X"), - qq_get_room_cmd_desc(room_cmd), room_cmd, room_id, reply); - - purple_notify_error(gc, _("QQ Qun Command"), prim, msg_utf8); - - g_free(prim); - g_free(msg_utf8); -} - -void qq_update_room(PurpleConnection *gc, guint8 room_cmd, guint32 room_id) -{ - gint ret; - - g_return_if_fail (gc != NULL); - - switch (room_cmd) { - case 0: - qq_send_room_cmd_mess(gc, QQ_ROOM_CMD_GET_INFO, room_id, NULL, 0, - QQ_CMD_CLASS_UPDATE_ROOM, 0); - break; - case QQ_ROOM_CMD_GET_INFO: - ret = qq_request_room_get_buddies(gc, room_id, QQ_CMD_CLASS_UPDATE_ROOM); - if (ret <= 0) { - qq_send_room_cmd_mess(gc, QQ_ROOM_CMD_GET_ONLINES, room_id, NULL, 0, - QQ_CMD_CLASS_UPDATE_ROOM, 0); - } - break; - case QQ_ROOM_CMD_GET_BUDDIES: - qq_send_room_cmd_mess(gc, QQ_ROOM_CMD_GET_ONLINES, room_id, NULL, 0, - QQ_CMD_CLASS_UPDATE_ROOM, 0); - break; - case QQ_ROOM_CMD_GET_ONLINES: - /* last command */ - default: - break; - } -} - -void qq_update_all_rooms(PurpleConnection *gc, guint8 room_cmd, guint32 room_id) -{ - gboolean is_new_turn = FALSE; - guint32 next_id; - - g_return_if_fail(gc != NULL); - - next_id = qq_room_get_next(gc, room_id); - purple_debug_info("QQ", "Update rooms, next id %u, prev id %u\n", next_id, room_id); - - if (next_id <= 0) { - if (room_id > 0) { - is_new_turn = TRUE; - next_id = qq_room_get_next(gc, 0); - purple_debug_info("QQ", "New turn, id %u\n", next_id); - } else { - purple_debug_info("QQ", "No room. Finished update\n"); - return; - } - } - - switch (room_cmd) { - case 0: - qq_send_room_cmd_mess(gc, QQ_ROOM_CMD_GET_INFO, next_id, NULL, 0, - QQ_CMD_CLASS_UPDATE_ALL, 0); - break; - case QQ_ROOM_CMD_GET_INFO: - if (!is_new_turn) { - qq_send_room_cmd_mess(gc, QQ_ROOM_CMD_GET_INFO, next_id, NULL, 0, - QQ_CMD_CLASS_UPDATE_ALL, 0); - } else { - qq_request_room_get_buddies(gc, next_id, QQ_CMD_CLASS_UPDATE_ALL); - } - break; - case QQ_ROOM_CMD_GET_BUDDIES: - /* last command */ - if (!is_new_turn) { - qq_request_room_get_buddies(gc, next_id, QQ_CMD_CLASS_UPDATE_ALL); - } else { - purple_debug_info("QQ", "Finished update\n"); - } - break; - default: - break; - } -} - -void qq_update_all(PurpleConnection *gc, guint16 cmd) -{ - qq_data *qd; - - g_return_if_fail (gc != NULL && gc->proto_data != NULL); - qd = (qq_data *) gc->proto_data; - - switch (cmd) { - case 0: - qq_request_buddy_info(gc, qd->uid, QQ_CMD_CLASS_UPDATE_ALL, 0); - break; - case QQ_CMD_GET_BUDDY_INFO: - qq_request_change_status(gc, QQ_CMD_CLASS_UPDATE_ALL); - break; - case QQ_CMD_CHANGE_STATUS: - qq_request_get_buddies(gc, 0, QQ_CMD_CLASS_UPDATE_ALL); - break; - case QQ_CMD_GET_BUDDIES_LIST: - qq_request_get_buddies_and_rooms(gc, 0, QQ_CMD_CLASS_UPDATE_ALL); - break; - case QQ_CMD_GET_BUDDIES_AND_ROOMS: - if (qd->client_version >= 2007) { - /* QQ2007/2008 can not get buddies level*/ - qq_request_get_buddies_online(gc, 0, QQ_CMD_CLASS_UPDATE_ALL); - } else { - qq_request_get_buddies_level(gc, QQ_CMD_CLASS_UPDATE_ALL); - } - break; - case QQ_CMD_GET_LEVEL: - qq_request_get_buddies_online(gc, 0, QQ_CMD_CLASS_UPDATE_ALL); - break; - case QQ_CMD_GET_BUDDIES_ONLINE: - /* last command */ - qq_update_all_rooms(gc, 0, 0); - break; - default: - break; - } - qd->online_last_update = time(NULL); -} - -static void update_all_rooms_online(PurpleConnection *gc, guint8 room_cmd, guint32 room_id) -{ - guint32 next_id; - - g_return_if_fail (gc != NULL); - - next_id = qq_room_get_next_conv(gc, room_id); - if (next_id <= 0 && room_id <= 0) { - purple_debug_info("QQ", "No room in conversation, no update online buddies\n"); - return; - } - if (next_id <= 0 ) { - purple_debug_info("QQ", "finished update rooms' online buddies\n"); - return; - } - - switch (room_cmd) { - case 0: - qq_send_room_cmd_mess(gc, QQ_ROOM_CMD_GET_ONLINES, next_id, NULL, 0, - QQ_CMD_CLASS_UPDATE_ALL, 0); - break; - case QQ_ROOM_CMD_GET_ONLINES: - qq_send_room_cmd_mess(gc, QQ_ROOM_CMD_GET_ONLINES, next_id, NULL, 0, - QQ_CMD_CLASS_UPDATE_ALL, 0); - break; - default: - break; - } -} - -void qq_update_online(PurpleConnection *gc, guint16 cmd) -{ - qq_data *qd; - g_return_if_fail (gc != NULL && gc->proto_data != NULL); - qd = (qq_data *) gc->proto_data; - - switch (cmd) { - case 0: - qq_request_get_buddies_online(gc, 0, QQ_CMD_CLASS_UPDATE_ONLINE); - break; - case QQ_CMD_GET_BUDDIES_ONLINE: - /* last command */ - update_all_rooms_online(gc, 0, 0); - break; - default: - break; - } - qd->online_last_update = time(NULL); -} - -void qq_proc_room_cmds(PurpleConnection *gc, guint16 seq, - guint8 room_cmd, guint32 room_id, guint8 *rcved, gint rcved_len, - UPDCLS update_class, guint32 ship32) -{ - qq_data *qd; - guint8 *data; - gint data_len; - qq_room_data *rmd; - gint bytes; - guint8 reply_cmd, reply; - - g_return_if_fail (gc != NULL && gc->proto_data != NULL); - qd = (qq_data *) gc->proto_data; - - data = g_newa(guint8, rcved_len); - data_len = qq_decrypt(data, rcved, rcved_len, qd->session_key); - if (data_len < 0) { - purple_debug_warning("QQ", - "Can not decrypt room cmd by session key, [%05d], 0x%02X %s for %d, len %d\n", - seq, room_cmd, qq_get_room_cmd_desc(room_cmd), room_id, rcved_len); - qq_show_packet("Can not decrypted", rcved, rcved_len); - return; - } - - if (room_id <= 0) { - purple_debug_warning("QQ", - "Invaild room id, [%05d], 0x%02X %s for %d, len %d\n", - seq, room_cmd, qq_get_room_cmd_desc(room_cmd), room_id, rcved_len); - /* Some room cmd has no room id, like QQ_ROOM_CMD_SEARCH */ - } - - if (data_len <= 2) { - purple_debug_warning("QQ", - "Invaild len of room cmd decrypted, [%05d], 0x%02X %s for %d, len %d\n", - seq, room_cmd, qq_get_room_cmd_desc(room_cmd), room_id, rcved_len); - return; - } - - bytes = 0; - bytes += qq_get8(&reply_cmd, data + bytes); - bytes += qq_get8(&reply, data + bytes); - - if (reply_cmd != room_cmd) { - purple_debug_warning("QQ", - "Missing room cmd in reply 0x%02X %s, [%05d], 0x%02X %s for %d, len %d\n", - reply_cmd, qq_get_room_cmd_desc(reply_cmd), - seq, room_cmd, qq_get_room_cmd_desc(room_cmd), room_id, rcved_len); - } - - /* now process the packet */ - if (reply != QQ_ROOM_CMD_REPLY_OK) { - switch (reply) { /* this should be all errors */ - case QQ_ROOM_CMD_REPLY_NOT_MEMBER: - rmd = qq_room_data_find(gc, room_id); - if (rmd == NULL) { - purple_debug_warning("QQ", - "Missing room id in [%05d], 0x%02X %s for %d, len %d\n", - seq, room_cmd, qq_get_room_cmd_desc(room_cmd), room_id, rcved_len); - } else { - purple_debug_warning("QQ", - "Not a member of room \"%s\"\n", rmd->title_utf8); - rmd->my_role = QQ_ROOM_ROLE_NO; - } - break; - case QQ_ROOM_CMD_REPLY_SEARCH_ERROR: - if (qd->roomlist != NULL) { - if (purple_roomlist_get_in_progress(qd->roomlist)) - purple_roomlist_set_in_progress(qd->roomlist, FALSE); - } - default: - process_room_cmd_notify(gc, reply_cmd, room_id, reply, data + bytes, data_len - bytes); - } - return; - } - - /* seems ok so far, so we process the reply according to sub_cmd */ - switch (reply_cmd) { - case QQ_ROOM_CMD_GET_INFO: - qq_process_room_cmd_get_info(data + bytes, data_len - bytes, ship32, gc); - break; - case QQ_ROOM_CMD_CREATE: - qq_group_process_create_group_reply(data + bytes, data_len - bytes, gc); - break; - case QQ_ROOM_CMD_CHANGE_INFO: - qq_group_process_modify_info_reply(data + bytes, data_len - bytes, gc); - break; - case QQ_ROOM_CMD_MEMBER_OPT: - qq_group_process_modify_members_reply(data + bytes, data_len - bytes, gc); - break; - case QQ_ROOM_CMD_ACTIVATE: - qq_group_process_activate_group_reply(data + bytes, data_len - bytes, gc); - break; - case QQ_ROOM_CMD_SEARCH: - qq_process_room_search(gc, data + bytes, data_len - bytes, ship32); - break; - case QQ_ROOM_CMD_JOIN: - qq_process_group_cmd_join_group(data + bytes, data_len - bytes, gc); - break; - case QQ_ROOM_CMD_AUTH: - qq_process_group_cmd_join_group_auth(data + bytes, data_len - bytes, gc); - break; - case QQ_ROOM_CMD_QUIT: - qq_process_group_cmd_exit_group(data + bytes, data_len - bytes, gc); - break; - case QQ_ROOM_CMD_SEND_IM: - qq_process_room_send_im(gc, data + bytes, data_len - bytes); - break; - case QQ_ROOM_CMD_SEND_IM_EX: - qq_process_room_send_im_ex(gc, data + bytes, data_len - bytes); - break; - case QQ_ROOM_CMD_GET_ONLINES: - qq_process_room_cmd_get_onlines(data + bytes, data_len - bytes, gc); - break; - case QQ_ROOM_CMD_GET_BUDDIES: - qq_process_room_cmd_get_buddies(data + bytes, data_len - bytes, gc); - break; - default: - purple_debug_warning("QQ", "Unknow room cmd 0x%02X %s\n", - reply_cmd, qq_get_room_cmd_desc(reply_cmd)); - } - - if (update_class == QQ_CMD_CLASS_NONE) - return; - - if (update_class == QQ_CMD_CLASS_UPDATE_ALL) { - qq_update_all_rooms(gc, room_cmd, room_id); - return; - } - if (update_class == QQ_CMD_CLASS_UPDATE_ONLINE) { - update_all_rooms_online(gc, room_cmd, room_id); - return; - } - if (update_class == QQ_CMD_CLASS_UPDATE_ROOM) { - qq_update_room(gc, room_cmd, room_id); - } -} - -guint8 qq_proc_login_cmds(PurpleConnection *gc, guint16 cmd, guint16 seq, - guint8 *rcved, gint rcved_len, UPDCLS update_class, guint32 ship32) -{ - qq_data *qd; - guint8 *data = NULL; - gint data_len = 0; - guint ret_8 = QQ_LOGIN_REPLY_ERR; - - g_return_val_if_fail (gc != NULL && gc->proto_data != NULL, QQ_LOGIN_REPLY_ERR); - qd = (qq_data *) gc->proto_data; - - g_return_val_if_fail(rcved_len > 0, QQ_LOGIN_REPLY_ERR); - data = g_newa(guint8, rcved_len); - - switch (cmd) { - case QQ_CMD_TOKEN: - if (qq_process_token(gc, rcved, rcved_len) == QQ_LOGIN_REPLY_OK) { - if (qd->client_version >= 2007) { - qq_request_token_ex(gc); - } else { - qq_request_login(gc); - } - return QQ_LOGIN_REPLY_OK; - } - return QQ_LOGIN_REPLY_ERR; - case QQ_CMD_GET_SERVER: - case QQ_CMD_TOKEN_EX: - data_len = qq_decrypt(data, rcved, rcved_len, qd->ld.random_key); - break; - case QQ_CMD_CHECK_PWD: - /* May use password_twice_md5 in the past version like QQ2005 */ - data_len = qq_decrypt(data, rcved, rcved_len, qd->ld.random_key); - if (data_len >= 0) { - purple_debug_warning("QQ", "Decrypt login packet by random_key, %d bytes\n", data_len); - } else { - data_len = qq_decrypt(data, rcved, rcved_len, qd->ld.pwd_twice_md5); - if (data_len >= 0) { - purple_debug_warning("QQ", "Decrypt login packet by pwd_twice_md5, %d bytes\n", data_len); - } - } - break; - case QQ_CMD_LOGIN: - default: - if (qd->client_version >= 2007) { - data_len = qq_decrypt(data, rcved, rcved_len, qd->ld.pwd_twice_md5); - if (data_len >= 0) { - purple_debug_warning("QQ", "Decrypt login packet by pwd_twice_md5\n"); - } else { - data_len = qq_decrypt(data, rcved, rcved_len, qd->ld.login_key); - if (data_len >= 0) { - purple_debug_warning("QQ", "Decrypt login packet by login_key\n"); - } - } - } else { - /* May use password_twice_md5 in the past version like QQ2005 */ - data_len = qq_decrypt(data, rcved, rcved_len, qd->ld.random_key); - if (data_len >= 0) { - purple_debug_warning("QQ", "Decrypt login packet by random_key\n"); - } else { - data_len = qq_decrypt(data, rcved, rcved_len, qd->ld.pwd_twice_md5); - if (data_len >= 0) { - purple_debug_warning("QQ", "Decrypt login packet by pwd_twice_md5\n"); - } - } - } - break; - } - - if (data_len < 0) { - purple_debug_warning("QQ", - "Can not decrypt login cmd, [%05d], 0x%04X %s, len %d\n", - seq, cmd, qq_get_cmd_desc(cmd), rcved_len); - qq_show_packet("Can not decrypted", rcved, rcved_len); - purple_connection_error_reason(gc, - PURPLE_CONNECTION_ERROR_ENCRYPTION_ERROR, - _("Unable to decrypt login reply")); - return QQ_LOGIN_REPLY_ERR; - } - - switch (cmd) { - case QQ_CMD_GET_SERVER: - ret_8 = qq_process_get_server(gc, data, data_len); - if ( ret_8 == QQ_LOGIN_REPLY_OK) { - qq_request_token(gc); - } else if ( ret_8 == QQ_LOGIN_REPLY_REDIRECT) { - return QQ_LOGIN_REPLY_REDIRECT; - } - break; - case QQ_CMD_TOKEN_EX: - ret_8 = qq_process_token_ex(gc, data, data_len); - if (ret_8 == QQ_LOGIN_REPLY_OK) { - qq_request_check_pwd(gc); - } else if (ret_8 == QQ_LOGIN_REPLY_NEXT_TOKEN_EX) { - qq_request_token_ex_next(gc); - } else if (ret_8 == QQ_LOGIN_REPLY_CAPTCHA_DLG) { - qq_captcha_input_dialog(gc, &(qd->captcha)); - g_free(qd->captcha.token); - g_free(qd->captcha.data); - memset(&qd->captcha, 0, sizeof(qd->captcha)); - } - break; - case QQ_CMD_CHECK_PWD: - ret_8 = qq_process_check_pwd(gc, data, data_len); - if (ret_8 != QQ_LOGIN_REPLY_OK) { - return ret_8; - } - if (qd->client_version >= 2008) { - qq_request_login_2008(gc); - } else { - qq_request_login_2007(gc); - } - break; - case QQ_CMD_LOGIN: - if (qd->client_version >= 2008) { - ret_8 = qq_process_login_2008(gc, data, data_len); - if ( ret_8 == QQ_LOGIN_REPLY_REDIRECT) { - qq_request_get_server(gc); - return QQ_LOGIN_REPLY_OK; - } - } else if (qd->client_version >= 2007) { - ret_8 = qq_process_login_2007(gc, data, data_len); - if ( ret_8 == QQ_LOGIN_REPLY_REDIRECT) { - qq_request_get_server(gc); - return QQ_LOGIN_REPLY_OK; - } - } else { - ret_8 = qq_process_login(gc, data, data_len); - } - if (ret_8 != QQ_LOGIN_REPLY_OK) { - return ret_8; - } - - purple_connection_update_progress(gc, _("Logging in"), QQ_CONNECT_STEPS - 1, QQ_CONNECT_STEPS); - purple_debug_info("QQ", "Login replies OK; everything is fine\n"); - purple_connection_set_state(gc, PURPLE_CONNECTED); - qd->is_login = TRUE; /* must be defined after sev_finish_login */ - - /* now initiate QQ Qun, do it first as it may take longer to finish */ - qq_room_data_initial(gc); - - /* is_login, but we have packets before login */ - qq_trans_process_remained(gc); - - qq_update_all(gc, 0); - break; - default: - process_unknow_cmd(gc, _("Unknown LOGIN CMD"), data, data_len, cmd, seq); - return QQ_LOGIN_REPLY_ERR; - } - return QQ_LOGIN_REPLY_OK; -} - -void qq_proc_client_cmds(PurpleConnection *gc, guint16 cmd, guint16 seq, - guint8 *rcved, gint rcved_len, UPDCLS update_class, guint32 ship32) -{ - qq_data *qd; - - guint8 *data; - gint data_len; - - guint8 ret_8 = 0; - guint16 ret_16 = 0; - guint32 ret_32 = 0; - gboolean is_unknow = FALSE; - - g_return_if_fail(rcved_len > 0); - - g_return_if_fail (gc != NULL && gc->proto_data != NULL); - qd = (qq_data *) gc->proto_data; - - data = g_newa(guint8, rcved_len); - data_len = qq_decrypt(data, rcved, rcved_len, qd->session_key); - if (data_len < 0) { - purple_debug_warning("QQ", - "Reply can not be decrypted by session key, [%05d], 0x%04X %s, len %d\n", - seq, cmd, qq_get_cmd_desc(cmd), rcved_len); - qq_show_packet("Can not decrypted", rcved, rcved_len); - return; - } - - if (data_len <= 0) { - purple_debug_warning("QQ", - "Reply decrypted is empty, [%05d], 0x%04X %s, len %d\n", - seq, cmd, qq_get_cmd_desc(cmd), rcved_len); - return; - } - - switch (cmd) { - case QQ_CMD_UPDATE_INFO: - qq_process_change_info(gc, data, data_len); - break; - case QQ_CMD_ADD_BUDDY_NO_AUTH: - qq_process_add_buddy_no_auth(gc, data, data_len, ship32); - break; - case QQ_CMD_REMOVE_BUDDY: - qq_process_remove_buddy(gc, data, data_len, ship32); - break; - case QQ_CMD_REMOVE_ME: - qq_process_buddy_remove_me(gc, data, data_len, ship32); - break; - case QQ_CMD_ADD_BUDDY_AUTH: - qq_process_add_buddy_auth(data, data_len, gc); - break; - case QQ_CMD_GET_BUDDY_INFO: - qq_process_get_buddy_info(data, data_len, ship32, gc); - break; - case QQ_CMD_CHANGE_STATUS: - qq_process_change_status(data, data_len, gc); - break; - case QQ_CMD_SEND_IM: - do_im_ack(data, data_len, gc); - break; - case QQ_CMD_KEEP_ALIVE: - if (qd->client_version >= 2008) { - qq_process_keep_alive_2008(data, data_len, gc); - } else if (qd->client_version >= 2007) { - qq_process_keep_alive_2007(data, data_len, gc); - } else { - qq_process_keep_alive(data, data_len, gc); - } - break; - case QQ_CMD_GET_BUDDIES_ONLINE: - ret_8 = qq_process_get_buddies_online(data, data_len, gc); - if (ret_8 > 0 && ret_8 < 0xff) { - purple_debug_info("QQ", "Requesting for more online buddies\n"); - qq_request_get_buddies_online(gc, ret_8, update_class); - return; - } - purple_debug_info("QQ", "All online buddies received\n"); - qq_update_buddyies_status(gc); - break; - case QQ_CMD_GET_LEVEL: - qq_process_get_level_reply(data, data_len, gc); - break; - case QQ_CMD_GET_BUDDIES_LIST: - ret_16 = qq_process_get_buddies(data, data_len, gc); - if (ret_16 > 0 && ret_16 < 0xffff) { - purple_debug_info("QQ", "Requesting for more buddies\n"); - qq_request_get_buddies(gc, ret_16, update_class); - return; - } - purple_debug_info("QQ", "All buddies received. Requesting buddies' levels\n"); - break; - case QQ_CMD_GET_BUDDIES_AND_ROOMS: - ret_32 = qq_process_get_buddies_and_rooms(data, data_len, gc); - if (ret_32 > 0 && ret_32 < 0xffffffff) { - purple_debug_info("QQ", "Requesting for more buddies and groups\n"); - qq_request_get_buddies_and_rooms(gc, ret_32, update_class); - return; - } - purple_debug_info("QQ", "All buddies and groups received\n"); - break; - case QQ_CMD_AUTH_CODE: - qq_process_auth_code(gc, data, data_len, ship32); - break; - case QQ_CMD_BUDDY_QUESTION: - qq_process_question(gc, data, data_len, ship32); - break; - case QQ_CMD_ADD_BUDDY_NO_AUTH_EX: - qq_process_add_buddy_no_auth_ex(gc, data, data_len, ship32); - break; - case QQ_CMD_ADD_BUDDY_AUTH_EX: - qq_process_add_buddy_auth_ex(gc, data, data_len, ship32); - break; - case QQ_CMD_BUDDY_CHECK_CODE: - qq_process_buddy_check_code(gc, data, data_len); - break; - case QQ_CMD_BUDDY_MEMO: - purple_debug_info("QQ", "Receive memo from server!\n"); - qq_process_get_buddy_memo(gc, data, data_len, update_class, ship32); - return; - purple_debug_info("QQ", "Should NOT be here...\n"); - break; - default: - process_unknow_cmd(gc, _("Unknown CLIENT CMD"), data, data_len, cmd, seq); - is_unknow = TRUE; - break; - } - if (is_unknow) - return; - - if (update_class == QQ_CMD_CLASS_NONE) - return; - - purple_debug_info("QQ", "Update class %d\n", update_class); - if (update_class == QQ_CMD_CLASS_UPDATE_ALL) { - qq_update_all(gc, cmd); - return; - } - if (update_class == QQ_CMD_CLASS_UPDATE_ONLINE) { - qq_update_online(gc, cmd); - return; - } -} - diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/qq/qq_process.h --- a/libpurple/protocols/qq/qq_process.h Thu May 05 03:40:29 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,56 +0,0 @@ -/** - * @file qq_process.h - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * 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 02111-1301 USA - */ - -#ifndef _QQ_PROCESS_H -#define _QQ_PROCESS_H - -#include -#include "connection.h" - -#include "qq.h" - -enum { - QQ_CMD_CLASS_NONE = 0, - QQ_CMD_CLASS_UPDATE_ALL, - QQ_CMD_CLASS_UPDATE_ONLINE, - QQ_CMD_CLASS_UPDATE_BUDDY, - QQ_CMD_CLASS_UPDATE_ROOM -}; - -guint8 qq_proc_login_cmds(PurpleConnection *gc, guint16 cmd, guint16 seq, - guint8 *rcved, gint rcved_len, UPDCLS update_class, guint32 ship32); -void qq_proc_client_cmds(PurpleConnection *gc, guint16 cmd, guint16 seq, - guint8 *rcved, gint rcved_len, UPDCLS update_class, guint32 ship32); -void qq_proc_room_cmds(PurpleConnection *gc, guint16 seq, - guint8 room_cmd, guint32 room_id, guint8 *rcved, gint rcved_len, - UPDCLS update_class, guint32 ship32); - -void qq_proc_server_cmd(PurpleConnection *gc, guint16 cmd, guint16 seq, guint8 *rcved, gint rcved_len); - -void qq_update_all(PurpleConnection *gc, guint16 cmd); -void qq_update_online(PurpleConnection *gc, guint16 cmd); -void qq_update_room(PurpleConnection *gc, guint8 room_cmd, guint32 room_id); -void qq_update_all_rooms(PurpleConnection *gc, guint8 room_cmd, guint32 room_id); -#endif - diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/qq/qq_trans.c --- a/libpurple/protocols/qq/qq_trans.c Thu May 05 03:40:29 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,395 +0,0 @@ -/** - * @file qq_trans.c - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * 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 02111-1301 USA - */ - -#include "internal.h" - -#include "connection.h" -#include "debug.h" -#include "notify.h" -#include "prefs.h" -#include "request.h" - -#include "qq_define.h" -#include "qq_network.h" -#include "qq_process.h" -#include "qq_trans.h" - -enum { - QQ_TRANS_IS_SERVER = 0x01, /* Is server command or client command */ - QQ_TRANS_IS_IMPORT = 0x02, /* Only notice if not get reply; or resend, disconn if reties get 0*/ - QQ_TRANS_REMAINED = 0x04, /* server command before login*/ - QQ_TRANS_IS_REPLY = 0x08 /* server command before login*/ -}; - - -gboolean qq_trans_is_server(qq_transaction *trans) -{ - g_return_val_if_fail(trans != NULL, FALSE); - - if (trans->flag & QQ_TRANS_IS_SERVER) - return TRUE; - else - return FALSE; -} - -gboolean qq_trans_is_dup(qq_transaction *trans) -{ - g_return_val_if_fail(trans != NULL, TRUE); - - if (trans->rcved_times > 1) - return TRUE; - else - return FALSE; -} - -guint8 qq_trans_get_room_cmd(qq_transaction *trans) -{ - g_return_val_if_fail(trans != NULL, 0); - return trans->room_cmd; -} - -guint32 qq_trans_get_room_id(qq_transaction *trans) -{ - g_return_val_if_fail(trans != NULL, 0); - return trans->room_id; -} - -guint32 qq_trans_get_class(qq_transaction *trans) -{ - g_return_val_if_fail(trans != NULL, QQ_CMD_CLASS_NONE); - return trans->update_class; -} - -guint32 qq_trans_get_ship(qq_transaction *trans) -{ - g_return_val_if_fail(trans != NULL, 0); - return trans->ship32; -} - -static qq_transaction *trans_create(PurpleConnection *gc, gint fd, - guint16 cmd, guint16 seq, guint8 *data, gint data_len, UPDCLS update_class, guint32 ship32) -{ - qq_transaction *trans; - - g_return_val_if_fail(gc != NULL, NULL); - - trans = g_new0(qq_transaction, 1); - - memset(trans, 0, sizeof(qq_transaction)); - trans->fd = fd; - trans->cmd = cmd; - trans->seq = seq; - - trans->data = NULL; - trans->data_len = 0; - if (data != NULL && data_len > 0) { - /* don't use g_strdup, may have 0x00 */ - trans->data = g_memdup(data, data_len); - trans->data_len = data_len; - } - - trans->update_class = update_class; - trans->ship32 = ship32; - return trans; -} - -/* Remove a packet with seq from send trans */ -static void trans_remove(PurpleConnection *gc, qq_transaction *trans) -{ - qq_data *qd; - - g_return_if_fail(gc != NULL); - qd = (qq_data *) gc->proto_data; - g_return_if_fail(qd != NULL); - - g_return_if_fail(trans != NULL); -#if 0 - purple_debug_info("QQ_TRANS", - "Remove [%s%05d] retry %d rcved %d scan %d %s\n", - (trans->flag & QQ_TRANS_IS_SERVER) ? "SRV-" : "", - trans->seq, - trans->send_retries, trans->rcved_times, trans->scan_times, - qq_get_cmd_desc(trans->cmd)); -#endif - if (trans->data) g_free(trans->data); - qd->transactions = g_list_remove(qd->transactions, trans); - g_free(trans); -} - -static qq_transaction *trans_find(PurpleConnection *gc, guint16 cmd, guint16 seq) -{ - qq_data *qd; - GList *list; - qq_transaction *trans; - - g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, NULL); - qd = (qq_data *) gc->proto_data; - - list = qd->transactions; - while (list != NULL) { - trans = (qq_transaction *) list->data; - if(trans->cmd == cmd && trans->seq == seq) { - return trans; - } - list = list->next; - } - - return NULL; -} - -void qq_trans_add_client_cmd(PurpleConnection *gc, - guint16 cmd, guint16 seq, guint8 *data, gint data_len, UPDCLS update_class, guint32 ship32) -{ - qq_data *qd = (qq_data *)gc->proto_data; - qq_transaction *trans = trans_create(gc, qd->fd, cmd, seq, data, data_len, update_class, ship32); - - if (cmd == QQ_CMD_TOKEN || cmd == QQ_CMD_LOGIN || cmd == QQ_CMD_KEEP_ALIVE) { - trans->flag |= QQ_TRANS_IS_IMPORT; - } - trans->send_retries = qd->resend_times; -#if 0 - purple_debug_info("QQ_TRANS", "Add client cmd, seq %d, data %p, len %d\n", - trans->seq, trans->data, trans->data_len); -#endif - qd->transactions = g_list_append(qd->transactions, trans); -} - -qq_transaction *qq_trans_find_rcved(PurpleConnection *gc, guint16 cmd, guint16 seq) -{ - qq_transaction *trans; - - trans = trans_find(gc, cmd, seq); - if (trans == NULL) { - return NULL; - } - - if (trans->rcved_times == 0) { - trans->scan_times = 0; - } - trans->rcved_times++; - /* server may not get our confirm reply before, send reply again*/ - if (qq_trans_is_server(trans) && (trans->flag & QQ_TRANS_IS_REPLY)) { - if (trans->data != NULL && trans->data_len > 0) { - qq_send_cmd_encrypted(gc, trans->cmd, trans->seq, trans->data, trans->data_len, FALSE); - } - } - return trans; -} - -void qq_trans_add_room_cmd(PurpleConnection *gc, - guint16 seq, guint8 room_cmd, guint32 room_id, guint8 *data, gint data_len, - UPDCLS update_class, guint32 ship32) -{ - qq_data *qd = (qq_data *)gc->proto_data; - qq_transaction *trans = trans_create(gc, qd->fd, QQ_CMD_ROOM, seq, data, data_len, - update_class, ship32); - - trans->room_cmd = room_cmd; - trans->room_id = room_id; - trans->send_retries = qd->resend_times; -#if 0 - purple_debug_info("QQ_TRANS", "Add room cmd, seq %d, data %p, len %d\n", - trans->seq, trans->data, trans->data_len); -#endif - qd->transactions = g_list_append(qd->transactions, trans); -} - -void qq_trans_add_server_cmd(PurpleConnection *gc, guint16 cmd, guint16 seq, - guint8 *rcved, gint rcved_len) -{ - qq_data *qd = (qq_data *)gc->proto_data; - qq_transaction *trans = trans_create(gc, qd->fd, cmd, seq, rcved, rcved_len, QQ_CMD_CLASS_NONE, 0); - - trans->flag = QQ_TRANS_IS_SERVER; - trans->send_retries = 0; - trans->rcved_times = 1; -#if 0 - purple_debug_info("QQ_TRANS", "Add server cmd, seq %d, data %p, len %d\n", - trans->seq, trans->data, trans->data_len); -#endif - qd->transactions = g_list_append(qd->transactions, trans); -} - -void qq_trans_add_server_reply(PurpleConnection *gc, guint16 cmd, guint16 seq, - guint8 *reply, gint reply_len) -{ - qq_transaction *trans; - - g_return_if_fail(reply != NULL && reply_len > 0); - - trans = trans_find(gc, cmd, seq); - if (trans == NULL) { - return; - } - - g_return_if_fail(trans->flag & QQ_TRANS_IS_SERVER); - trans->flag |= QQ_TRANS_IS_REPLY; - - if (trans->data) g_free(trans->data); - - trans->data = g_memdup(reply, reply_len); - trans->data_len = reply_len; -} - -void qq_trans_add_remain(PurpleConnection *gc, guint16 cmd, guint16 seq, - guint8 *data, gint data_len) -{ - qq_data *qd = (qq_data *)gc->proto_data; - qq_transaction *trans = trans_create(gc, qd->fd, cmd, seq, data, data_len, QQ_CMD_CLASS_NONE, 0); - - trans->flag = QQ_TRANS_IS_SERVER; - trans->flag |= QQ_TRANS_REMAINED; - trans->send_retries = 0; - trans->rcved_times = 1; -#if 1 - purple_debug_info("QQ_TRANS", "Add server cmd and remained, seq %d, data %p, len %d\n", - trans->seq, trans->data, trans->data_len); -#endif - qd->transactions = g_list_append(qd->transactions, trans); -} - -void qq_trans_process_remained(PurpleConnection *gc) -{ - qq_data *qd = (qq_data *)gc->proto_data; - GList *curr; - GList *next; - qq_transaction *trans; - - g_return_if_fail(qd != NULL); - - next = qd->transactions; - while( (curr = next) ) { - next = curr->next; - trans = (qq_transaction *) (curr->data); -#if 0 - purple_debug_info("QQ_TRANS", "Scan [%d]\n", trans->seq); -#endif - if ( !(trans->flag & QQ_TRANS_IS_SERVER) ) { - continue; - } - if ( !(trans->flag & QQ_TRANS_REMAINED) ) { - continue; - } - /* set QQ_TRANS_REMAINED off */ - trans->flag &= ~QQ_TRANS_REMAINED; - -#if 1 - purple_debug_info("QQ_TRANS", - "Process server cmd remained, seq %d, data %p, len %d, send_retries %d\n", - trans->seq, trans->data, trans->data_len, trans->send_retries); -#endif - qq_proc_server_cmd(gc, trans->cmd, trans->seq, trans->data, trans->data_len); - } - - /* purple_debug_info("QQ_TRANS", "Scan finished\n"); */ - return; -} - -gboolean qq_trans_scan(PurpleConnection *gc) -{ - qq_data *qd = (qq_data *)gc->proto_data; - GList *curr; - GList *next; - qq_transaction *trans; - - g_return_val_if_fail(qd != NULL, FALSE); - - next = qd->transactions; - while( (curr = next) ) { - next = curr->next; - trans = (qq_transaction *) (curr->data); - /* purple_debug_info("QQ_TRANS", "Scan [%d]\n", trans->seq); */ - - if (trans->flag & QQ_TRANS_REMAINED) { - /* keep server cmd before login*/ - continue; - } - - trans->scan_times++; - if (trans->scan_times <= 1) { - /* skip in 10 seconds */ - continue; - } - - if (trans->rcved_times > 0) { - /* Has been received */ - trans_remove(gc, trans); - continue; - } - - if (trans->flag & QQ_TRANS_IS_SERVER) { - continue; - } - - /* Never get reply */ - trans->send_retries--; - if (trans->send_retries <= 0) { - purple_debug_warning("QQ_TRANS", - "[%d] %s is lost.\n", - trans->seq, qq_get_cmd_desc(trans->cmd)); - if (trans->flag & QQ_TRANS_IS_IMPORT) { - return TRUE; - } - - qd->net_stat.lost++; - purple_debug_error("QQ_TRANS", - "Lost [%d] %s, data %p, len %d, retries %d\n", - trans->seq, qq_get_cmd_desc(trans->cmd), - trans->data, trans->data_len, trans->send_retries); - trans_remove(gc, trans); - continue; - } - - qd->net_stat.resend++; - purple_debug_warning("QQ_TRANS", - "Resend [%d] %s data %p, len %d, send_retries %d\n", - trans->seq, qq_get_cmd_desc(trans->cmd), - trans->data, trans->data_len, trans->send_retries); - qq_send_cmd_encrypted(gc, trans->cmd, trans->seq, trans->data, trans->data_len, FALSE); - } - - /* purple_debug_info("QQ_TRANS", "Scan finished\n"); */ - return FALSE; -} - -/* clean up send trans and free all contents */ -void qq_trans_remove_all(PurpleConnection *gc) -{ - qq_data *qd = (qq_data *)gc->proto_data; - qq_transaction *trans; - gint count = 0; - - while(qd->transactions != NULL) { - trans = (qq_transaction *) (qd->transactions->data); - qd->transactions = g_list_remove(qd->transactions, trans); - - if (trans->data) g_free(trans->data); - g_free(trans); - - count++; - } - if (count > 0) { - purple_debug_info("QQ_TRANS", "Free all %d packets\n", count); - } -} diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/qq/qq_trans.h --- a/libpurple/protocols/qq/qq_trans.h Thu May 05 03:40:29 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,75 +0,0 @@ -/** - * @file qq_trans.h - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * 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 02111-1301 USA - */ - -#ifndef _QQ_SEND_QUEUE_H_ -#define _QQ_SEND_QUEUE_H_ - -#include -#include "qq.h" - -typedef struct _qq_transaction { - guint8 flag; - guint16 seq; - guint16 cmd; - - guint8 room_cmd; - guint32 room_id; - - guint8 *data; - gint data_len; - - gint fd; - gint send_retries; - gint rcved_times; - gint scan_times; - - UPDCLS update_class; - guint32 ship32; -} qq_transaction; - -qq_transaction *qq_trans_find_rcved(PurpleConnection *gc, guint16 cmd, guint16 seq); -gboolean qq_trans_is_server(qq_transaction *trans) ; -gboolean qq_trans_is_dup(qq_transaction *trans); -guint8 qq_trans_get_room_cmd(qq_transaction *trans); -guint32 qq_trans_get_room_id(qq_transaction *trans); -guint32 qq_trans_get_class(qq_transaction *trans); -guint32 qq_trans_get_ship(qq_transaction *trans); - -void qq_trans_add_client_cmd(PurpleConnection *gc, guint16 cmd, guint16 seq, - guint8 *data, gint data_len, UPDCLS update_class, guint32 ship32); -void qq_trans_add_room_cmd(PurpleConnection *gc, - guint16 seq, guint8 room_cmd, guint32 room_id, - guint8 *data, gint data_len, UPDCLS update_class, guint32 ship32); -void qq_trans_add_server_cmd(PurpleConnection *gc, guint16 cmd, guint16 seq, - guint8 *rcved, gint rcved_len); -void qq_trans_add_server_reply(PurpleConnection *gc, guint16 cmd, guint16 seq, - guint8 *reply, gint reply_len); -void qq_trans_add_remain(PurpleConnection *gc, guint16 cmd, guint16 seq, - guint8 *data, gint data_len); - -void qq_trans_process_remained(PurpleConnection *gc); -gboolean qq_trans_scan(PurpleConnection *gc); -void qq_trans_remove_all(PurpleConnection *gc); - -#endif diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/qq/send_file.c --- a/libpurple/protocols/qq/send_file.c Thu May 05 03:40:29 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,940 +0,0 @@ -/** - * @file send_file.c - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * 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 02111-1301 USA - */ - -#include "qq.h" - -#include "send_file.h" -#include "debug.h" -#include "network.h" -#include "notify.h" - -#include "buddy_list.h" -#include "file_trans.h" -#include "qq_define.h" -#include "im.h" -#include "qq_base.h" -#include "packet_parse.h" -#include "qq_network.h" -#include "utils.h" - -enum -{ - QQ_FILE_TRANS_REQ = 0x0035, - QQ_FILE_TRANS_ACC_UDP = 0x0037, - QQ_FILE_TRANS_ACC_TCP = 0x0003, - QQ_FILE_TRANS_DENY_UDP = 0x0039, - QQ_FILE_TRANS_DENY_TCP = 0x0005, - QQ_FILE_TRANS_NOTIFY = 0x003b, - QQ_FILE_TRANS_NOTIFY_ACK = 0x003c, - QQ_FILE_TRANS_CANCEL = 0x0049, - QQ_FILE_TRANS_PASV = 0x003f -}; - -static int _qq_in_same_lan(ft_info *info) -{ - if (info->remote_internet_ip == info->local_internet_ip) return 1; - purple_debug_info("QQ", - "Not in the same LAN, remote internet ip[%x], local internet ip[%x]\n", - info->remote_internet_ip - , info->local_internet_ip); - return 0; -} - -static int _qq_xfer_init_udp_channel(ft_info *info) -{ - struct sockaddr_in sin; - memset(&sin, 0, sizeof(sin)); - sin.sin_family = AF_INET; - if (!_qq_in_same_lan(info)) { - sin.sin_port = g_htons(info->remote_major_port); - sin.sin_addr.s_addr = g_htonl(info->remote_internet_ip); - } else { - sin.sin_port = g_htons(info->remote_minor_port); - sin.sin_addr.s_addr = g_htonl(info->remote_real_ip); - } - return 0; -} - -/* these 2 functions send and recv buffer from/to UDP channel */ -static ssize_t _qq_xfer_udp_recv(guint8 *buf, size_t len, PurpleXfer *xfer) -{ - struct sockaddr_in sin; - socklen_t sinlen; - ft_info *info; - gint r; - - info = (ft_info *) xfer->data; - sinlen = sizeof(sin); - r = recvfrom(info->recv_fd, buf, len, 0, (struct sockaddr *) &sin, &sinlen); - purple_debug_info("QQ", - "==> recv %d bytes from File UDP Channel, remote ip[%s], remote port[%d]\n", - r, inet_ntoa(sin.sin_addr), g_ntohs(sin.sin_port)); - return r; -} - -/* -static ssize_t _qq_xfer_udp_send(const char *buf, size_t len, PurpleXfer *xfer) -{ - ft_info *info; - - info = (ft_info *) xfer->data; - return send(info->sender_fd, buf, len, 0); -} -*/ - -static ssize_t _qq_xfer_udp_send(const guint8 *buf, size_t len, PurpleXfer *xfer) -{ - struct sockaddr_in sin; - ft_info *info; - - info = (ft_info *) xfer->data; - memset(&sin, 0, sizeof(sin)); - sin.sin_family = AF_INET; - if (!_qq_in_same_lan(info)) { - sin.sin_port = g_htons(info->remote_major_port); - sin.sin_addr.s_addr = g_htonl(info->remote_internet_ip); - } else if (info->use_major) { - sin.sin_port = g_htons(info->remote_major_port); - sin.sin_addr.s_addr = g_htonl(info->remote_real_ip); - } else { - sin.sin_port = g_htons(info->remote_minor_port); - sin.sin_addr.s_addr = g_htonl(info->remote_real_ip); - } - purple_debug_info("QQ", "sending to channel: %s:%d\n", - inet_ntoa(sin.sin_addr), - (int)g_ntohs(sin.sin_port) - ); - return sendto(info->sender_fd, buf, len, 0, (struct sockaddr *) &sin, sizeof(sin)); -} - -/* user-defined functions for purple_xfer_read and purple_xfer_write */ - -/* -static ssize_t _qq_xfer_read(char **buf, PurpleXfer *xfer) -{ - *buf = g_newa(char, QQ_FILE_FRAGMENT_MAXLEN + 100); - return _qq_xfer_udp_recv(*buf, QQ_FILE_FRAGMENT_MAXLEN + 100, xfer); -} -*/ - -gssize _qq_xfer_write(const guint8 *buf, size_t len, PurpleXfer *xfer) -{ - return _qq_xfer_udp_send(buf, len, xfer); -} - -static void _qq_xfer_recv_packet(gpointer data, gint source, PurpleInputCondition condition) -{ - PurpleXfer *xfer = (PurpleXfer *) data; - PurpleAccount *account = purple_xfer_get_account(xfer); - PurpleConnection *gc = purple_account_get_connection(account); - guint8 *buf; - gint size; - /* FIXME: It seems that the transfer never use a packet - * larger than 1500 bytes, so if it happened to be a - * larger packet, either error occurred or protocol should - * be modified - */ - ft_info *info; - info = xfer->data; - g_return_if_fail (source == info->recv_fd); - buf = g_newa(guint8, 1500); - size = _qq_xfer_udp_recv(buf, 1500, xfer); - qq_process_recv_file(gc, buf, size); -} - -/* start file transfer process */ -/* -static void _qq_xfer_send_start (PurpleXfer *xfer) -{ - PurpleAccount *account; - PurpleConnection *gc; - ft_info *info; - - account = purple_xfer_get_account(xfer); - gc = purple_account_get_connection(account); - info = (ft_info *) xfer->data; -} -*/ - -/* -static void _qq_xfer_send_ack (PurpleXfer *xfer, const char *buffer, size_t len) -{ - PurpleAccount *account; - PurpleConnection *gc; - - account = purple_xfer_get_account(xfer); - gc = purple_account_get_connection(account); - qq_process_recv_file(gc, (guint8 *) buffer, len); -} -*/ - -/* -static void _qq_xfer_recv_start(PurpleXfer *xfer) -{ -} -*/ - -static void _qq_xfer_end(PurpleXfer *xfer) -{ - ft_info *info; - g_return_if_fail(xfer != NULL && xfer->data != NULL); - info = (ft_info *) xfer->data; - - qq_xfer_close_file(xfer); - if (info->dest_fp != NULL) { - fclose(info->dest_fp); - purple_debug_info("QQ", "file closed\n"); - } - if (info->major_fd != 0) { - close(info->major_fd); - purple_debug_info("QQ", "major port closed\n"); - } - if (info->minor_fd != 0) { - close(info->minor_fd); - purple_debug_info("QQ", "minor port closed\n"); - } - /* - if (info->buffer != NULL) { - munmap(info->buffer, purple_xfer_get_size(xfer)); - purple_debug_info("QQ", "file mapping buffer is freed.\n"); - } - */ - g_free(info); -} - -static void qq_show_conn_info(ft_info *info) -{ - gchar *internet_ip_str, *real_ip_str; - guint32 ip; - - ip = g_htonl(info->remote_real_ip); - real_ip_str = gen_ip_str((guint8 *) &ip); - ip = g_htonl(info->remote_internet_ip); - internet_ip_str = gen_ip_str((guint8 *) &ip); - purple_debug_info("QQ", "remote internet ip[%s:%d], major port[%d], real ip[%s], minor port[%d]\n", - internet_ip_str, info->remote_internet_port, - info->remote_major_port, real_ip_str, info->remote_minor_port - ); - g_free(real_ip_str); - g_free(internet_ip_str); -} - -#define QQ_CONN_INFO_LEN 61 -gint qq_get_conn_info(ft_info *info, guint8 *data) -{ - gint bytes = 0; - /* 16 + 30 + 1 + 4 + 2 + 2 + 4 + 2 = 61 */ - bytes += qq_getdata(info->file_session_key, 16, data + bytes); - bytes += 30; /* skip 30 bytes */ - bytes += qq_get8(&info->conn_method, data + bytes); - bytes += qq_get32(&info->remote_internet_ip, data + bytes); - bytes += qq_get16(&info->remote_internet_port, data + bytes); - bytes += qq_get16(&info->remote_major_port, data + bytes); - bytes += qq_get32(&info->remote_real_ip, data + bytes); - bytes += qq_get16(&info->remote_minor_port, data + bytes); - qq_show_conn_info(info); - return bytes; -} - -gint qq_fill_conn_info(guint8 *raw_data, ft_info *info) -{ - gint bytes = 0; - /* 064: connection method, UDP 0x00, TCP 0x03 */ - bytes += qq_put8 (raw_data + bytes, info->conn_method); - /* 065-068: outer ip address of sender (proxy address) */ - bytes += qq_put32 (raw_data + bytes, info->local_internet_ip); - /* 069-070: sender port */ - bytes += qq_put16 (raw_data + bytes, info->local_internet_port); - /* 071-072: the first listening port(TCP doesn't have this part) */ - bytes += qq_put16 (raw_data + bytes, info->local_major_port); - /* 073-076: real ip */ - bytes += qq_put32 (raw_data + bytes, info->local_real_ip); - /* 077-078: the second listening port */ - bytes += qq_put16 (raw_data + bytes, info->local_minor_port); - return bytes; -} - - -/* fill in the common information of file transfer */ -static gint _qq_create_packet_file_header -(guint8 *raw_data, UID to_uid, guint16 message_type, qq_data *qd, gboolean seq_ack) -{ - gint bytes; - time_t now; - guint16 seq; - ft_info *info; - - bytes = 0; - now = time(NULL); - if (!seq_ack) seq = qd->send_seq; - else { - info = (ft_info *) qd->xfer->data; - seq = info->send_seq; - } - - /* 000-003: receiver uid */ - bytes += qq_put32 (raw_data + bytes, qd->uid); - /* 004-007: sender uid */ - bytes += qq_put32 (raw_data + bytes, to_uid); - /* 008-009: sender client version */ - bytes += qq_put16 (raw_data + bytes, qd->client_tag); - /* 010-013: receiver uid */ - bytes += qq_put32 (raw_data + bytes, qd->uid); - /* 014-017: sender uid */ - bytes += qq_put32 (raw_data + bytes, to_uid); - /* 018-033: md5 of (uid+session_key) */ - bytes += qq_putdata (raw_data + bytes, qd->session_md5, 16); - /* 034-035: message type */ - bytes += qq_put16 (raw_data + bytes, message_type); - /* 036-037: sequence number */ - bytes += qq_put16 (raw_data + bytes, seq); - /* 038-041: send time */ - bytes += qq_put32 (raw_data + bytes, (guint32) now); - /* 042-042: always 0x00 */ - bytes += qq_put8 (raw_data + bytes, 0x00); - /* 043-043: sender icon */ - bytes += qq_put8 (raw_data + bytes, qd->my_icon); - /* 044-046: always 0x00 */ - bytes += qq_put16 (raw_data + bytes, 0x0000); - bytes += qq_put8 (raw_data + bytes, 0x00); - /* 047-047: we use font attr */ - bytes += qq_put8 (raw_data + bytes, 0x01); - /* 048-051: always 0x00 */ - bytes += qq_put32 (raw_data + bytes, 0x00000000); - - /* 052-062: always 0x00 */ - bytes += qq_put32 (raw_data + bytes, 0x00000000); - bytes += qq_put32 (raw_data + bytes, 0x00000000); - bytes += qq_put16 (raw_data + bytes, 0x0000); - bytes += qq_put8 (raw_data + bytes, 0x00); - /* 063: transfer_type, 0x65: FILE 0x6b: FACE */ - bytes += qq_put8 (raw_data + bytes, QQ_FILE_TRANSFER_FILE); /* FIXME */ - - return bytes; -} - -#if 0 -in_addr_t get_real_ip() -{ - char hostname[40]; - struct hostent *host; - - gethostname(hostname, sizeof(hostname)); - host = gethostbyname(hostname); - return *(host->h_addr); -} - - -#include -#include - -#define MAXINTERFACES 16 -in_addr_t get_real_ip() -{ - int fd, intrface, i; - struct ifconf ifc; - struct ifreq buf[MAXINTERFACES]; - in_addr_t ret; - - if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) return 0; - ifc.ifc_len = sizeof(buf); - ifc.ifc_buf = (caddr_t) buf; - if (ioctl(fd, SIOCGIFCONF, (char *) &ifc) < 0) return 0; - intrface = ifc.ifc_len / sizeof(struct ifreq); - for (i = 0; i < intrface; i++) { - /* buf[intrface].ifr_name */ - if (ioctl(fd, SIOCGIFADDR, (char *) &buf[i]) >= 0) - { - ret = (((struct sockaddr_in *)(&buf[i].ifr_addr))->sin_addr).s_addr; - if (ret == g_ntohl(0x7f000001)) continue; - return ret; - } - } - return 0; -} -#endif - -static void _qq_xfer_init_socket(PurpleXfer *xfer) -{ - gint sockfd, listen_port = 0, i; - socklen_t sin_len; - struct sockaddr_in sin; - ft_info *info; - - g_return_if_fail(xfer != NULL); - g_return_if_fail(xfer->data != NULL); - info = (ft_info *) xfer->data; - - /* debug - info->local_real_ip = 0x7f000001; - */ - info->local_real_ip = g_ntohl(inet_addr(purple_network_get_my_ip(-1))); - purple_debug_info("QQ", "local real ip is %x\n", info->local_real_ip); - - for (i = 0; i < 2; i++) { - sockfd = socket(PF_INET, SOCK_DGRAM, 0); - g_return_if_fail(sockfd >= 0); - - memset(&sin, 0, sizeof(sin)); - sin.sin_family = AF_INET; - sin.sin_port = 0; - sin.sin_addr.s_addr = INADDR_ANY; - sin_len = sizeof(sin); - bind(sockfd, (struct sockaddr *) &sin, sin_len); - getsockname(sockfd, (struct sockaddr *) &sin, &sin_len); - listen_port = g_ntohs(sin.sin_port); - - switch (i) { - case 0: - info->local_major_port = listen_port; - info->major_fd = sockfd; - purple_debug_info("QQ", "UDP Major Channel created on port[%d]\n", - info->local_major_port); - break; - case 1: - info->local_minor_port = listen_port; - info->minor_fd = sockfd; - purple_debug_info("QQ", "UDP Minor Channel created on port[%d]\n", - info->local_minor_port); - break; - } - } - - if (_qq_in_same_lan(info)) { - info->sender_fd = info->recv_fd = info->minor_fd; - } else { - info->sender_fd = info->recv_fd = info->major_fd; - } -/* xfer->watcher = purple_input_add(info->recv_fd, PURPLE_INPUT_READ, _qq_xfer_recv_packet, xfer); */ -} - -/* create the QQ_FILE_TRANS_REQ packet with file infomations */ -static void _qq_send_packet_file_request (PurpleConnection *gc, UID to_uid, gchar *filename, gint filesize) -{ - qq_data *qd; - guint8 *raw_data; - gchar *filelen_str; - gint filename_len, filelen_strlen, packet_len, bytes; - ft_info *info; - - qd = (qq_data *) gc->proto_data; - - info = g_new0(ft_info, 1); - info->to_uid = to_uid; - info->send_seq = qd->send_seq; - info->local_internet_ip = qd->my_ip.s_addr; - info->local_internet_port = qd->my_port; - info->local_real_ip = 0x00000000; - info->conn_method = 0x00; - qd->xfer->data = info; - - filename_len = strlen(filename); - filelen_str = g_strdup_printf("%d ?ֽ?", filesize); - filelen_strlen = strlen(filelen_str); - - packet_len = 82 + filename_len + filelen_strlen; - raw_data = g_newa(guint8, packet_len); - bytes = 0; - - bytes += _qq_create_packet_file_header(raw_data + bytes, to_uid, - QQ_FILE_TRANS_REQ, qd, FALSE); - bytes += qq_fill_conn_info(raw_data + bytes, info); - /* 079: 0x20 */ - bytes += qq_put8 (raw_data + bytes, 0x20); - /* 080: 0x1f */ - bytes += qq_put8 (raw_data + bytes, 0x1f); - /* undetermined len: filename */ - bytes += qq_putdata (raw_data + bytes, (guint8 *) filename, filename_len); - /* 0x1f */ - bytes += qq_put8 (raw_data + bytes, 0x1f); - /* file length */ - bytes += qq_putdata (raw_data + bytes, (guint8 *) filelen_str, filelen_strlen); - - if (packet_len == bytes) - qq_send_cmd(gc, QQ_CMD_SEND_IM, raw_data, bytes); - else - purple_debug_info("qq_send_packet_file_request", - "%d bytes expected but got %d bytes\n", - packet_len, bytes); - - g_free (filelen_str); -} - -/* tell the buddy we want to accept the file */ -static void _qq_send_packet_file_accept(PurpleConnection *gc, UID to_uid) -{ - qq_data *qd; - guint8 *raw_data; - guint16 minor_port; - guint32 real_ip; - gint packet_len, bytes; - ft_info *info; - - qd = (qq_data *) gc->proto_data; - info = (ft_info *) qd->xfer->data; - - purple_debug_info("QQ", "I've accepted the file transfer request from %d\n", to_uid); - _qq_xfer_init_socket(qd->xfer); - - packet_len = 79; - raw_data = g_newa (guint8, packet_len); - bytes = 0; - - minor_port = info->local_minor_port; - real_ip = info->local_real_ip; - info->local_minor_port = 0; - info->local_real_ip = 0; - - bytes += _qq_create_packet_file_header(raw_data + bytes, to_uid, QQ_FILE_TRANS_ACC_UDP, qd, TRUE); - bytes += qq_fill_conn_info(raw_data + bytes, info); - - info->local_minor_port = minor_port; - info->local_real_ip = real_ip; - - if (packet_len == bytes) - qq_send_cmd(gc, QQ_CMD_SEND_IM, raw_data, bytes); - else - purple_debug_info("qq_send_packet_file_accept", - "%d bytes expected but got %d bytes\n", - packet_len, bytes); -} - -static void _qq_send_packet_file_notifyip(PurpleConnection *gc, UID to_uid) -{ - PurpleXfer *xfer; - ft_info *info; - qq_data *qd; - guint8 *raw_data; - gint packet_len, bytes; - - qd = (qq_data *) gc->proto_data; - xfer = qd->xfer; - info = xfer->data; - - packet_len = 79; - raw_data = g_newa (guint8, packet_len); - bytes = 0; - - purple_debug_info("QQ", "<== sending qq file notify ip packet\n"); - bytes += _qq_create_packet_file_header(raw_data + bytes, to_uid, QQ_FILE_TRANS_NOTIFY, qd, TRUE); - bytes += qq_fill_conn_info(raw_data + bytes, info); - if (packet_len == bytes) - qq_send_cmd(gc, QQ_CMD_SEND_IM, raw_data, bytes); - else - purple_debug_info("qq_send_packet_file_notify", - "%d bytes expected but got %d bytes\n", - packet_len, bytes); - - if (xfer->watcher) purple_input_remove(xfer->watcher); - xfer->watcher = purple_input_add(info->recv_fd, PURPLE_INPUT_READ, _qq_xfer_recv_packet, xfer); - purple_input_add(info->major_fd, PURPLE_INPUT_READ, _qq_xfer_recv_packet, xfer); -} - -/* tell the buddy we don't want the file */ -static void _qq_send_packet_file_reject (PurpleConnection *gc, UID to_uid) -{ - qq_data *qd; - guint8 *raw_data; - gint packet_len, bytes; - - purple_debug_info("_qq_send_packet_file_reject", "start\n"); - qd = (qq_data *) gc->proto_data; - - packet_len = 64; - raw_data = g_newa (guint8, packet_len); - bytes = 0; - - bytes += _qq_create_packet_file_header(raw_data + bytes, to_uid, QQ_FILE_TRANS_DENY_UDP, qd, TRUE); - - if (packet_len == bytes) - qq_send_cmd(gc, QQ_CMD_SEND_IM, raw_data, bytes); - else - purple_debug_info("qq_send_packet_file", - "%d bytes expected but got %d bytes\n", - packet_len, bytes); -} - -/* tell the buddy to cancel transfer */ -static void _qq_send_packet_file_cancel (PurpleConnection *gc, UID to_uid) -{ - qq_data *qd; - guint8 *raw_data; - gint packet_len, bytes; - - purple_debug_info("_qq_send_packet_file_cancel", "start\n"); - qd = (qq_data *) gc->proto_data; - - packet_len = 64; - raw_data = g_newa (guint8, packet_len); - bytes = 0; - - purple_debug_info("_qq_send_packet_file_cancel", "before create header\n"); - bytes += _qq_create_packet_file_header(raw_data + bytes, to_uid, QQ_FILE_TRANS_CANCEL, qd, TRUE); - purple_debug_info("_qq_send_packet_file_cancel", "end create header\n"); - - if (packet_len == bytes) { - purple_debug_info("_qq_send_packet_file_cancel", "before send cmd\n"); - qq_send_cmd(gc, QQ_CMD_SEND_IM, raw_data, bytes); - } - else - purple_debug_info("qq_send_packet_file", - "%d bytes expected but got %d bytes\n", - packet_len, bytes); - - purple_debug_info("qq_send_packet_file_cancel", "end\n"); -} - -/* request to send a file */ -static void -_qq_xfer_init (PurpleXfer * xfer) -{ - PurpleConnection *gc; - PurpleAccount *account; - UID to_uid; - const gchar *filename; - gchar *base_filename; - - g_return_if_fail (xfer != NULL); - account = purple_xfer_get_account(xfer); - gc = purple_account_get_connection(account); - - to_uid = purple_name_to_uid (xfer->who); - g_return_if_fail (to_uid != 0); - - filename = purple_xfer_get_local_filename (xfer); - g_return_if_fail (filename != NULL); - - base_filename = g_path_get_basename(filename); - - _qq_send_packet_file_request (gc, to_uid, base_filename, - purple_xfer_get_size(xfer)); - g_free(base_filename); -} - -/* cancel the transfer of receiving files */ -static void _qq_xfer_cancel(PurpleXfer *xfer) -{ - PurpleConnection *gc; - PurpleAccount *account; - - g_return_if_fail (xfer != NULL); - account = purple_xfer_get_account(xfer); - gc = purple_account_get_connection(account); - - switch (purple_xfer_get_status(xfer)) { - case PURPLE_XFER_STATUS_CANCEL_LOCAL: - _qq_send_packet_file_cancel(gc, purple_name_to_uid(xfer->who)); - break; - case PURPLE_XFER_STATUS_CANCEL_REMOTE: - _qq_send_packet_file_cancel(gc, purple_name_to_uid(xfer->who)); - break; - case PURPLE_XFER_STATUS_NOT_STARTED: - break; - case PURPLE_XFER_STATUS_UNKNOWN: - _qq_send_packet_file_reject(gc, purple_name_to_uid(xfer->who)); - break; - case PURPLE_XFER_STATUS_DONE: - break; - case PURPLE_XFER_STATUS_ACCEPTED: - break; - case PURPLE_XFER_STATUS_STARTED: - break; - } -} - -/* init the transfer of receiving files */ -static void _qq_xfer_recv_init(PurpleXfer *xfer) -{ - PurpleConnection *gc; - PurpleAccount *account; - - g_return_if_fail(xfer != NULL); - account = purple_xfer_get_account(xfer); - gc = purple_account_get_connection(account); - - _qq_send_packet_file_accept(gc, purple_name_to_uid(xfer->who)); -} - -/* process reject im for file transfer request */ -void qq_process_recv_file_reject (guint8 *data, gint data_len, - UID sender_uid, PurpleConnection *gc) -{ - gchar *msg, *filename; - qq_data *qd; - - g_return_if_fail (data != NULL && data_len != 0); - qd = (qq_data *) gc->proto_data; - g_return_if_fail (qd->xfer != NULL); - - /* border has been checked before - if (*cursor >= (data + data_len - 1)) { - purple_debug_warning("QQ", - "Received file reject message is empty\n"); - return; - } - */ - filename = g_path_get_basename(purple_xfer_get_local_filename(qd->xfer)); - msg = g_strdup_printf(_("%d has declined the file %s"), - sender_uid, filename); - - purple_notify_warning (gc, _("File Send"), msg, NULL); - purple_xfer_request_denied(qd->xfer); - qd->xfer = NULL; - - g_free(filename); - g_free(msg); -} - -/* process cancel im for file transfer request */ -void qq_process_recv_file_cancel (guint8 *data, gint data_len, - UID sender_uid, PurpleConnection *gc) -{ - gchar *msg, *filename; - qq_data *qd; - - g_return_if_fail (data != NULL && data_len != 0); - qd = (qq_data *) gc->proto_data; - g_return_if_fail (qd->xfer != NULL - && purple_xfer_get_filename(qd->xfer) != NULL); - - /* border has been checked before - if (*cursor >= (data + data_len - 1)) { - purple_debug_warning("QQ", "Received file reject message is empty\n"); - return; - } - */ - filename = g_path_get_basename(purple_xfer_get_local_filename(qd->xfer)); - msg = g_strdup_printf - (_("%d cancelled the transfer of %s"), - sender_uid, filename); - - purple_notify_warning (gc, _("File Send"), msg, NULL); - purple_xfer_cancel_remote(qd->xfer); - qd->xfer = NULL; - - g_free(filename); - g_free(msg); -} - -/* process accept im for file transfer request */ -void qq_process_recv_file_accept(guint8 *data, gint data_len, UID sender_uid, PurpleConnection *gc) -{ - qq_data *qd; - gint bytes; - ft_info *info; - PurpleXfer *xfer; - - g_return_if_fail (data != NULL && data_len != 0); - qd = (qq_data *) gc->proto_data; - xfer = qd->xfer; - info = (ft_info *) xfer->data; - - if (data_len <= 30 + QQ_CONN_INFO_LEN) { - purple_debug_warning("QQ", "Received file reject message is empty\n"); - return; - } - - bytes = 18 + 12; /* skip 30 bytes */ - qq_get_conn_info(info, data + bytes); - _qq_xfer_init_socket(xfer); - - _qq_xfer_init_udp_channel(info); - _qq_send_packet_file_notifyip(gc, sender_uid); -} - -/* process request from buddy's im for file transfer request */ -void qq_process_recv_file_request(guint8 *data, gint data_len, UID sender_uid, PurpleConnection * gc) -{ - qq_data *qd; - PurpleXfer *xfer; - gchar *sender_name, **fileinfo; - ft_info *info; - PurpleBuddy *b; - qq_buddy_data *bd; - gint bytes; - - g_return_if_fail (data != NULL && data_len != 0); - qd = (qq_data *) gc->proto_data; - - info = g_newa(ft_info, 1); - info->local_internet_ip = qd->my_ip.s_addr; - info->local_internet_port = qd->my_port; - info->local_real_ip = 0x00000000; - info->to_uid = sender_uid; - - if (data_len <= 2 + 30 + QQ_CONN_INFO_LEN) { - purple_debug_warning("QQ", "Received file request message is empty\n"); - return; - } - bytes = 0; - bytes += qq_get16(&(info->send_seq), data + bytes); - - bytes += 18 + 12; /* skip 30 bytes */ - bytes += qq_get_conn_info(info, data + bytes); - - fileinfo = g_strsplit((gchar *) (data + 81 + 12), "\x1f", 2); - g_return_if_fail (fileinfo != NULL && fileinfo[0] != NULL && fileinfo[1] != NULL); - - sender_name = uid_to_purple_name(sender_uid); - - /* FACE from IP detector, ignored by gfhuang */ - if(g_ascii_strcasecmp(fileinfo[0], "FACE") == 0) { - purple_debug_warning("QQ", - "Received a FACE ip detect from %d, so he/she must be online :)\n", sender_uid); - - b = purple_find_buddy(gc->account, sender_name); - bd = (b == NULL) ? NULL : purple_buddy_get_protocol_data(b); - if (bd) { - if(0 != info->remote_real_ip) { - g_memmove(&(bd->ip), &info->remote_real_ip, sizeof(bd->ip)); - bd->port = info->remote_minor_port; - } - else if (0 != info->remote_internet_ip) { - g_memmove(&(bd->ip), &info->remote_internet_ip, sizeof(bd->ip)); - bd->port = info->remote_major_port; - } - - if(!is_online(bd->status)) { - bd->status = QQ_BUDDY_ONLINE_INVISIBLE; - bd->last_update = time(NULL); - qq_update_buddy_status(gc, bd->uid, bd->status, bd->comm_flag); - } - else - purple_debug_info("QQ", "buddy %d is already online\n", sender_uid); - - } - else - purple_debug_warning("QQ", "buddy %d is not in list\n", sender_uid); - - g_free(sender_name); - g_strfreev(fileinfo); - return; - } - - xfer = purple_xfer_new(purple_connection_get_account(gc), - PURPLE_XFER_RECEIVE, - sender_name); - if (xfer) - { - purple_xfer_set_filename(xfer, fileinfo[0]); - purple_xfer_set_size(xfer, atoi(fileinfo[1])); - - purple_xfer_set_init_fnc(xfer, _qq_xfer_recv_init); - purple_xfer_set_request_denied_fnc(xfer, _qq_xfer_cancel); - purple_xfer_set_cancel_recv_fnc(xfer, _qq_xfer_cancel); - purple_xfer_set_end_fnc(xfer, _qq_xfer_end); - purple_xfer_set_write_fnc(xfer, _qq_xfer_write); - - xfer->data = info; - qd->xfer = xfer; - - purple_xfer_request(xfer); - } - - g_free(sender_name); - g_strfreev(fileinfo); -} - -static void _qq_xfer_send_notify_ip_ack(gpointer data, gint source, PurpleInputCondition cond) -{ - PurpleXfer *xfer = (PurpleXfer *) data; - PurpleAccount *account = purple_xfer_get_account(xfer); - PurpleConnection *gc = purple_account_get_connection(account); - ft_info *info = (ft_info *) xfer->data; - - purple_input_remove(xfer->watcher); - xfer->watcher = purple_input_add(info->recv_fd, PURPLE_INPUT_READ, _qq_xfer_recv_packet, xfer); - qq_send_file_ctl_packet(gc, QQ_FILE_CMD_NOTIFY_IP_ACK, info->to_uid, 0); - /* - info->use_major = TRUE; - qq_send_file_ctl_packet(gc, QQ_FILE_CMD_NOTIFY_IP_ACK, info->to_uid, 0); - info->use_major = FALSE; - */ -} - -void qq_process_recv_file_notify(guint8 *data, gint data_len, - UID sender_uid, PurpleConnection *gc) -{ - gint bytes; - qq_data *qd; - ft_info *info; - PurpleXfer *xfer; - - g_return_if_fail (data != NULL && data_len != 0); - qd = (qq_data *) gc->proto_data; - - xfer = qd->xfer; - info = (ft_info *) qd->xfer->data; - if (data_len <= 2 + 30 + QQ_CONN_INFO_LEN) { - purple_debug_warning("QQ", "Received file notify message is empty\n"); - return; - } - - bytes = 0; - bytes += qq_get16(&(info->send_seq), data + bytes); - - bytes += 18 + 12; - bytes += qq_get_conn_info(info, data + bytes); - - _qq_xfer_init_udp_channel(info); - - xfer->watcher = purple_input_add(info->sender_fd, PURPLE_INPUT_WRITE, _qq_xfer_send_notify_ip_ack, xfer); -} - -/* temp placeholder until a working function can be implemented */ -gboolean qq_can_receive_file(PurpleConnection *gc, const char *who) -{ - return TRUE; -} - -void qq_send_file(PurpleConnection *gc, const char *who, const char *file) -{ - qq_data *qd; - PurpleXfer *xfer; - - qd = (qq_data *) gc->proto_data; - - xfer = purple_xfer_new (gc->account, PURPLE_XFER_SEND, - who); - if (xfer) - { - purple_xfer_set_init_fnc (xfer, _qq_xfer_init); - purple_xfer_set_cancel_send_fnc (xfer, _qq_xfer_cancel); - purple_xfer_set_write_fnc(xfer, _qq_xfer_write); - - qd->xfer = xfer; - purple_xfer_request(xfer); - } -} - -/* -static void qq_send_packet_request_key(PurpleConnection *gc, guint8 key) -{ - qq_send_cmd(gc, QQ_CMD_REQUEST_KEY, &key, 1); -} - -static void qq_process_recv_request_key(PurpleConnection *gc) -{ -} -*/ diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/qq/send_file.h --- a/libpurple/protocols/qq/send_file.h Thu May 05 03:40:29 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,81 +0,0 @@ -/** - * @file send_file.h - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * 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 02111-1301 USA - */ - -#ifndef _QQ_QQ_SEND_FILE_H_ -#define _QQ_QQ_SEND_FILE_H_ - -#include "ft.h" -#include "qq.h" - -typedef struct _ft_info { - UID to_uid; - guint16 send_seq; - guint8 file_session_key[QQ_KEY_LENGTH]; - guint8 conn_method; - guint32 remote_internet_ip; - guint16 remote_internet_port; - guint16 remote_major_port; - guint32 remote_real_ip; - guint16 remote_minor_port; - guint32 local_internet_ip; - guint16 local_internet_port; - guint16 local_major_port; - guint32 local_real_ip; - guint16 local_minor_port; - /* we use these to control the packets sent or received */ - guint32 fragment_num; - guint32 fragment_len; - /* The max index of sending/receiving fragment - * for sender, it is the lower bolder of a slide window for sending - * for receiver, it seems that packets having a fragment index lower - * than max_fragment_index have been received already - */ - guint32 max_fragment_index; - guint32 window; - - /* It seems that using xfer's function is not enough for our - * transfer module. So I will use our own structure instead - * of xfer provided - */ - int major_fd; - int minor_fd; - int sender_fd; - int recv_fd; - FILE *dest_fp; - /* guint8 *buffer; */ - gboolean use_major; -} ft_info; - -void qq_process_recv_file_accept(guint8 *data, gint data_len, UID sender_uid, PurpleConnection *gc); -void qq_process_recv_file_reject(guint8 *data, gint data_len, UID sender_uid, PurpleConnection *gc); -void qq_process_recv_file_cancel(guint8 *data, gint data_len, UID sender_uid, PurpleConnection *gc); -void qq_process_recv_file_request(guint8 *data, gint data_len, UID sender_uid, PurpleConnection *gc); -void qq_process_recv_file_notify(guint8 *data, gint data_len, UID sender_uid, PurpleConnection *gc); -gboolean qq_can_receive_file(PurpleConnection *gc, const char *who); -void qq_send_file(PurpleConnection *gc, const char *who, const char *file); -gint qq_get_conn_info(ft_info *info, guint8 *data); -gint qq_fill_conn_info(guint8 *data, ft_info *info); -gssize _qq_xfer_write(const guint8 *buf, size_t len, PurpleXfer *xfer); - -#endif diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/qq/utils.c --- a/libpurple/protocols/qq/utils.c Thu May 05 03:40:29 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,359 +0,0 @@ -/** - * @file utils.c - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * 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 02111-1301 USA - */ - -#include "internal.h" - -#include "limits.h" -#include "stdlib.h" -#include "string.h" - -#ifdef _WIN32 -#include "win32dep.h" -#endif - -#include "cipher.h" - -#include "char_conv.h" -#include "debug.h" -#include "prefs.h" -#include "qq.h" -#include "util.h" -#include "utils.h" - -/* These functions are used only in development phase */ -/* - static void _qq_show_socket(gchar *desc, gint fd) { - struct sockaddr_in sin; - socklen_t len = sizeof(sin); - getsockname(fd, (struct sockaddr *)&sin, &len); - purple_debug_info(desc, "%s:%d\n", - inet_ntoa(sin.sin_addr), g_ntohs(sin.sin_port)); - } - */ - -void qq_get_md5(guint8 *md5, gint md5_len, const guint8* const src, gint src_len) -{ - PurpleCipher *cipher; - PurpleCipherContext *context; - - g_return_if_fail(md5 != NULL && md5_len > 0); - g_return_if_fail(src != NULL && src_len > 0); - - cipher = purple_ciphers_find_cipher("md5"); - context = purple_cipher_context_new(cipher, NULL); - purple_cipher_context_append(context, src, src_len); - purple_cipher_context_digest(context, md5_len, md5, NULL); - purple_cipher_context_destroy(context); -} - -gchar *get_name_by_index_str(gchar **array, const gchar *index_str, gint amount) -{ - gint index; - - index = atoi(index_str); - if (index < 0 || index >= amount) - index = 0; - - return array[index]; -} - -gchar *get_index_str_by_name(gchar **array, const gchar *name, gint amount) -{ - gint index; - - for (index = 0; index <= amount; index++) - if (g_ascii_strcasecmp(array[index], name) == 0) - break; - - if (index >= amount) - index = 0; /* meaning no match */ - return g_strdup_printf("%d", index); -} - -/* split the given data(len) with delimit, - * check the number of field matches the expected_fields (<=0 means all) - * return gchar* array (needs to be freed by g_strfreev later), or NULL */ -gchar **split_data(guint8 *data, gint len, const gchar *delimit, gint expected_fields) -{ - guint8 *input; - gchar **segments, **seg; - gint count = 0, j; - - g_return_val_if_fail(data != NULL && len != 0 && delimit != 0, NULL); - - /* as the last field would be string, but data is not ended with 0x00 - * we have to duplicate the data and append a 0x00 at the end */ - input = g_newa(guint8, len + 1); - g_memmove(input, data, len); - input[len] = 0x00; - - segments = g_strsplit((gchar *) input, delimit, 0); - if (expected_fields <= 0) - return segments; - - for (seg = segments; *seg != NULL; seg++) - count++; - if (count < expected_fields) { /* not enough fields */ - purple_debug_error("QQ", "Less fields %d then %d\n", count, expected_fields); - return NULL; - } else if (count > expected_fields) { /* more fields, OK */ - purple_debug_warning("QQ", "More fields %d than %d\n", count, expected_fields); - /* free up those not used */ - for (j = expected_fields; j < count; j++) { - purple_debug_warning("QQ", "field[%d] is %s\n", j, segments[j]); - g_free(segments[j]); - } - segments[expected_fields] = NULL; - } - - return segments; -} - -/* convert Purple name to original QQ UID */ -UID purple_name_to_uid(const gchar *const name) -{ - UID ret; - g_return_val_if_fail(name != NULL, 0); - - ret = strtoul(name, NULL, 10); - if (errno == ERANGE) - return 0; - else - return ret; -} - -gchar *gen_ip_str(guint8 *ip) { - gchar *ret; - if (ip == NULL || ip[0] == 0) { - ret = g_new(gchar, 1); - *ret = '\0'; - return ret; - } else { - return g_strdup_printf("%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); - } -} - -guint8 *str_ip_gen(gchar *str) { - guint8 *ip = g_new(guint8, 4); - gint a, b, c, d; - - sscanf(str, "%d.%d.%d.%d", &a, &b, &c, &d); - ip[0] = a; - ip[1] = b; - ip[2] = c; - ip[3] = d; - return ip; -} - -/* convert a QQ UID to a unique name of Purple - * the return needs to be freed */ -gchar *uid_to_purple_name(UID uid) -{ - return g_strdup_printf("%u", uid); -} - -/* try to dump the data as GBK */ -gchar* try_dump_as_gbk(const guint8 *const data, gint len) -{ - gint i; - guint8 *incoming; - gchar *msg_utf8; - - incoming = g_newa(guint8, len + 1); - g_memmove(incoming, data, len); - incoming[len] = 0x00; - /* GBK code: - * Single-byte ASCII: 0x21-0x7E - * GBK first byte range: 0x81-0xFE - * GBK second byte range: 0x40-0x7E and 0x80-0xFE */ - for (i = 0; i < len; i++) - if (incoming[i] >= 0x81) - break; - - msg_utf8 = i < len ? qq_to_utf8((gchar *) &incoming[i], QQ_CHARSET_DEFAULT) : NULL; - - if (msg_utf8 != NULL) { - purple_debug_warning("QQ", "Try extract GB msg: %s\n", msg_utf8); - } - return msg_utf8; -} - -/* strips whitespace */ -static gchar *strstrip(const gchar *const buffer) -{ - GString *stripped; - gchar *ret, cur; - gint i; - - g_return_val_if_fail(buffer != NULL, NULL); - - stripped = g_string_new(""); - for (i=0; istr; - g_string_free(stripped, FALSE); - - return ret; -} - -/* Attempts to dump an ASCII hex string to a string of bytes. - * The return should be freed later. */ -guint8 *hex_str_to_bytes(const gchar *const buffer, gint *out_len) -{ - gchar *hex_str, *hex_buffer, *cursor; - gchar tmp[2]; - guint8 *bytes, nibble1, nibble2; - gint index; - - g_return_val_if_fail(buffer != NULL, NULL); - - hex_buffer = strstrip(buffer); - - if (strlen(hex_buffer) % 2 != 0) { - purple_debug_warning("QQ", - "Unable to convert an odd number of nibbles to a string of bytes!\n"); - g_free(hex_buffer); - return NULL; - } - bytes = g_newa(guint8, strlen(hex_buffer) / 2); - hex_str = g_ascii_strdown(hex_buffer, -1); - g_free(hex_buffer); - index = 0; - for (cursor = hex_str; cursor < hex_str + sizeof(gchar) * (strlen(hex_str)) - 1; cursor++) { - if (g_ascii_isdigit(*cursor)) { - tmp[0] = *cursor; - tmp[1] = '\0'; - nibble1 = atoi(tmp); - } else if (g_ascii_isalpha(*cursor) && (gint) *cursor - 87 < 16) { - nibble1 = (gint) *cursor - 87; - } else { - purple_debug_warning("QQ", "Invalid char \'%c\' found in hex string!\n", - *cursor); - g_free(hex_str); - return NULL; - } - nibble1 = nibble1 << 4; - cursor++; - if (g_ascii_isdigit(*cursor)) { - tmp[0] = *cursor; - tmp[1] = '\0'; - nibble2 = atoi(tmp); - } else if (g_ascii_isalpha(*cursor) && (gint) (*cursor - 87) < 16) { - nibble2 = (gint) *cursor - 87; - } else { - purple_debug_warning("QQ", "Invalid char found in hex string!\n"); - g_free(hex_str); - return NULL; - } - bytes[index++] = nibble1 + nibble2; - } - *out_len = strlen(hex_str) / 2; - g_free(hex_str); - return g_memdup(bytes, *out_len); -} - -/* Dumps a chunk of raw data into an ASCII hex string. - * The return should be freed later. */ -static gchar *hex_dump_to_str(const guint8 *const buffer, gint bytes) -{ - GString *str; - gchar *ret; - gint i, j, ch; - - str = g_string_new(""); - for (i = 0; i < bytes; i += 16) { - /* length label */ - g_string_append_printf(str, "%07x: ", i); - - /* dump hex value */ - for (j = 0; j < 16; j++) - if ((i + j) < bytes) - g_string_append_printf(str, " %02x", buffer[i + j]); - else - g_string_append(str, " --"); - g_string_append(str, " "); - - /* dump ascii value */ - for (j = 0; j < 16 && (i + j) < bytes; j++) { - ch = buffer[i + j] & 127; - if (ch < ' ' || ch == 127) - g_string_append_c(str, '.'); - else - g_string_append_c(str, ch); - } - g_string_append_c(str, '\n'); - } - - ret = str->str; - /* GString can be freed without freeing it character data */ - g_string_free(str, FALSE); - - return ret; -} - -void qq_hex_dump(PurpleDebugLevel level, const char *category, - const guint8 *pdata, gint bytes, - const char *format, ...) -{ - va_list args; - char *arg_s = NULL; - gchar *phex = NULL; - - g_return_if_fail(level != PURPLE_DEBUG_ALL); - g_return_if_fail(format != NULL); - - va_start(args, format); - arg_s = g_strdup_vprintf(format, args); - va_end(args); - - if (bytes <= 0) { - purple_debug(level, category, "%s", arg_s); - return; - } - - phex = hex_dump_to_str(pdata, bytes); - purple_debug(level, category, "%s - (len %d)\n%s", arg_s, bytes, phex); - g_free(phex); -} - -void qq_show_packet(const gchar *desc, const guint8 *buf, gint len) -{ - qq_hex_dump(PURPLE_DEBUG_WARNING, "QQ", buf, len, desc); -} - -void qq_filter_str(gchar *str) { - gchar *temp; - if (str == NULL) { - return; - } - - for (temp = str; *temp != 0; temp++) { - /*if (*temp == '\r' || *temp == '\n') *temp = ' ';*/ - if (*temp > 0 && *temp < 0x20) *temp = ' '; - } - g_strstrip(str); -} diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/qq/utils.h --- a/libpurple/protocols/qq/utils.h Thu May 05 03:40:29 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,56 +0,0 @@ -/** - * @file utils.h - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * 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 02111-1301 USA - */ - -#ifndef _QQ_MY_UTILS_H_ -#define _QQ_MY_UTILS_H_ - -#include -#include -#include "qq.h" - -#include "debug.h" - -void qq_get_md5(guint8 *md5, gint md5_len, const guint8* const src, gint src_len); - -gchar *get_name_by_index_str(gchar **array, const gchar *index_str, gint amount); -gchar *get_index_str_by_name(gchar **array, const gchar *name, gint amount); - -gchar **split_data(guint8 *data, gint len, const gchar *delimit, gint expected_fields); - -gchar *gen_ip_str(guint8 *ip); -guint8 *str_ip_gen(gchar *str); - -UID purple_name_to_uid(const gchar *name); -gchar *uid_to_purple_name(UID uid); - -gchar *try_dump_as_gbk(const guint8 *const data, gint len); - -void qq_show_packet(const gchar *desc, const guint8 *buf, gint len); -void qq_hex_dump(PurpleDebugLevel level, const char *category, - const guint8 *pdata, gint bytes, - const char *format, ...); -guint8 *hex_str_to_bytes(const gchar *buf, gint *out_len); - -void qq_filter_str(gchar *str); -#endif diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/simple/simple.c --- a/libpurple/protocols/simple/simple.c Thu May 05 03:40:29 2011 +0000 +++ b/libpurple/protocols/simple/simple.c Mon May 09 04:26:46 2011 +0000 @@ -1903,7 +1903,8 @@ } else { /* UDP */ purple_debug_info("simple", "using udp with server %s and port %d\n", hostname, port); - sip->query_data = purple_dnsquery_a(hostname, port, simple_udp_host_resolved, sip); + sip->query_data = purple_dnsquery_a_account(sip->account, hostname, + port, simple_udp_host_resolved, sip); if (sip->query_data == NULL) { purple_connection_error_reason(sip->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, @@ -1965,7 +1966,7 @@ hosttoconnect = purple_account_get_string(account, "proxy", sip->servername); } - sip->srv_query_data = purple_srv_resolve("sip", + sip->srv_query_data = purple_srv_resolve_account(account, "sip", sip->udp ? "udp" : "tcp", hosttoconnect, srvresolved, sip); } diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/protocols/yahoo/yahoo_filexfer.c --- a/libpurple/protocols/yahoo/yahoo_filexfer.c Thu May 05 03:40:29 2011 +0000 +++ b/libpurple/protocols/yahoo/yahoo_filexfer.c Mon May 09 04:26:46 2011 +0000 @@ -1660,6 +1660,7 @@ } if(val_222 == 3) { + PurpleAccount *account; xfer = g_hash_table_lookup(yd->xfer_peer_idstring_map, xfer_peer_idstring); if(!xfer) @@ -1679,14 +1680,17 @@ return; } + account = purple_connection_get_account(gc); if (yd->jp) { - purple_dnsquery_a(YAHOOJP_XFER_RELAY_HOST, YAHOOJP_XFER_RELAY_PORT, + purple_dnsquery_a_account(account, YAHOOJP_XFER_RELAY_HOST, + YAHOOJP_XFER_RELAY_PORT, yahoo_xfer_dns_connected_15, xfer); } else { - purple_dnsquery_a(YAHOO_XFER_RELAY_HOST, YAHOO_XFER_RELAY_PORT, + purple_dnsquery_a_account(account, YAHOO_XFER_RELAY_HOST, + YAHOO_XFER_RELAY_PORT, yahoo_xfer_dns_connected_15, xfer); } return; @@ -1784,7 +1788,6 @@ char *xfer_idstring_for_relay = NULL; GSList *l; struct yahoo_packet *pkt_to_send; - PurpleAccount *account; struct yahoo_p2p_data *p2p_data; yd = gc->proto_data; @@ -1838,7 +1841,8 @@ xfer_data->info_val_249 = val_249; xfer_data->xfer_idstring_for_relay = g_strdup(xfer_idstring_for_relay); - if(val_249 == 1 || val_249 == 3) { + if(val_249 == 1 || val_249 == 3) { + PurpleAccount *account; if (!purple_url_parse(url, &(xfer_data->host), &(xfer_data->port), &(xfer_data->path), NULL, NULL)) { purple_xfer_cancel_remote(xfer); return; diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/proxy.c --- a/libpurple/proxy.c Thu May 05 03:40:29 2011 +0000 +++ b/libpurple/proxy.c Mon May 09 04:26:46 2011 +0000 @@ -29,6 +29,7 @@ /* it is intended to : 1st handle http proxy, using the CONNECT command , 2nd provide an easy way to add socks support , 3rd draw women to it like flies to honey */ +#define _PURPLE_PROXY_C_ #include "internal.h" #include "cipher.h" @@ -69,6 +70,7 @@ guchar *read_buffer; gsize read_buf_len; gsize read_len; + PurpleAccount *account; }; static const char * const socks5errors[] = { @@ -1367,7 +1369,8 @@ proxy_do_write(connect_data, connect_data->fd, PURPLE_INPUT_WRITE); } else { - connect_data->query_data = purple_dnsquery_a(connect_data->host, + connect_data->query_data = purple_dnsquery_a_account( + connect_data->account, connect_data->host, connect_data->port, s4_host_resolved, connect_data); if (connect_data->query_data == NULL) { @@ -2137,6 +2140,7 @@ break; case PURPLE_PROXY_SOCKS5: + case PURPLE_PROXY_TOR: proxy_connect_socks5(connect_data, addr, addrlen); break; @@ -2281,6 +2285,7 @@ connect_data->host = g_strdup(host); connect_data->port = port; connect_data->gpi = purple_proxy_get_setup(account); + connect_data->account = account; if ((purple_proxy_info_get_type(connect_data->gpi) != PURPLE_PROXY_NONE) && (purple_proxy_info_get_host(connect_data->gpi) == NULL || @@ -2299,6 +2304,7 @@ case PURPLE_PROXY_HTTP: case PURPLE_PROXY_SOCKS4: case PURPLE_PROXY_SOCKS5: + case PURPLE_PROXY_TOR: case PURPLE_PROXY_USE_ENVVAR: connecthost = purple_proxy_info_get_host(connect_data->gpi); connectport = purple_proxy_info_get_port(connect_data->gpi); @@ -2311,7 +2317,7 @@ return NULL; } - connect_data->query_data = purple_dnsquery_a(connecthost, + connect_data->query_data = purple_dnsquery_a_account(account, connecthost, connectport, connection_host_resolved, connect_data); if (connect_data->query_data == NULL) { @@ -2347,6 +2353,7 @@ connect_data->host = g_strdup(host); connect_data->port = port; connect_data->gpi = purple_proxy_get_setup(account); + connect_data->account = account; if ((purple_proxy_info_get_type(connect_data->gpi) != PURPLE_PROXY_NONE) && (purple_proxy_info_get_host(connect_data->gpi) == NULL || @@ -2365,6 +2372,7 @@ case PURPLE_PROXY_HTTP: case PURPLE_PROXY_SOCKS4: case PURPLE_PROXY_SOCKS5: + case PURPLE_PROXY_TOR: case PURPLE_PROXY_USE_ENVVAR: purple_debug_info("proxy", "Ignoring Proxy type (%d) for UDP.\n", purple_proxy_info_get_type(connect_data->gpi)); @@ -2377,7 +2385,7 @@ return NULL; } - connect_data->query_data = purple_dnsquery_a(connecthost, + connect_data->query_data = purple_dnsquery_a_account(account, connecthost, connectport, connection_host_resolved, connect_data); if (connect_data->query_data == NULL) { @@ -2390,16 +2398,63 @@ return connect_data; } -/* - * Combine some of this code with purple_proxy_connect() - */ PurpleProxyConnectData * purple_proxy_connect_socks5(void *handle, PurpleProxyInfo *gpi, const char *host, int port, PurpleProxyConnectFunction connect_cb, gpointer data) { + return purple_proxy_connect_socks5_account(NULL, handle, gpi, + host, port, connect_cb, data); +} + + +/* This is called when we connect to the SOCKS5 proxy server (through any + * relevant account proxy) + */ +static void socks5_connected_to_proxy(gpointer data, gint source, + const gchar *error_message) { + /* This is the PurpleProxyConnectData for the overall SOCKS5 connection */ + PurpleProxyConnectData *connect_data = data; + + /* Check that the overall SOCKS5 connection wasn't cancelled while we were + * connecting to it (we don't have a way of associating the process of + * connecting to the SOCKS5 server to the overall PurpleProxyConnectData) + */ + if (!PURPLE_PROXY_CONNECT_DATA_IS_VALID(connect_data)) + return; + + if (error_message != NULL) { + purple_debug_error("proxy", "Unable to connect to SOCKS5 host.\n"); + connect_data->connect_cb(connect_data->data, source, error_message); + return; + } + + purple_debug_info("proxy", "Initiating SOCKS5 negotiation.\n"); + + purple_debug_info("proxy", + "Connecting to %s:%d via %s:%d using SOCKS5\n", + connect_data->host, connect_data->port, + purple_proxy_info_get_host(connect_data->gpi), + purple_proxy_info_get_port(connect_data->gpi)); + + connect_data->fd = source; + + s5_canwrite(connect_data, connect_data->fd, PURPLE_INPUT_WRITE); +} + +/* + * Combine some of this code with purple_proxy_connect() + */ +PurpleProxyConnectData * +purple_proxy_connect_socks5_account(void *handle, PurpleAccount *account, + PurpleProxyInfo *gpi, + const char *host, int port, + PurpleProxyConnectFunction connect_cb, + gpointer data) +{ PurpleProxyConnectData *connect_data; + PurpleProxyConnectData *account_proxy_conn_data; g_return_val_if_fail(host != NULL, NULL); g_return_val_if_fail(port >= 0, NULL); @@ -2414,17 +2469,28 @@ connect_data->host = g_strdup(host); connect_data->port = port; connect_data->gpi = gpi; - - connect_data->query_data = - purple_dnsquery_a(purple_proxy_info_get_host(gpi), - purple_proxy_info_get_port(gpi), - connection_host_resolved, connect_data); - if (connect_data->query_data == NULL) - { + connect_data->account = account; + + /* If there is an account proxy, use it to connect to the desired SOCKS5 + * proxy. + */ + account_proxy_conn_data = purple_proxy_connect(connect_data->handle, + connect_data->account, + purple_proxy_info_get_host(connect_data->gpi), + purple_proxy_info_get_port(connect_data->gpi), + socks5_connected_to_proxy, connect_data); + + if (account_proxy_conn_data == NULL) { + purple_debug_error("proxy", "Unable to initiate connection to account proxy.\n"); purple_proxy_connect_data_destroy(connect_data); return NULL; } + /* The API doesn't really provide us with a way to cancel the specific + * proxy connection attempt (account_proxy_conn_data) when the overall + * SOCKS5 connection (connect_data) attempt is cancelled :( + */ + handles = g_slist_prepend(handles, connect_data); return connect_data; @@ -2470,6 +2536,8 @@ proxytype = PURPLE_PROXY_SOCKS4; else if (purple_strequal(type, "socks5")) proxytype = PURPLE_PROXY_SOCKS5; + else if (purple_strequal(type, "tor")) + proxytype = PURPLE_PROXY_TOR; else if (purple_strequal(type, "envvar")) proxytype = PURPLE_PROXY_USE_ENVVAR; else diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/proxy.h --- a/libpurple/proxy.h Thu May 05 03:40:29 2011 +0000 +++ b/libpurple/proxy.h Mon May 09 04:26:46 2011 +0000 @@ -39,7 +39,8 @@ PURPLE_PROXY_HTTP, /**< HTTP proxy. */ PURPLE_PROXY_SOCKS4, /**< SOCKS 4 proxy. */ PURPLE_PROXY_SOCKS5, /**< SOCKS 5 proxy. */ - PURPLE_PROXY_USE_ENVVAR /**< Use environmental settings. */ + PURPLE_PROXY_USE_ENVVAR, /**< Use environmental settings. */ + PURPLE_PROXY_TOR /**< Use a Tor proxy (SOCKS 5 really) */ } PurpleProxyType; @@ -288,6 +289,37 @@ /** * Makes a connection through a SOCKS5 proxy. * + * Note that if the account that is making the connection uses a proxy, this + * connection to a SOCKS5 proxy will be made through the account proxy. + * + * @param handle A handle that should be associated with this + * connection attempt. The handle can be used + * to cancel the connection attempt using the + * purple_proxy_connect_cancel_with_handle() + * function. + * @param account The account making the connection. + * @param gpi The PurpleProxyInfo specifying the proxy settings + * @param host The destination host. + * @param port The destination port. + * @param connect_cb The function to call when the connection is + * established. If the connection failed then + * fd will be -1 and error message will be set + * to something descriptive (hopefully). + * @param data User-defined data. + * + * @return NULL if there was an error, or a reference to an + * opaque data structure that can be used to cancel + * the pending connection, if needed. + */ +PurpleProxyConnectData *purple_proxy_connect_socks5_account(void *handle, + PurpleAccount *account, PurpleProxyInfo *gpi, + const char *host, int port, + PurpleProxyConnectFunction connect_cb, gpointer data); + +#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_PROXY_C_) +/** + * Makes a connection through a SOCKS5 proxy. + * * @param handle A handle that should be associated with this * connection attempt. The handle can be used * to cancel the connection attempt using the @@ -305,11 +337,13 @@ * @return NULL if there was an error, or a reference to an * opaque data structure that can be used to cancel * the pending connection, if needed. + * @deprecated Use purple_proxy_connect_socks5_account instead */ PurpleProxyConnectData *purple_proxy_connect_socks5(void *handle, PurpleProxyInfo *gpi, const char *host, int port, PurpleProxyConnectFunction connect_cb, gpointer data); +#endif /** * Cancel an in-progress connection attempt. This should be called diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/stun.c --- a/libpurple/stun.c Thu May 05 03:40:29 2011 +0000 +++ b/libpurple/stun.c Mon May 09 04:26:46 2011 +0000 @@ -365,7 +365,7 @@ purple_debug_info("stun", "got %d SRV responses, server: %s, port: %d\n", results, servername, port); - purple_dnsquery_a(servername, port, hbn_cb, NULL); + purple_dnsquery_a_account(NULL, servername, port, hbn_cb, NULL); g_free(resp); } @@ -424,7 +424,7 @@ nattype.servername = g_strdup(servername); callbacks = g_slist_append(callbacks, cb); - purple_srv_resolve("stun", "udp", servername, do_test1, + purple_srv_resolve_account(NULL, "stun", "udp", servername, do_test1, (gpointer) servername); return &nattype; diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/tests/Makefile.am --- a/libpurple/tests/Makefile.am Thu May 05 03:40:29 2011 +0000 +++ b/libpurple/tests/Makefile.am Mon May 09 04:26:46 2011 +0000 @@ -15,7 +15,6 @@ test_jabber_jutil.c \ test_jabber_scram.c \ test_oscar_util.c \ - test_qq.c \ test_yahoo_util.c \ test_util.c \ $(top_builddir)/libpurple/util.h @@ -32,7 +31,6 @@ check_libpurple_LDADD=\ $(top_builddir)/libpurple/protocols/jabber/libjabber.la \ $(top_builddir)/libpurple/protocols/oscar/liboscar.la \ - $(top_builddir)/libpurple/protocols/qq/libqq_tmp.la \ $(top_builddir)/libpurple/protocols/yahoo/libymsg.la \ $(top_builddir)/libpurple/libpurple.la \ @CHECK_LIBS@ \ diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/tests/check_libpurple.c --- a/libpurple/tests/check_libpurple.c Thu May 05 03:40:29 2011 +0000 +++ b/libpurple/tests/check_libpurple.c Mon May 09 04:26:46 2011 +0000 @@ -89,7 +89,6 @@ srunner_add_suite(sr, jabber_jutil_suite()); srunner_add_suite(sr, jabber_scram_suite()); srunner_add_suite(sr, oscar_util_suite()); - srunner_add_suite(sr, qq_suite()); srunner_add_suite(sr, yahoo_util_suite()); srunner_add_suite(sr, util_suite()); diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/tests/test_qq.c --- a/libpurple/tests/test_qq.c Thu May 05 03:40:29 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,105 +0,0 @@ -#include - -#include "tests.h" -#include "../protocols/qq/qq_crypt.h" - -START_TEST(test_qq_encrypt) -{ - const guint8 * const key = (guint8 *)"hamburger"; - guint8 crypted[80]; - gint ret; - - ret = qq_encrypt(crypted, (const guint8 * const)"a", 1, key); - assert_int_equal(16, ret); - - ret = qq_encrypt(crypted, (const guint8 * const)"aa", 2, key); - assert_int_equal(16, ret); - - ret = qq_encrypt(crypted, (const guint8 * const)"aaa", 3, key); - assert_int_equal(16, ret); - - ret = qq_encrypt(crypted, (const guint8 * const)"aaaa", 4, key); - assert_int_equal(16, ret); - - ret = qq_encrypt(crypted, (const guint8 * const)"aaaaa", 5, key); - assert_int_equal(16, ret); - - ret = qq_encrypt(crypted, (const guint8 * const)"aaaaaa", 6, key); - assert_int_equal(16, ret); - - ret = qq_encrypt(crypted, (const guint8 * const)"aaaaaaa", 7, key); - assert_int_equal(24, ret); - - ret = qq_encrypt(crypted, (const guint8 * const)"aaaaaaaa", 8, key); - assert_int_equal(24, ret); - - ret = qq_encrypt(crypted, (const guint8 * const)"aaaaaaaaa", 9, key); - assert_int_equal(24, ret); - - ret = qq_encrypt(crypted, (const guint8 * const)"aaaaaaaaaa", 10, key); - assert_int_equal(24, ret); - - ret = qq_encrypt(crypted, - (const guint8 * const)"aaaaaaaaaaa", 11, key); - assert_int_equal(24, ret); - - ret = qq_encrypt(crypted, - (const guint8 * const)"aaaaaaaaaaaa", 12, key); - assert_int_equal(24, ret); - - ret = qq_encrypt(crypted, - (const guint8 * const)"aaaaaaaaaaaaa", 13, key); - assert_int_equal(24, ret); - - ret = qq_encrypt(crypted, - (const guint8 * const)"aaaaaaaaaaaaaa", 14, key); - assert_int_equal(24, ret); - - ret = qq_encrypt(crypted, - (const guint8 * const)"aaaaaaaaaaaaaaa", 15, key); - assert_int_equal(32, ret); - - ret = qq_encrypt(crypted, - (const guint8 * const)"aaaaaaaaaaaaaaaa", 16, key); - assert_int_equal(32, ret); - - ret = qq_encrypt(crypted, - (const guint8 * const)"aaaaaaaaaaaaaaaaa", 17, key); - assert_int_equal(32, ret); - - ret = qq_encrypt(crypted, - (const guint8 * const)"aaaaaaaaaaaaaaaaaa", 18, key); - assert_int_equal(32, ret); - - ret = qq_encrypt(crypted, - (const guint8 * const)"aaaaaaaaaaaaaaaaaaa", 19, key); - assert_int_equal(32, ret); - - /* - fprintf(stderr, "crypted=%s\n", crypted); - assert_string_equal_free("plain", - yahoo_codes_to_html("plain")); - */ -} -END_TEST - -START_TEST(test_qq_decrypt) -{ -} -END_TEST - -Suite * -qq_suite(void) -{ - Suite *s; - TCase *tc; - - s = suite_create("QQ"); - - tc = tcase_create("QQ Crypt Functions"); - tcase_add_test(tc, test_qq_encrypt); - tcase_add_test(tc, test_qq_decrypt); - suite_add_tcase(s, tc); - - return s; -} diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/tests/tests.h --- a/libpurple/tests/tests.h Thu May 05 03:40:29 2011 +0000 +++ b/libpurple/tests/tests.h Mon May 09 04:26:46 2011 +0000 @@ -14,7 +14,6 @@ Suite * jabber_jutil_suite(void); Suite * jabber_scram_suite(void); Suite * oscar_util_suite(void); -Suite * qq_suite(void); Suite * yahoo_util_suite(void); Suite * util_suite(void); diff -r ea4bb5fe1fdc -r 0d4702446530 libpurple/util.c --- a/libpurple/util.c Thu May 05 03:40:29 2011 +0000 +++ b/libpurple/util.c Mon May 09 04:26:46 2011 +0000 @@ -713,6 +713,8 @@ g_return_val_if_fail(timestamp != NULL, 0); + memset(&t, 0, sizeof(struct tm)); + str = timestamp; /* Strip leading whitespace */ diff -r ea4bb5fe1fdc -r 0d4702446530 pidgin/gtkaccount.c --- a/pidgin/gtkaccount.c Thu May 05 03:40:29 2011 +0000 +++ b/pidgin/gtkaccount.c Mon May 09 04:26:46 2011 +0000 @@ -1003,12 +1003,6 @@ gtk_list_store_append(model, &iter); gtk_list_store_set(model, &iter, - 0, _("HTTP"), - 1, PURPLE_PROXY_HTTP, - -1); - - gtk_list_store_append(model, &iter); - gtk_list_store_set(model, &iter, 0, _("SOCKS 4"), 1, PURPLE_PROXY_SOCKS4, -1); @@ -1021,6 +1015,18 @@ gtk_list_store_append(model, &iter); gtk_list_store_set(model, &iter, + 0, _("Tor/Privacy (SOCKS5)"), + 1, PURPLE_PROXY_TOR, + -1); + + gtk_list_store_append(model, &iter); + gtk_list_store_set(model, &iter, + 0, _("HTTP"), + 1, PURPLE_PROXY_HTTP, + -1); + + gtk_list_store_append(model, &iter); + gtk_list_store_set(model, &iter, 0, _("Use Environmental Settings"), 1, PURPLE_PROXY_USE_ENVVAR, -1); @@ -1036,8 +1042,14 @@ static void proxy_type_changed_cb(GtkWidget *menu, AccountPrefsDialog *dialog) { - dialog->new_proxy_type = - gtk_combo_box_get_active(GTK_COMBO_BOX(menu)) - 1; + GtkTreeIter iter; + + if (gtk_combo_box_get_active_iter(GTK_COMBO_BOX(menu), &iter)) { + int int_value; + gtk_tree_model_get(gtk_combo_box_get_model(GTK_COMBO_BOX(menu)), &iter, + 1, &int_value, -1); + dialog->new_proxy_type = int_value; + } if (dialog->new_proxy_type == PURPLE_PROXY_USE_GLOBAL || dialog->new_proxy_type == PURPLE_PROXY_NONE || @@ -1079,6 +1091,8 @@ PurpleProxyInfo *proxy_info; GtkWidget *vbox; GtkWidget *vbox2; + GtkTreeIter iter; + GtkTreeModel *proxy_model; if (dialog->proxy_frame != NULL) gtk_widget_destroy(dialog->proxy_frame); @@ -1125,21 +1139,10 @@ if (dialog->account != NULL && (proxy_info = purple_account_get_proxy_info(dialog->account)) != NULL) { - - PurpleProxyType type = purple_proxy_info_get_type(proxy_info); const char *value; int int_val; - /* Hah! */ - /* I dunno what you're laughing about, fuzz ball. */ - dialog->new_proxy_type = type; - gtk_combo_box_set_active(GTK_COMBO_BOX(dialog->proxy_dropdown), - type + 1); - - if (type == PURPLE_PROXY_USE_GLOBAL || type == PURPLE_PROXY_NONE || - type == PURPLE_PROXY_USE_ENVVAR) - gtk_widget_hide_all(vbox2); - + dialog->new_proxy_type = purple_proxy_info_get_type(proxy_info); if ((value = purple_proxy_info_get_host(proxy_info)) != NULL) gtk_entry_set_text(GTK_ENTRY(dialog->proxy_host_entry), value); @@ -1157,14 +1160,26 @@ if ((value = purple_proxy_info_get_password(proxy_info)) != NULL) gtk_entry_set_text(GTK_ENTRY(dialog->proxy_pass_entry), value); - } - else { + + } else dialog->new_proxy_type = PURPLE_PROXY_USE_GLOBAL; - gtk_combo_box_set_active(GTK_COMBO_BOX(dialog->proxy_dropdown), - dialog->new_proxy_type + 1); - gtk_widget_hide_all(vbox2); + + proxy_model = gtk_combo_box_get_model( + GTK_COMBO_BOX(dialog->proxy_dropdown)); + if (gtk_tree_model_get_iter_first(proxy_model, &iter)) { + int int_val; + do { + gtk_tree_model_get(proxy_model, &iter, 1, &int_val, -1); + if (int_val == dialog->new_proxy_type) { + gtk_combo_box_set_active_iter( + GTK_COMBO_BOX(dialog->proxy_dropdown), &iter); + break; + } + } while(gtk_tree_model_iter_next(proxy_model, &iter)); } + proxy_type_changed_cb(dialog->proxy_dropdown, dialog); + /* Connect signals. */ g_signal_connect(G_OBJECT(dialog->proxy_dropdown), "changed", G_CALLBACK(proxy_type_changed_cb), dialog); @@ -2254,7 +2269,7 @@ G_CALLBACK(account_treeview_double_click_cb), dialog); gtk_notebook_append_page(GTK_NOTEBOOK(accounts_window->notebook), - pidgin_make_scrollable(treeview, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC, GTK_SHADOW_NONE, -1, -1), + pidgin_make_scrollable(treeview, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC, GTK_SHADOW_NONE, -1, -1), NULL); add_columns(treeview, dialog); diff -r ea4bb5fe1fdc -r 0d4702446530 pidgin/gtkprefs.c --- a/pidgin/gtkprefs.c Thu May 05 03:40:29 2011 +0000 +++ b/pidgin/gtkprefs.c Mon May 09 04:26:46 2011 +0000 @@ -2041,9 +2041,10 @@ pidgin_prefs_dropdown(prefs_proxy_frame, _("Proxy t_ype:"), PURPLE_PREF_STRING, "/purple/proxy/type", _("No proxy"), "none", - "SOCKS 4", "socks4", - "SOCKS 5", "socks5", - "HTTP", "http", + _("SOCKS 4"), "socks4", + _("SOCKS 5"), "socks5", + _("Tor/Privacy (SOCKS5)"), "tor", + _("HTTP"), "http", _("Use Environmental Settings"), "envvar", NULL); gtk_box_pack_start(GTK_BOX(prefs_proxy_frame), prefs_proxy_subframe, 0, 0, 0); diff -r ea4bb5fe1fdc -r 0d4702446530 pidgin/pixmaps/Makefile.am --- a/pidgin/pixmaps/Makefile.am Thu May 05 03:40:29 2011 +0000 +++ b/pidgin/pixmaps/Makefile.am Mon May 09 04:26:46 2011 +0000 @@ -103,7 +103,6 @@ emblems/16/male.png \ emblems/16/not-authorized.png \ emblems/16/operator.png \ - emblems/16/qq-member.png \ emblems/16/secure.png \ emblems/16/unavailable.png \ emblems/16/video.png \ @@ -119,7 +118,6 @@ emblems/scalable/game.svg \ emblems/scalable/male.svg \ emblems/scalable/not-authorized.svg \ - emblems/scalable/qq-member.svg \ emblems/scalable/secure.svg \ emblems/scalable/unavailable.svg \ emblems/scalable/video.svg \ @@ -181,7 +179,6 @@ emotes/default/24/scalable/plate.svg \ emotes/default/24/scalable/poop.svg \ emotes/default/24/scalable/present.svg \ - emotes/default/24/scalable/qq.svg \ emotes/default/24/scalable/rainbow.svg \ emotes/default/24/scalable/rain.svg \ emotes/default/24/scalable/rose-dead.svg \ @@ -216,7 +213,6 @@ protocols/16/scalable/jabber.svg \ protocols/16/scalable/meanwhile.svg \ protocols/16/scalable/msn.svg \ - protocols/16/scalable/qq.svg \ protocols/16/scalable/silc.svg \ protocols/16/scalable/simple.svg \ protocols/16/scalable/yahoo.svg \ @@ -236,7 +232,6 @@ protocols/16/msn.png \ protocols/16/mxit.png \ protocols/16/myspace.png \ - protocols/16/qq.png \ protocols/16/silc.png \ protocols/16/simple.png \ protocols/16/yahoo.png \ @@ -273,7 +268,6 @@ protocols/22/scalable/jabber.svg \ protocols/22/scalable/meanwhile.svg \ protocols/22/scalable/msn.svg \ - protocols/22/scalable/qq.svg \ protocols/22/scalable/silc.svg \ protocols/22/scalable/simple.svg \ protocols/22/scalable/yahoo.svg \ @@ -292,7 +286,6 @@ protocols/22/meanwhile.png \ protocols/22/msn.png \ protocols/22/myspace.png \ - protocols/22/qq.png \ protocols/22/silc.png \ protocols/22/simple.png \ protocols/22/yahoo.png \ @@ -311,7 +304,6 @@ protocols/48/msn.png \ protocols/48/mxit.png \ protocols/48/myspace.png \ - protocols/48/qq.png \ protocols/48/silc.png \ protocols/48/simple.png \ protocols/48/yahoo.png \ @@ -329,7 +321,6 @@ protocols/scalable/meanwhile.svg \ protocols/scalable/msn.svg \ protocols/scalable/mxit.svg \ - protocols/scalable/qq.svg \ protocols/scalable/silc.svg \ protocols/scalable/simple.svg \ protocols/scalable/yahoo.svg \ diff -r ea4bb5fe1fdc -r 0d4702446530 pidgin/pixmaps/emblems/16/qq-member.png Binary file pidgin/pixmaps/emblems/16/qq-member.png has changed diff -r ea4bb5fe1fdc -r 0d4702446530 pidgin/pixmaps/emblems/scalable/qq-member.svg --- a/pidgin/pixmaps/emblems/scalable/qq-member.svg Thu May 05 03:40:29 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,198 +0,0 @@ - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - diff -r ea4bb5fe1fdc -r 0d4702446530 pidgin/pixmaps/emotes/default/24/Makefile.am --- a/pidgin/pixmaps/emotes/default/24/Makefile.am Thu May 05 03:40:29 2011 +0000 +++ b/pidgin/pixmaps/emotes/default/24/Makefile.am Mon May 09 04:26:46 2011 +0000 @@ -135,7 +135,6 @@ pray.png \ present.png \ pumpkin.png \ - qq.png \ question.png \ quiet.png \ rainbow.png \ diff -r ea4bb5fe1fdc -r 0d4702446530 pidgin/pixmaps/emotes/default/24/qq.png Binary file pidgin/pixmaps/emotes/default/24/qq.png has changed diff -r ea4bb5fe1fdc -r 0d4702446530 pidgin/pixmaps/emotes/default/24/scalable/qq.svg --- a/pidgin/pixmaps/emotes/default/24/scalable/qq.svg Thu May 05 03:40:29 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,138 +0,0 @@ - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - diff -r ea4bb5fe1fdc -r 0d4702446530 pidgin/pixmaps/protocols/16/qq.png Binary file pidgin/pixmaps/protocols/16/qq.png has changed diff -r ea4bb5fe1fdc -r 0d4702446530 pidgin/pixmaps/protocols/16/scalable/qq.svg --- a/pidgin/pixmaps/protocols/16/scalable/qq.svg Thu May 05 03:40:29 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,285 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - diff -r ea4bb5fe1fdc -r 0d4702446530 pidgin/pixmaps/protocols/22/qq.png Binary file pidgin/pixmaps/protocols/22/qq.png has changed diff -r ea4bb5fe1fdc -r 0d4702446530 pidgin/pixmaps/protocols/22/scalable/qq.svg --- a/pidgin/pixmaps/protocols/22/scalable/qq.svg Thu May 05 03:40:29 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,242 +0,0 @@ - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - diff -r ea4bb5fe1fdc -r 0d4702446530 pidgin/pixmaps/protocols/48/qq.png Binary file pidgin/pixmaps/protocols/48/qq.png has changed diff -r ea4bb5fe1fdc -r 0d4702446530 pidgin/pixmaps/protocols/scalable/qq.svg --- a/pidgin/pixmaps/protocols/scalable/qq.svg Thu May 05 03:40:29 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,291 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff -r ea4bb5fe1fdc -r 0d4702446530 pidgin/plugins/vvconfig.c --- a/pidgin/plugins/vvconfig.c Thu May 05 03:40:29 2011 +0000 +++ b/pidgin/plugins/vvconfig.c Mon May 09 04:26:46 2011 +0000 @@ -90,7 +90,17 @@ } element = gst_element_factory_make(element_name, "test"); + if(!element) { + purple_debug_info("vvconfig", "'%s' - unable to find element\n", element_name); + return g_list_reverse(ret); + } + klass = G_OBJECT_GET_CLASS (element); + if(!klass) { + purple_debug_info("vvconfig", "'%s' - unable to find G_Object Class\n", element_name); + return g_list_reverse(ret); + } + if (!g_object_class_find_property(klass, "device") || !GST_IS_PROPERTY_PROBE(element) || !(probe = GST_PROPERTY_PROBE(element)) || diff -r ea4bb5fe1fdc -r 0d4702446530 pidgin/win32/nsis/pidgin-installer.nsi --- a/pidgin/win32/nsis/pidgin-installer.nsi Thu May 05 03:40:29 2011 +0000 +++ b/pidgin/win32/nsis/pidgin-installer.nsi Mon May 09 04:26:46 2011 +0000 @@ -580,7 +580,6 @@ Delete "$INSTDIR\plugins\libmyspace.dll" Delete "$INSTDIR\plugins\libnapster.dll" Delete "$INSTDIR\plugins\libnovell.dll" - Delete "$INSTDIR\plugins\libqq.dll" Delete "$INSTDIR\plugins\libsametime.dll" Delete "$INSTDIR\plugins\libsilc.dll" Delete "$INSTDIR\plugins\libsimple.dll" diff -r ea4bb5fe1fdc -r 0d4702446530 po/ChangeLog --- a/po/ChangeLog Thu May 05 03:40:29 2011 +0000 +++ b/po/ChangeLog Mon May 09 04:26:46 2011 +0000 @@ -1,5 +1,8 @@ Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul +version 2.8.0 + * English (Canadian) updated (Elliott Sales de Andrade) + version 2.7.11 * Afrikaans translation updated (Friedel Wolff) * Bengali translation updated (Jamil Ahmed) diff -r ea4bb5fe1fdc -r 0d4702446530 po/POTFILES.in --- a/po/POTFILES.in Thu May 05 03:40:29 2011 +0000 +++ b/po/POTFILES.in Mon May 09 04:26:46 2011 +0000 @@ -151,22 +151,6 @@ libpurple/protocols/oscar/userinfo.c libpurple/protocols/oscar/util.c libpurple/protocols/oscar/visibility.c -libpurple/protocols/qq/buddy_info.c -libpurple/protocols/qq/buddy_list.c -libpurple/protocols/qq/buddy_memo.c -libpurple/protocols/qq/buddy_opt.c -libpurple/protocols/qq/group.c -libpurple/protocols/qq/group_im.c -libpurple/protocols/qq/group_info.c -libpurple/protocols/qq/group_internal.c -libpurple/protocols/qq/group_join.c -libpurple/protocols/qq/group_opt.c -libpurple/protocols/qq/im.c -libpurple/protocols/qq/qq.c -libpurple/protocols/qq/qq_base.c -libpurple/protocols/qq/qq_network.c -libpurple/protocols/qq/qq_process.c -libpurple/protocols/qq/send_file.c libpurple/protocols/sametime/sametime.c libpurple/protocols/silc/buddy.c libpurple/protocols/silc/chat.c diff -r ea4bb5fe1fdc -r 0d4702446530 po/ca.po --- a/po/ca.po Thu May 05 03:40:29 2011 +0000 +++ b/po/ca.po Mon May 09 04:26:46 2011 +0000 @@ -33,8 +33,8 @@ msgstr "" "Project-Id-Version: Pidgin\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2011-01-30 11:04+0100\n" -"PO-Revision-Date: 2011-01-30 11:11+0100\n" +"POT-Creation-Date: 2011-05-07 10:31+0200\n" +"PO-Revision-Date: 2011-05-07 10:48+0200\n" "Last-Translator: Josep Puigdemont i Casamajó \n" "Language-Team: Catalan \n" "Language: ca\n" @@ -239,6 +239,9 @@ msgid "Alias (optional)" msgstr "Àlies (opcional)" +msgid "Invite message (optional)" +msgstr "Missatge d'invitació (opcional)" + msgid "Add in group" msgstr "Afegeix al grup" @@ -1975,6 +1978,9 @@ msgid "Unknown reason" msgstr "Motiu desconegut" +msgid "Aborting DNS lookup in Tor Proxy mode." +msgstr "S'ha avortat la cerca del DNS en el mode de servidor intermediari Tor." + #, c-format msgid "" "Error reading %s: \n" @@ -2405,9 +2411,8 @@ msgid "Create a new directory for each user" msgstr "Crea un directori nou per a cada usuari" -#, fuzzy msgid "Escape the filenames" -msgstr "%s ha cancel·lat la transferència del fitxer" +msgstr "Empra caràcters escapats en els noms de fitxer" msgid "Notes" msgstr "Notes" @@ -3223,6 +3228,21 @@ msgid "Change Gadu-Gadu Password" msgstr "Canvia la contrasenya per al Gadu-Gadu" +msgid "Show status to:" +msgstr "Mostra l'estat a:" + +msgid "All people" +msgstr "Tothom" + +msgid "Only buddies" +msgstr "Només amics" + +msgid "Change status broadcasting" +msgstr "Canvia la difusió de l'estat" + +msgid "Please, select who can see your status" +msgstr "Seleccioneu qui pot veure el vostre estat" + #, c-format msgid "Select a chat for buddy: %s" msgstr "Seleccioneu un xat per a l'amic: %s" @@ -3254,9 +3274,7 @@ msgstr "UIN" #. first name -#. purple_notify_user_info_add_pair( info, _( "Hidden Number" ), profile->hidden ? _( "Yes" ) : _( "No" ) ); #. optional information -#. purple_notify_user_info_add_pair( info, _( "Title" ), profile->title ); msgid "First Name" msgstr "Nom" @@ -3368,6 +3386,19 @@ msgid "GG server" msgstr "Servidor GG" +msgid "Don't use encryption" +msgstr "No empris xifratge" + +msgid "Use encryption if available" +msgstr "Empra xifratge si està disponible" + +#. TODO +msgid "Require encryption" +msgstr "Requereix xifratge" + +msgid "Connection security" +msgstr "Seguretat de la connexió" + #, c-format msgid "Unknown command: %s" msgstr "Ordre desconeguda: %s" @@ -3403,7 +3434,6 @@ #. * buffer that stores what is "being sent" until the #. * PurpleHTTPConnection reports it is fully sent. #. -#. TODO: what to do here - do we really have to disconnect? #. TODO: do we really want to disconnect on a failure to write? #, c-format msgid "Lost connection with server: %s" @@ -3660,6 +3690,9 @@ msgid "action <action to perform>: Perform an action." msgstr "action <acció a dur a terme>: realitza una acció." +msgid "authserv: Send a command to authserv" +msgstr "authserv: envia una ordre al authserv" + msgid "" "away [message]: Set an away message, or use no message to return from being " "away." @@ -4017,7 +4050,6 @@ msgid "Postal Code" msgstr "Codi postal" -#. purple_notify_user_info_add_pair( info, _( "Email" ), profile->email ); msgid "Country" msgstr "País" @@ -4787,18 +4819,9 @@ msgid "Domain" msgstr "Domini" -msgid "Require encryption" -msgstr "Requereix xifratge" - -msgid "Use encryption if available" -msgstr "Empra xifratge si està disponible" - msgid "Use old-style SSL" msgstr "Empra SSL antic" -msgid "Connection security" -msgstr "Seguretat de la connexió" - msgid "Allow plaintext auth over unencrypted streams" msgstr "Permet autorització de text sobre fluxos sense xifrar" @@ -4910,6 +4933,7 @@ "No s'ha pogut enviar el fitxer a %s, atès que l'usuari no permet la " "transferència de fitxers" +#. not success msgid "File Send Failed" msgstr "Ha fallat la transferència del fitxer" @@ -5632,18 +5656,6 @@ msgid "Unable to Add" msgstr "No s'ha pogut afegir" -msgid "Authorization Request Message:" -msgstr "Missatge de petició d'autorització:" - -msgid "Please authorize me!" -msgstr "Autoritzeu-me, si us plau." - -#. * -#. * A wrapper for purple_request_action() that uses @c OK and @c Cancel buttons. -#. -msgid "_OK" -msgstr "_D'acord" - msgid "Error retrieving profile" msgstr "S'ha produït un error en recuperar el perfil" @@ -5856,6 +5868,11 @@ msgid "Mobile message was not sent because it was too long." msgstr "No s'ha enviat el missatge al mòbil perquè era massa llarg." +msgid "Mobile message was not sent because an unknown error occurred." +msgstr "" +"No s'ha pogut enviar el missatge al mòbil perquè s'ha produït un error " +"desconegut." + #, c-format msgid "" "The MSN server will shut down for maintenance in %d minute. You will " @@ -6031,18 +6048,6 @@ msgid "The username specified is invalid." msgstr "El nom d'usuari especificat no és vàlid." -msgid "The PIN you entered is invalid." -msgstr "El PIN que heu introduït no és vàlid." - -msgid "The PIN you entered has an invalid length [4-10]." -msgstr "La llargada del PIN que heu introduït no és vàlida [4-10]." - -msgid "The PIN is invalid. It should only consist of digits [0-9]." -msgstr "El PIN no és vàlid. Només pot contenir dígits [0-9]." - -msgid "The two PINs you entered do not match." -msgstr "Els dos PIN que heu introduït no coincideixen." - msgid "The Display Name you entered is invalid." msgstr "El nom d'usuari que heu introduït no és vàlid." @@ -6066,35 +6071,65 @@ "Encara no s'ha pogut recuperar la informació del vostre perfil. Torneu-ho a " "intentar més tard." -msgid "Your UID" -msgstr "El vostre UID" +#. display name +#. nick name (required) +msgid "Display Name" +msgstr "Nom que es mostrarà" + +#. about me +msgid "About Me" +msgstr "Quant a mi" + +#. where I live +msgid "Where I Live" +msgstr "On visc" + +#. mobile number +msgid "Mobile Number" +msgstr "Número de telèfon mòbil" + +#. is searchable +msgid "Can be searched" +msgstr "Pot cercar-se" + +#. is suggestable +msgid "Can be suggested" +msgstr "Pot suggerir-se" + +msgid "Update your MXit Profile" +msgstr "Actualitzeu el vostre perfil MXit" + +msgid "The PIN you entered is invalid." +msgstr "El PIN que heu introduït no és vàlid." + +msgid "The PIN you entered has an invalid length [4-10]." +msgstr "La llargada del PIN que heu introduït no és vàlida [4-10]." + +msgid "The PIN is invalid. It should only consist of digits [0-9]." +msgstr "El PIN no és vàlid. Només pot contenir dígits [0-9]." + +msgid "The two PINs you entered do not match." +msgstr "Els dos PIN que heu introduït no coincideixen." + +#. show error to user +msgid "PIN Update Error" +msgstr "S'ha produït un error en actualitzar el PIN" #. pin #. pin (required) msgid "PIN" msgstr "PIN" +#. verify pin msgid "Verify PIN" msgstr "Verifiqueu el PIN" -#. display name -#. nick name (required) -msgid "Display Name" -msgstr "Nom que es mostrarà" - -#. hidden -msgid "Hide my number" -msgstr "Oculta el meu número" - -#. mobile number -msgid "Mobile Number" -msgstr "Número de telèfon mòbil" - -msgid "Update your Profile" -msgstr "Actualitzeu el vostre perfil" - -msgid "Here you can update your MXit profile" -msgstr "Aquí podeu actualitzar el vostre perfil MXit" +#. (reference: "libpurple/request.h") +msgid "Change PIN" +msgstr "Canvia el PIN" + +msgid "Change MXit PIN" +msgstr "Canvia el PIN de l'MXit" msgid "View Splash" msgstr "Mostra la pantalla de presentació" @@ -6105,10 +6140,34 @@ msgid "About" msgstr "Quant a" +msgid "Search for user" +msgstr "Cerca un usuari" + +msgid "Search for a MXit contact" +msgstr "Cerca un contacte de l'MXit" + +msgid "Type search information" +msgstr "Escriviu informació de la cerca" + +msgid "_Search" +msgstr "C_erca" + #. display / change profile msgid "Change Profile..." msgstr "Canvia el perfil..." +#. change PIN +msgid "Change PIN..." +msgstr "Canvia el PIN..." + +#. suggested friends +msgid "Suggested friends..." +msgstr "Amics suggerits..." + +#. search for contacts +msgid "Search for contacts..." +msgstr "Cerca contactes..." + #. display splash-screen msgid "View Splash..." msgstr "Mostra la pantalla de presentació..." @@ -6137,6 +6196,9 @@ msgid "Connecting..." msgstr "S'està connectant..." +msgid "The Display Name you entered is too short." +msgstr "El nom d'usuari que heu introduït és massa curt." + msgid "The PIN you entered has an invalid length [7-10]." msgstr "La llargada del PIN que heu introduït no és vàlida [4-10]." @@ -6211,13 +6273,12 @@ msgid "Retrieving User Information..." msgstr "S'està obtenint informació de l'usuari..." -#. you were kicked +msgid "was kicked" +msgstr "ha estat fet fora" + msgid "You have been kicked from this MultiMX." msgstr "Us han fet fora d'aquest MultiMX." -msgid "was kicked" -msgstr "ha estat fet fora" - msgid "_Room Name:" msgstr "Nom de la _Sala:" @@ -6239,9 +6300,19 @@ msgid "Hidden Number" msgstr "Nombre ocult" +msgid "No profile available" +msgstr "El perfil no està disponible" + +msgid "This contact does not have a profile." +msgstr "Aquest contacte no té cap perfil." + msgid "Your MXit ID..." msgstr "El vostre identificador MXit..." +#. contact is in Deleted, Rejected or None state +msgid "Re-Invite" +msgstr "Convida de nou" + #. Configuration options #. WAP server (reference: "libpurple/accountopt.h") msgid "WAP Server" @@ -6256,6 +6327,30 @@ msgid "Last Online" msgstr "Darrer cop en línia" +msgid "Invite Message" +msgstr "Missatge d'invitació" + +msgid "No results" +msgstr "Cap resultat" + +msgid "No contacts found." +msgstr "No s'ha trobat cap contacte." + +#. define columns +msgid "UserId" +msgstr "Usuari" + +msgid "Where I live" +msgstr "On visc" + +#, c-format +msgid "You have %i suggested friends." +msgstr "Teniu %i suggeriments d'amics." + +#, c-format +msgid "We found %i contacts that match your search." +msgstr "Hem trobat %i contactes que coincideixen amb la cerca." + #. we must have lost the connection, so terminate it so that we can reconnect msgid "We have lost the connection to MXit. Please reconnect." msgstr "S'ha trencat la connexió a MXit. Torneu-vos a connectar." @@ -7013,6 +7108,12 @@ msgid "Authorization Denied Message:" msgstr "Missatge de denegació de l'autorització:" +#. * +#. * A wrapper for purple_request_action() that uses @c OK and @c Cancel buttons. +#. +msgid "_OK" +msgstr "_D'acord" + #, c-format msgid "Received unexpected response from %s: %s" msgstr "S'ha rebut una resposta inesperada de %s: %s" @@ -7373,7 +7474,6 @@ msgstr "S'ha rebut l'autorització" #. Unregistered username -#. uid is not exist #. the username does not exist msgid "Username does not exist" msgstr "L'usuari no existeix" @@ -7546,6 +7646,14 @@ msgid "You have been disconnected from chat room %s." msgstr "Se us ha desconnectat de la conversa %s." +msgid "The new formatting is invalid." +msgstr "El format nou no és vàlid." + +msgid "Username formatting can change only capitalization and whitespace." +msgstr "" +"El format del nom d'usuari només pot canviar majúscules i minúscules, i " +"espais en blanc." + msgid "Pop-Up Message" msgstr "Missatge emergent" @@ -7811,14 +7919,6 @@ msgid "ICQ Privacy Options" msgstr "Opcions de privadesa d'ICQ" -msgid "The new formatting is invalid." -msgstr "El format nou no és vàlid." - -msgid "Username formatting can change only capitalization and whitespace." -msgstr "" -"El format del nom d'usuari només pot canviar majúscules i minúscules, i " -"espais en blanc." - msgid "Change Address To:" msgstr "Canvia l'adreça per:" @@ -7844,9 +7944,6 @@ msgid "Type the email address of the buddy you are searching for." msgstr "Escriviu l'adreça de correu de l'amic que estigueu cercant." -msgid "_Search" -msgstr "C_erca" - msgid "Set User Info (web)..." msgstr "Estableix informació d'usuari (web)..." @@ -7883,9 +7980,6 @@ msgid "Search for Buddy by Email Address..." msgstr "Cerca un amic per l'adreça de correu..." -msgid "Don't use encryption" -msgstr "No empris xifratge" - msgid "Use clientLogin" msgstr "Empra clientLogin" @@ -8163,727 +8257,6 @@ msgid "These buddies will always see you as offline" msgstr "Aquests amics us veuran sempre fora de línia" -msgid "Aquarius" -msgstr "Aquari" - -msgid "Pisces" -msgstr "Peixos" - -msgid "Aries" -msgstr "Àries" - -msgid "Taurus" -msgstr "Taure" - -msgid "Gemini" -msgstr "Bessons" - -msgid "Cancer" -msgstr "Cranc" - -msgid "Leo" -msgstr "Lleó" - -msgid "Virgo" -msgstr "Verge" - -msgid "Libra" -msgstr "Balança" - -msgid "Scorpio" -msgstr "Escorpió" - -msgid "Sagittarius" -msgstr "Sagitari" - -msgid "Capricorn" -msgstr "Capricorn" - -msgid "Rat" -msgstr "Rata" - -msgid "Ox" -msgstr "Bou" - -msgid "Tiger" -msgstr "Tigre" - -msgid "Rabbit" -msgstr "Conill" - -msgid "Dragon" -msgstr "Drac" - -msgid "Snake" -msgstr "Serp" - -msgid "Horse" -msgstr "Cavall" - -msgid "Goat" -msgstr "Ovella" - -msgid "Monkey" -msgstr "Mico" - -msgid "Rooster" -msgstr "Gall" - -msgid "Dog" -msgstr "Gos" - -msgid "Pig" -msgstr "Porc" - -msgid "Other" -msgstr "Altres" - -msgid "Visible" -msgstr "Visible" - -msgid "Friend Only" -msgstr "Només amic" - -msgid "Private" -msgstr "Privat" - -msgid "QQ Number" -msgstr "Número QQ" - -msgid "Country/Region" -msgstr "País/Regió" - -msgid "Province/State" -msgstr "Província/Estat" - -msgid "Zipcode" -msgstr "Codi postal" - -msgid "Phone Number" -msgstr "Número de telèfon" - -msgid "Authorize adding" -msgstr "Autoritzar que us afegeixin" - -msgid "Cellphone Number" -msgstr "Número de mòbil" - -msgid "Personal Introduction" -msgstr "Introducció personal" - -msgid "City/Area" -msgstr "Ciutat/Àrea" - -msgid "Publish Mobile" -msgstr "Publica el mòbil" - -msgid "Publish Contact" -msgstr "Publica el contacte" - -msgid "College" -msgstr "Col·legi" - -msgid "Horoscope" -msgstr "Horòscop" - -msgid "Zodiac" -msgstr "Zodíac" - -msgid "Blood" -msgstr "Sang" - -msgid "True" -msgstr "Cert" - -msgid "False" -msgstr "Fals" - -msgid "Modify Contact" -msgstr "Modifica el contacte" - -msgid "Modify Address" -msgstr "Modifica l'adreça" - -msgid "Modify Extended Information" -msgstr "Modifica la informació estesa" - -msgid "Modify Information" -msgstr "Modifica la informació" - -msgid "Update" -msgstr "Actualitza" - -msgid "Could not change buddy information." -msgstr "No s'ha pogut canviar la informació l'amic." - -msgid "Note" -msgstr "Nota" - -# FIXME: "memo", el qq té una terminologia molt peculiar -#. callback -msgid "Buddy Memo" -msgstr "Memo de l'amic" - -msgid "Change his/her memo as you like" -msgstr "Canvieu-ne el memo" - -msgid "_Modify" -msgstr "_Modifica" - -msgid "Memo Modify" -msgstr "Modifica el memo" - -msgid "Server says:" -msgstr "El servidor diu:" - -msgid "Your request was accepted." -msgstr "S'ha acceptat la vostra sol·licitud." - -msgid "Your request was rejected." -msgstr "S'ha rebutjat la vostra sol·licitud." - -#, c-format -msgid "%u requires verification: %s" -msgstr "%u requereix verificació: %s" - -# Nota: títol de finestra -msgid "Add buddy question" -msgstr "Afegir una pregunta" - -msgid "Enter answer here" -msgstr "Introduïu la resposta aquí" - -msgid "Send" -msgstr "Envia" - -msgid "Invalid answer." -msgstr "La resposta no és vàlida" - -msgid "Authorization denied message:" -msgstr "Missatge de denegació de l'autorització:" - -msgid "Sorry, you're not my style." -msgstr "Em sap greu, no sou el meu tipus." - -#, c-format -msgid "%u needs authorization" -msgstr "Cal autorització per a %u" - -# Nota: títol de finestra (josep) -msgid "Add buddy authorize" -msgstr "Autorització per a afegir un amic" - -msgid "Enter request here" -msgstr "Introduïu la sol·licitud aquí" - -msgid "Would you be my friend?" -msgstr "Voleu ser el meu amic?" - -msgid "QQ Buddy" -msgstr "Amic QQ" - -msgid "Add buddy" -msgstr "Afegeix un amic" - -msgid "Invalid QQ Number" -msgstr "El nombre QQ no és vàlid" - -msgid "Failed sending authorize" -msgstr "No s'ha pogut enviar l'autorització" - -#, c-format -msgid "Failed removing buddy %u" -msgstr "No s'ha pogut suprimir l'amic %u" - -#, c-format -msgid "Failed removing me from %d's buddy list" -msgstr "No us heu pogut suprimir de la llista d'amics de %d" - -msgid "No reason given" -msgstr "No s'ha indicat cap motiu" - -#. only need to get value -#, c-format -msgid "You have been added by %s" -msgstr "%s us ha afegit" - -msgid "Would you like to add him?" -msgstr "Voleu afegir-lo?" - -#, c-format -msgid "Rejected by %s" -msgstr "Rebutjat per %s" - -#, c-format -msgid "Message: %s" -msgstr "Missatge: %s" - -msgid "ID: " -msgstr "Identificador: " - -msgid "Group ID" -msgstr "Identificador del Grup" - -msgid "QQ Qun" -msgstr "QQ Qun" - -msgid "Please enter Qun number" -msgstr "Introduïu el número Qun" - -msgid "You can only search for permanent Qun\n" -msgstr "Només podeu cercar Quns permanents\n" - -msgid "(Invalid UTF-8 string)" -msgstr "(No és una cadena UTF-8 vàlida)" - -msgid "Not member" -msgstr "No en sóc membre" - -msgid "Member" -msgstr "Membre" - -msgid "Requesting" -msgstr "Demanant" - -msgid "Admin" -msgstr "Administrador" - -# FIXME -#. XXX: Should this be "Topic"? -msgid "Room Title" -msgstr "Nom de la sala" - -msgid "Notice" -msgstr "Avís" - -msgid "Detail" -msgstr "Detalls" - -msgid "Creator" -msgstr "Creador" - -msgid "About me" -msgstr "Quant a mi" - -msgid "Category" -msgstr "Categoria" - -msgid "The Qun does not allow others to join" -msgstr "Aquest Qun no permet que s'hi afegeixi ningú" - -msgid "Join QQ Qun" -msgstr "Entra al Qun QQ" - -msgid "Input request here" -msgstr "Introduïu la sol·licitud aquí" - -#, c-format -msgid "Successfully joined Qun %s (%u)" -msgstr "S'ha entrat al Qun %s (%u)" - -msgid "Successfully joined Qun" -msgstr "S'ha entrat al Qun" - -#, c-format -msgid "Qun %u denied from joining" -msgstr "No se us ha permès entrar al Qun %u" - -msgid "QQ Qun Operation" -msgstr "Operació Qun QQ" - -msgid "Failed:" -msgstr "Ha fallat:" - -msgid "Join Qun, Unknown Reply" -msgstr "Resposta desconeguda en entrar al Qun" - -msgid "Quit Qun" -msgstr "Surt del Qun" - -msgid "" -"Note, if you are the creator, \n" -"this operation will eventually remove this Qun." -msgstr "" -"Nota, si en sou el creador, \n" -"aquesta operació suprimirà aquest Qun." - -msgid "Sorry, you are not our style" -msgstr "Em sap greu, no sou el meu tipus" - -msgid "Successfully changed Qun members" -msgstr "S'ha canviat els membres del Qun" - -msgid "Successfully changed Qun information" -msgstr "S'ha canviat la iformació del Qun correctament" - -msgid "You have successfully created a Qun" -msgstr "Heu creat un Qun" - -msgid "Would you like to set up detailed information now?" -msgstr "Voleu establir informació detallada ara?" - -msgid "Setup" -msgstr "Configuració" - -#, c-format -msgid "%u requested to join Qun %u for %s" -msgstr "%u ha sol·licitat unir-se al Qun %u per %s" - -#, c-format -msgid "%u request to join Qun %u" -msgstr "%u ha sol·licitat unir-se al Qun %u" - -#, c-format -msgid "Failed to join Qun %u, operated by admin %u" -msgstr "No s'ha pogut entrar al Qun %u, administrat per %u" - -#, c-format -msgid "Joining Qun %u is approved by admin %u for %s" -msgstr "L'administrador %2$u us ha permès unir-vos al Qun %1$u per %3$s" - -#, c-format -msgid "Removed buddy %u." -msgstr "S'ha suprimit l'amic %u." - -#, c-format -msgid "New buddy %u joined." -msgstr "El nou amic %u ha entrat." - -#, c-format -msgid "Unknown-%d" -msgstr "Desconegut-%d" - -msgid "Level" -msgstr "Nivell" - -msgid " VIP" -msgstr " VIP" - -msgid " TCP" -msgstr " TCP" - -msgid " FromMobile" -msgstr " FromMobile" - -msgid " BindMobile" -msgstr " BindMobile" - -msgid " Video" -msgstr " Vídeo" - -msgid " Zone" -msgstr " Zona" - -# Nota: només apareix si es defineix DEBUG -msgid "Flag" -msgstr "Bandera" - -# Nota: només apareix si es defineix DEBUG -msgid "Ver" -msgstr "Ver" - -msgid "Invalid name" -msgstr "QQ: El nom d'usuari no és vàlid" - -msgid "Select icon..." -msgstr "Selecciona una icona..." - -#, c-format -msgid "Login time: %d-%d-%d, %d:%d:%d
\n" -msgstr "Temps d'entrada: %d-%d-%d, %d:%d:%d
\n" - -#, c-format -msgid "Total Online Buddies: %d
\n" -msgstr "Amic en línia: %d
\n" - -#, c-format -msgid "Last Refresh: %d-%d-%d, %d:%d:%d
\n" -msgstr "Actualitzat per darrer cop: %d-%d-%d, %d:%d:%d
\n" - -#, c-format -msgid "Server: %s
\n" -msgstr "Servidor: %s
\n" - -#, c-format -msgid "Client Tag: %s
\n" -msgstr "Etiqueta del client: %s
\n" - -#, c-format -msgid "Connection Mode: %s
\n" -msgstr "Mode de connexió: %s
\n" - -#, c-format -msgid "My Internet IP: %s:%d
\n" -msgstr "La meva adreça IP: %s:%d
\n" - -#, c-format -msgid "Sent: %lu
\n" -msgstr "Enviats: %lu
\n" - -#, c-format -msgid "Resend: %lu
\n" -msgstr "Reenviats: %lu
\n" - -#, c-format -msgid "Lost: %lu
\n" -msgstr "Perduts: %lu
\n" - -#, c-format -msgid "Received: %lu
\n" -msgstr "Rebuts: %lu
\n" - -#, c-format -msgid "Received Duplicate: %lu
\n" -msgstr "Rebuts duplicats: %lu
\n" - -#, c-format -msgid "Time: %d-%d-%d, %d:%d:%d
\n" -msgstr "Temps: %d-%d-%d, %d:%d:%d
\n" - -#, c-format -msgid "IP: %s
\n" -msgstr "IP: %s
\n" - -msgid "Login Information" -msgstr "Informació de la connexió" - -msgid "

Original Author:
\n" -msgstr "

Autor original:
\n" - -msgid "

Code Contributors:
\n" -msgstr "

Col·laboradors del codi:
\n" - -msgid "

Lovely Patch Writers:
\n" -msgstr "

Encantadors apedaçadors (de codi):
\n" - -msgid "

Acknowledgement:
\n" -msgstr "

Reconeixement:
\n" - -msgid "

Scrupulous Testers:
\n" -msgstr "

Comprovadors del codi:
\n" - -msgid "and more, please let me know... thank you!))" -msgstr "i més, si us plau feu-m'ho saber... gràcies!!!))" - -# FIXME: ush... traducció lliure... -msgid "

And, all the boys in the backroom...
\n" -msgstr "

I tothom que ho ha fet possible...
\n" - -msgid "Feel free to join us! :)" -msgstr "No dubteu a col·laborar amb nosaltres! :)" - -#, c-format -msgid "About OpenQ %s" -msgstr "Quant a l'OpenQ %s" - -msgid "Change Icon" -msgstr "Canvia la icona" - -msgid "Change Password" -msgstr "Canvia la contrasenya" - -msgid "Account Information" -msgstr "Informació del compte" - -msgid "Update all QQ Quns" -msgstr "Actualitza tots els Quns QQ" - -msgid "About OpenQ" -msgstr "Quant a l'OpenQ" - -msgid "Modify Buddy Memo" -msgstr "Modifica el memo de l'amic" - -#. *< type -#. *< ui_requirement -#. *< flags -#. *< dependencies -#. *< priority -#. *< id -#. *< name -#. *< version -#. * summary -#. * description -msgid "QQ Protocol Plugin" -msgstr "Connector per al protocol QQ" - -msgid "Auto" -msgstr "Auto" - -msgid "Select Server" -msgstr "Seleccioneu un servidor" - -msgid "QQ2008" -msgstr "QQ2008" - -msgid "QQ2007" -msgstr "QQ2007" - -msgid "QQ2005" -msgstr "QQ2005" - -msgid "Connect by TCP" -msgstr "Connecta amb TCP" - -msgid "Show server notice" -msgstr "Mostra els avisos del servidor" - -msgid "Show server news" -msgstr "Mostra les notícies del servidor" - -msgid "Show chat room when msg comes" -msgstr "Mostra la sala de xat quan hi arribin missatges" - -# FIXME: keep alive -> permanència -msgid "Keep alive interval (seconds)" -msgstr "Interval de permanència (en segons)" - -msgid "Update interval (seconds)" -msgstr "Interval d'actualització (en segons)" - -msgid "Unable to decrypt server reply" -msgstr "No es pot desxifrar la resposta del servidor" - -#, c-format -msgid "Failed requesting token, 0x%02X" -msgstr "S'ha produït un error en sol·licitar el testimoni, 0x%02X" - -#, c-format -msgid "Invalid token len, %d" -msgstr "La longiud del testimoni no és vàlida, %d" - -#. extend redirect used in QQ2006 -msgid "Redirect_EX is not currently supported" -msgstr "Redirect_EX no està implementat" - -#. need activation -#. need activation -#. need activation -msgid "Activation required" -msgstr "Cal activació" - -#, c-format -msgid "Unknown reply code when logging in (0x%02X)" -msgstr "No s'ha reconegut el codi de resposta en entrar (0x%02X)" - -# FIXME: captcha -msgid "Requesting captcha" -msgstr "S'està sol·licitant un capcha" - -msgid "Checking captcha" -msgstr "S'està comprovant el captcha" - -msgid "Failed captcha verification" -msgstr "Ha fallat la verificació del captcha" - -msgid "Captcha Image" -msgstr "Imatge captcha" - -msgid "Enter code" -msgstr "Introduïu el codi" - -msgid "QQ Captcha Verification" -msgstr "Verificació del captcha QQ" - -msgid "Enter the text from the image" -msgstr "Introduïu el text de la imatge" - -#, c-format -msgid "Unknown reply when checking password (0x%02X)" -msgstr "" -"No s'ha reconegut el codi de resposta en comprovar la contrasenya (0x%02X)" - -#, c-format -msgid "" -"Unknown reply code when logging in (0x%02X):\n" -"%s" -msgstr "" -"No s'ha reconegut el codi de resposta en entrar (0x%02X):\n" -"%s" - -msgid "Socket error" -msgstr "Error del sòcol" - -msgid "Getting server" -msgstr "S'està obtenint el servidor" - -msgid "Requesting token" -msgstr "S'està sol·licitant un testimoni" - -msgid "Unable to resolve hostname" -msgstr "No s'ha pogut resoldre el nom de l'ordinador" - -msgid "Invalid server or port" -msgstr "El servidor o el port no són vàlids" - -msgid "Connecting to server" -msgstr "S'està connectant al servidor" - -msgid "QQ Error" -msgstr "Error del QQ" - -#, c-format -msgid "" -"Server News:\n" -"%s\n" -"%s\n" -"%s" -msgstr "" -"Notícies del servidor:\n" -"%s\n" -"%s\n" -"%s" - -#, c-format -msgid "%s:%s" -msgstr "%s:%s" - -#, c-format -msgid "From %s:" -msgstr "De %s:" - -#, c-format -msgid "" -"Server notice From %s: \n" -"%s" -msgstr "" -"Avís del servidor de %s: \n" -"%s" - -msgid "Unknown SERVER CMD" -msgstr "Ordre del servidor desconeguda" - -#, c-format -msgid "" -"Error reply of %s(0x%02X)\n" -"Room %u, reply 0x%02X" -msgstr "" -"Resposta d'error de %s(0x%02X)\n" -"Sala %u, resposta 0x%02X" - -msgid "QQ Qun Command" -msgstr "Ordre QQ Qun" - -msgid "Unable to decrypt login reply" -msgstr "No s'ha pogut desxifrar la resposta d'entrada" - -msgid "Unknown LOGIN CMD" -msgstr "Ordre d'entrada desconeguda" - -msgid "Unknown CLIENT CMD" -msgstr "Ordre de client desconeguda" - -#, c-format -msgid "%d has declined the file %s" -msgstr "%d ha refusat el fitxer %s" - -msgid "File Send" -msgstr "S'ha enviat el fitxer" - -#, c-format -msgid "%d cancelled the transfer of %s" -msgstr "%d ha cancel·lat la transferència de %s" - #, c-format msgid "Group Title: %s
" msgstr "Títol del grup: %s
" @@ -9654,6 +9027,9 @@ msgid "Unit" msgstr "Unitat" +msgid "Note" +msgstr "Nota" + msgid "Join Chat" msgstr "Entra a un xat" @@ -10302,6 +9678,9 @@ msgid "Unable to create listen socket" msgstr "No s'ha pogut crear el sòcol on escoltar" +msgid "Unable to resolve hostname" +msgstr "No s'ha pogut resoldre el nom de l'ordinador" + msgid "SIP usernames may not contain whitespaces or @ symbols" msgstr "Els noms d'usuari SIP no poden contenir espais en blanc ni @" @@ -10422,6 +9801,9 @@ msgid "Yahoo! system message for %s:" msgstr "Missatge del sistema de yahoo! per a %s:" +msgid "Authorization denied message:" +msgstr "Missatge de denegació de l'autorització:" + #, c-format msgid "" "%s has (retroactively) denied your request to add them to your list for the " @@ -11219,15 +10601,18 @@ msgid "No Proxy" msgstr "Sense servidor intermediari" -msgid "HTTP" -msgstr "HTTP" - msgid "SOCKS 4" msgstr "SOCKS 4" msgid "SOCKS 5" msgstr "SOCKS 5" +msgid "Tor/Privacy (SOCKS5)" +msgstr "Tor/Privadesa (SOCKS5)" + +msgid "HTTP" +msgstr "HTTP" + msgid "Use Environmental Settings" msgstr "Empra les opcions de l'entorn" @@ -11255,6 +10640,12 @@ msgid "Pa_ssword:" msgstr "_Contrasenya:" +msgid "Use _silence suppression" +msgstr "Empra la supressió del silenci" + +msgid "_Voice and Video" +msgstr "_Veu i vídeo" + msgid "Unable to save new account" msgstr "No s'ha pogut desar el compte nou" @@ -11303,9 +10694,20 @@ "d'amics." #, c-format +msgid "" +"%s%s%s%s wants to add you (%s) to his or her buddy " +"list%s%s" +msgstr "" +"%s%s%s%s us vol afegir (%s) a la seva llista d'amics" +"%s%s" + +#, c-format msgid "%s%s%s%s wants to add you (%s) to his or her buddy list%s%s" msgstr "L'usuari %s%s%s%s us vol afegir (%s) a la seva llista d'amics%s%s" +msgid "Send Instant Message" +msgstr "Envia un missatge instantani" + #. Buddy List msgid "Background Color" msgstr "Color de fons" @@ -11859,6 +11261,9 @@ msgid "(Optional) A_lias:" msgstr "(Opcional) À_lies:" +msgid "(Optional) _Invite message:" +msgstr "(Opcional) Missatge d'_invitació:" + msgid "Add buddy to _group:" msgstr "Afegeix l'amic al _grup:" @@ -13345,6 +12750,13 @@ msgstr "Avisos nous" # FIXME: Cancel·la? +#. Translators: Make sure you translate "Dismiss" differently than +#. "close"! This string is used in the "You have pounced" dialog +#. that appears when one of your Buddy Pounces is triggered. In +#. this context "Dismiss" means "I acknowledge that I've seen that +#. this pounce was triggered--remove it from this list." Translating +#. it as "Remove" is acceptable if you can't think of a more precise +#. word. msgid "Dismiss" msgstr "Rebutja" @@ -14479,6 +13891,9 @@ msgid "PubSub Leaf" msgstr "Fulla PubSub" +msgid "Other" +msgstr "Altres" + msgid "" "\n" "Description: " @@ -15343,6 +14758,21 @@ msgid "D_evice" msgstr "D_ispositiu" +msgid "DROP" +msgstr "DROP" + +msgid "Volume:" +msgstr "Volum:" + +msgid "Silence threshold:" +msgstr "Llindar per al sileici:" + +msgid "Input and Output Settings" +msgstr "Paràmetres d'entrada i sortida" + +msgid "Microphone Test" +msgstr "Test del micròfon" + #. *< magic #. *< major version #. *< minor version @@ -15355,9 +14785,6 @@ msgid "Voice/Video Settings" msgstr "Configuració del so/vídeo" -msgid "Voice and Video Settings" -msgstr "Configuració de la veu i el vídeo" - #. *< name #. *< version msgid "Configure your microphone and webcam." @@ -15635,6 +15062,668 @@ msgid "You do not have permission to uninstall this application." msgstr "No tens permís per desinstal.lar aquesta aplicació." +#~ msgid "Authorization Request Message:" +#~ msgstr "Missatge de petició d'autorització:" + +#~ msgid "Please authorize me!" +#~ msgstr "Autoritzeu-me, si us plau." + +#~ msgid "Your UID" +#~ msgstr "El vostre UID" + +#~ msgid "Hide my number" +#~ msgstr "Oculta el meu número" + +#~ msgid "Here you can update your MXit profile" +#~ msgstr "Aquí podeu actualitzar el vostre perfil MXit" + +#~ msgid "Aquarius" +#~ msgstr "Aquari" + +#~ msgid "Pisces" +#~ msgstr "Peixos" + +#~ msgid "Aries" +#~ msgstr "Àries" + +#~ msgid "Taurus" +#~ msgstr "Taure" + +#~ msgid "Gemini" +#~ msgstr "Bessons" + +#~ msgid "Cancer" +#~ msgstr "Cranc" + +#~ msgid "Leo" +#~ msgstr "Lleó" + +#~ msgid "Virgo" +#~ msgstr "Verge" + +#~ msgid "Libra" +#~ msgstr "Balança" + +#~ msgid "Scorpio" +#~ msgstr "Escorpió" + +#~ msgid "Sagittarius" +#~ msgstr "Sagitari" + +#~ msgid "Capricorn" +#~ msgstr "Capricorn" + +#~ msgid "Rat" +#~ msgstr "Rata" + +#~ msgid "Ox" +#~ msgstr "Bou" + +#~ msgid "Tiger" +#~ msgstr "Tigre" + +#~ msgid "Rabbit" +#~ msgstr "Conill" + +#~ msgid "Dragon" +#~ msgstr "Drac" + +#~ msgid "Snake" +#~ msgstr "Serp" + +#~ msgid "Horse" +#~ msgstr "Cavall" + +#~ msgid "Goat" +#~ msgstr "Ovella" + +#~ msgid "Monkey" +#~ msgstr "Mico" + +#~ msgid "Rooster" +#~ msgstr "Gall" + +#~ msgid "Dog" +#~ msgstr "Gos" + +#~ msgid "Pig" +#~ msgstr "Porc" + +#~ msgid "Visible" +#~ msgstr "Visible" + +#~ msgid "Friend Only" +#~ msgstr "Només amic" + +#~ msgid "Private" +#~ msgstr "Privat" + +#~ msgid "QQ Number" +#~ msgstr "Número QQ" + +#~ msgid "Country/Region" +#~ msgstr "País/Regió" + +#~ msgid "Province/State" +#~ msgstr "Província/Estat" + +#~ msgid "Zipcode" +#~ msgstr "Codi postal" + +#~ msgid "Phone Number" +#~ msgstr "Número de telèfon" + +#~ msgid "Authorize adding" +#~ msgstr "Autoritzar que us afegeixin" + +#~ msgid "Cellphone Number" +#~ msgstr "Número de mòbil" + +#~ msgid "Personal Introduction" +#~ msgstr "Introducció personal" + +#~ msgid "City/Area" +#~ msgstr "Ciutat/Àrea" + +#~ msgid "Publish Mobile" +#~ msgstr "Publica el mòbil" + +#~ msgid "Publish Contact" +#~ msgstr "Publica el contacte" + +#~ msgid "College" +#~ msgstr "Col·legi" + +#~ msgid "Horoscope" +#~ msgstr "Horòscop" + +#~ msgid "Zodiac" +#~ msgstr "Zodíac" + +#~ msgid "Blood" +#~ msgstr "Sang" + +#~ msgid "True" +#~ msgstr "Cert" + +#~ msgid "False" +#~ msgstr "Fals" + +#~ msgid "Modify Contact" +#~ msgstr "Modifica el contacte" + +#~ msgid "Modify Address" +#~ msgstr "Modifica l'adreça" + +#~ msgid "Modify Extended Information" +#~ msgstr "Modifica la informació estesa" + +#~ msgid "Modify Information" +#~ msgstr "Modifica la informació" + +#~ msgid "Update" +#~ msgstr "Actualitza" + +#~ msgid "Could not change buddy information." +#~ msgstr "No s'ha pogut canviar la informació l'amic." + +# FIXME: "memo", el qq té una terminologia molt peculiar +#~ msgid "Buddy Memo" +#~ msgstr "Memo de l'amic" + +#~ msgid "Change his/her memo as you like" +#~ msgstr "Canvieu-ne el memo" + +#~ msgid "_Modify" +#~ msgstr "_Modifica" + +#~ msgid "Memo Modify" +#~ msgstr "Modifica el memo" + +#~ msgid "Server says:" +#~ msgstr "El servidor diu:" + +#~ msgid "Your request was accepted." +#~ msgstr "S'ha acceptat la vostra sol·licitud." + +#~ msgid "Your request was rejected." +#~ msgstr "S'ha rebutjat la vostra sol·licitud." + +#~ msgid "%u requires verification: %s" +#~ msgstr "%u requereix verificació: %s" + +# Nota: títol de finestra +#~ msgid "Add buddy question" +#~ msgstr "Afegir una pregunta" + +#~ msgid "Enter answer here" +#~ msgstr "Introduïu la resposta aquí" + +#~ msgid "Send" +#~ msgstr "Envia" + +#~ msgid "Invalid answer." +#~ msgstr "La resposta no és vàlida" + +#~ msgid "Sorry, you're not my style." +#~ msgstr "Em sap greu, no sou el meu tipus." + +#~ msgid "%u needs authorization" +#~ msgstr "Cal autorització per a %u" + +# Nota: títol de finestra (josep) +#~ msgid "Add buddy authorize" +#~ msgstr "Autorització per a afegir un amic" + +#~ msgid "Enter request here" +#~ msgstr "Introduïu la sol·licitud aquí" + +#~ msgid "Would you be my friend?" +#~ msgstr "Voleu ser el meu amic?" + +#~ msgid "QQ Buddy" +#~ msgstr "Amic QQ" + +#~ msgid "Add buddy" +#~ msgstr "Afegeix un amic" + +#~ msgid "Invalid QQ Number" +#~ msgstr "El nombre QQ no és vàlid" + +#~ msgid "Failed sending authorize" +#~ msgstr "No s'ha pogut enviar l'autorització" + +#~ msgid "Failed removing buddy %u" +#~ msgstr "No s'ha pogut suprimir l'amic %u" + +#~ msgid "Failed removing me from %d's buddy list" +#~ msgstr "No us heu pogut suprimir de la llista d'amics de %d" + +#~ msgid "No reason given" +#~ msgstr "No s'ha indicat cap motiu" + +#~ msgid "You have been added by %s" +#~ msgstr "%s us ha afegit" + +#~ msgid "Would you like to add him?" +#~ msgstr "Voleu afegir-lo?" + +#~ msgid "Rejected by %s" +#~ msgstr "Rebutjat per %s" + +#~ msgid "Message: %s" +#~ msgstr "Missatge: %s" + +#~ msgid "ID: " +#~ msgstr "Identificador: " + +#~ msgid "Group ID" +#~ msgstr "Identificador del Grup" + +#~ msgid "QQ Qun" +#~ msgstr "QQ Qun" + +#~ msgid "Please enter Qun number" +#~ msgstr "Introduïu el número Qun" + +#~ msgid "You can only search for permanent Qun\n" +#~ msgstr "Només podeu cercar Quns permanents\n" + +#~ msgid "(Invalid UTF-8 string)" +#~ msgstr "(No és una cadena UTF-8 vàlida)" + +#~ msgid "Not member" +#~ msgstr "No en sóc membre" + +#~ msgid "Member" +#~ msgstr "Membre" + +#~ msgid "Requesting" +#~ msgstr "Demanant" + +#~ msgid "Admin" +#~ msgstr "Administrador" + +# FIXME +#~ msgid "Room Title" +#~ msgstr "Nom de la sala" + +#~ msgid "Notice" +#~ msgstr "Avís" + +#~ msgid "Detail" +#~ msgstr "Detalls" + +#~ msgid "Creator" +#~ msgstr "Creador" + +#~ msgid "Category" +#~ msgstr "Categoria" + +#~ msgid "The Qun does not allow others to join" +#~ msgstr "Aquest Qun no permet que s'hi afegeixi ningú" + +#~ msgid "Join QQ Qun" +#~ msgstr "Entra al Qun QQ" + +#~ msgid "Input request here" +#~ msgstr "Introduïu la sol·licitud aquí" + +#~ msgid "Successfully joined Qun %s (%u)" +#~ msgstr "S'ha entrat al Qun %s (%u)" + +#~ msgid "Successfully joined Qun" +#~ msgstr "S'ha entrat al Qun" + +#~ msgid "Qun %u denied from joining" +#~ msgstr "No se us ha permès entrar al Qun %u" + +#~ msgid "QQ Qun Operation" +#~ msgstr "Operació Qun QQ" + +#~ msgid "Failed:" +#~ msgstr "Ha fallat:" + +#~ msgid "Join Qun, Unknown Reply" +#~ msgstr "Resposta desconeguda en entrar al Qun" + +#~ msgid "Quit Qun" +#~ msgstr "Surt del Qun" + +#~ msgid "" +#~ "Note, if you are the creator, \n" +#~ "this operation will eventually remove this Qun." +#~ msgstr "" +#~ "Nota, si en sou el creador, \n" +#~ "aquesta operació suprimirà aquest Qun." + +#~ msgid "Sorry, you are not our style" +#~ msgstr "Em sap greu, no sou el meu tipus" + +#~ msgid "Successfully changed Qun members" +#~ msgstr "S'ha canviat els membres del Qun" + +#~ msgid "Successfully changed Qun information" +#~ msgstr "S'ha canviat la iformació del Qun correctament" + +#~ msgid "You have successfully created a Qun" +#~ msgstr "Heu creat un Qun" + +#~ msgid "Would you like to set up detailed information now?" +#~ msgstr "Voleu establir informació detallada ara?" + +#~ msgid "Setup" +#~ msgstr "Configuració" + +#~ msgid "%u requested to join Qun %u for %s" +#~ msgstr "%u ha sol·licitat unir-se al Qun %u per %s" + +#~ msgid "%u request to join Qun %u" +#~ msgstr "%u ha sol·licitat unir-se al Qun %u" + +#~ msgid "Failed to join Qun %u, operated by admin %u" +#~ msgstr "No s'ha pogut entrar al Qun %u, administrat per %u" + +#~ msgid "Joining Qun %u is approved by admin %u for %s" +#~ msgstr "" +#~ "L'administrador %2$u us ha permès unir-vos al Qun %1$u per %3$s" + +#~ msgid "Removed buddy %u." +#~ msgstr "S'ha suprimit l'amic %u." + +#~ msgid "New buddy %u joined." +#~ msgstr "El nou amic %u ha entrat." + +#~ msgid "Unknown-%d" +#~ msgstr "Desconegut-%d" + +#~ msgid "Level" +#~ msgstr "Nivell" + +#~ msgid " VIP" +#~ msgstr " VIP" + +#~ msgid " TCP" +#~ msgstr " TCP" + +#~ msgid " FromMobile" +#~ msgstr " FromMobile" + +#~ msgid " BindMobile" +#~ msgstr " BindMobile" + +#~ msgid " Video" +#~ msgstr " Vídeo" + +#~ msgid " Zone" +#~ msgstr " Zona" + +# Nota: només apareix si es defineix DEBUG +#~ msgid "Flag" +#~ msgstr "Bandera" + +# Nota: només apareix si es defineix DEBUG +#~ msgid "Ver" +#~ msgstr "Ver" + +#~ msgid "Invalid name" +#~ msgstr "QQ: El nom d'usuari no és vàlid" + +#~ msgid "Select icon..." +#~ msgstr "Selecciona una icona..." + +#~ msgid "Login time: %d-%d-%d, %d:%d:%d
\n" +#~ msgstr "Temps d'entrada: %d-%d-%d, %d:%d:%d
\n" + +#~ msgid "Total Online Buddies: %d
\n" +#~ msgstr "Amic en línia: %d
\n" + +#~ msgid "Last Refresh: %d-%d-%d, %d:%d:%d
\n" +#~ msgstr "Actualitzat per darrer cop: %d-%d-%d, %d:%d:%d
\n" + +#~ msgid "Server: %s
\n" +#~ msgstr "Servidor: %s
\n" + +#~ msgid "Client Tag: %s
\n" +#~ msgstr "Etiqueta del client: %s
\n" + +#~ msgid "Connection Mode: %s
\n" +#~ msgstr "Mode de connexió: %s
\n" + +#~ msgid "My Internet IP: %s:%d
\n" +#~ msgstr "La meva adreça IP: %s:%d
\n" + +#~ msgid "Sent: %lu
\n" +#~ msgstr "Enviats: %lu
\n" + +#~ msgid "Resend: %lu
\n" +#~ msgstr "Reenviats: %lu
\n" + +#~ msgid "Lost: %lu
\n" +#~ msgstr "Perduts: %lu
\n" + +#~ msgid "Received: %lu
\n" +#~ msgstr "Rebuts: %lu
\n" + +#~ msgid "Received Duplicate: %lu
\n" +#~ msgstr "Rebuts duplicats: %lu
\n" + +#~ msgid "Time: %d-%d-%d, %d:%d:%d
\n" +#~ msgstr "Temps: %d-%d-%d, %d:%d:%d
\n" + +#~ msgid "IP: %s
\n" +#~ msgstr "IP: %s
\n" + +#~ msgid "Login Information" +#~ msgstr "Informació de la connexió" + +#~ msgid "

Original Author:
\n" +#~ msgstr "

Autor original:
\n" + +#~ msgid "

Code Contributors:
\n" +#~ msgstr "

Col·laboradors del codi:
\n" + +#~ msgid "

Lovely Patch Writers:
\n" +#~ msgstr "

Encantadors apedaçadors (de codi):
\n" + +#~ msgid "

Acknowledgement:
\n" +#~ msgstr "

Reconeixement:
\n" + +#~ msgid "

Scrupulous Testers:
\n" +#~ msgstr "

Comprovadors del codi:
\n" + +#~ msgid "and more, please let me know... thank you!))" +#~ msgstr "i més, si us plau feu-m'ho saber... gràcies!!!))" + +# FIXME: ush... traducció lliure... +#~ msgid "

And, all the boys in the backroom...
\n" +#~ msgstr "

I tothom que ho ha fet possible...
\n" + +#~ msgid "Feel free to join us! :)" +#~ msgstr "No dubteu a col·laborar amb nosaltres! :)" + +#~ msgid "About OpenQ %s" +#~ msgstr "Quant a l'OpenQ %s" + +#~ msgid "Change Password" +#~ msgstr "Canvia la contrasenya" + +#~ msgid "Account Information" +#~ msgstr "Informació del compte" + +#~ msgid "Update all QQ Quns" +#~ msgstr "Actualitza tots els Quns QQ" + +#~ msgid "About OpenQ" +#~ msgstr "Quant a l'OpenQ" + +#~ msgid "Modify Buddy Memo" +#~ msgstr "Modifica el memo de l'amic" + +#~ msgid "QQ Protocol Plugin" +#~ msgstr "Connector per al protocol QQ" + +#~ msgid "Auto" +#~ msgstr "Auto" + +#~ msgid "Select Server" +#~ msgstr "Seleccioneu un servidor" + +#~ msgid "QQ2008" +#~ msgstr "QQ2008" + +#~ msgid "QQ2007" +#~ msgstr "QQ2007" + +#~ msgid "QQ2005" +#~ msgstr "QQ2005" + +#~ msgid "Connect by TCP" +#~ msgstr "Connecta amb TCP" + +#~ msgid "Show server notice" +#~ msgstr "Mostra els avisos del servidor" + +#~ msgid "Show server news" +#~ msgstr "Mostra les notícies del servidor" + +#~ msgid "Show chat room when msg comes" +#~ msgstr "Mostra la sala de xat quan hi arribin missatges" + +# FIXME: keep alive -> permanència +#~ msgid "Keep alive interval (seconds)" +#~ msgstr "Interval de permanència (en segons)" + +#~ msgid "Update interval (seconds)" +#~ msgstr "Interval d'actualització (en segons)" + +#~ msgid "Unable to decrypt server reply" +#~ msgstr "No es pot desxifrar la resposta del servidor" + +#~ msgid "Failed requesting token, 0x%02X" +#~ msgstr "S'ha produït un error en sol·licitar el testimoni, 0x%02X" + +#~ msgid "Invalid token len, %d" +#~ msgstr "La longiud del testimoni no és vàlida, %d" + +#~ msgid "Redirect_EX is not currently supported" +#~ msgstr "Redirect_EX no està implementat" + +#~ msgid "Activation required" +#~ msgstr "Cal activació" + +#~ msgid "Unknown reply code when logging in (0x%02X)" +#~ msgstr "No s'ha reconegut el codi de resposta en entrar (0x%02X)" + +# FIXME: captcha +#~ msgid "Requesting captcha" +#~ msgstr "S'està sol·licitant un capcha" + +#~ msgid "Checking captcha" +#~ msgstr "S'està comprovant el captcha" + +#~ msgid "Failed captcha verification" +#~ msgstr "Ha fallat la verificació del captcha" + +#~ msgid "Captcha Image" +#~ msgstr "Imatge captcha" + +#~ msgid "Enter code" +#~ msgstr "Introduïu el codi" + +#~ msgid "QQ Captcha Verification" +#~ msgstr "Verificació del captcha QQ" + +#~ msgid "Enter the text from the image" +#~ msgstr "Introduïu el text de la imatge" + +#~ msgid "Unknown reply when checking password (0x%02X)" +#~ msgstr "" +#~ "No s'ha reconegut el codi de resposta en comprovar la contrasenya (0x%02X)" + +#~ msgid "" +#~ "Unknown reply code when logging in (0x%02X):\n" +#~ "%s" +#~ msgstr "" +#~ "No s'ha reconegut el codi de resposta en entrar (0x%02X):\n" +#~ "%s" + +#~ msgid "Socket error" +#~ msgstr "Error del sòcol" + +#~ msgid "Getting server" +#~ msgstr "S'està obtenint el servidor" + +#~ msgid "Requesting token" +#~ msgstr "S'està sol·licitant un testimoni" + +#~ msgid "Invalid server or port" +#~ msgstr "El servidor o el port no són vàlids" + +#~ msgid "Connecting to server" +#~ msgstr "S'està connectant al servidor" + +#~ msgid "QQ Error" +#~ msgstr "Error del QQ" + +#~ msgid "" +#~ "Server News:\n" +#~ "%s\n" +#~ "%s\n" +#~ "%s" +#~ msgstr "" +#~ "Notícies del servidor:\n" +#~ "%s\n" +#~ "%s\n" +#~ "%s" + +#~ msgid "%s:%s" +#~ msgstr "%s:%s" + +#~ msgid "From %s:" +#~ msgstr "De %s:" + +#~ msgid "" +#~ "Server notice From %s: \n" +#~ "%s" +#~ msgstr "" +#~ "Avís del servidor de %s: \n" +#~ "%s" + +#~ msgid "Unknown SERVER CMD" +#~ msgstr "Ordre del servidor desconeguda" + +#~ msgid "" +#~ "Error reply of %s(0x%02X)\n" +#~ "Room %u, reply 0x%02X" +#~ msgstr "" +#~ "Resposta d'error de %s(0x%02X)\n" +#~ "Sala %u, resposta 0x%02X" + +#~ msgid "QQ Qun Command" +#~ msgstr "Ordre QQ Qun" + +#~ msgid "Unable to decrypt login reply" +#~ msgstr "No s'ha pogut desxifrar la resposta d'entrada" + +#~ msgid "Unknown LOGIN CMD" +#~ msgstr "Ordre d'entrada desconeguda" + +#~ msgid "Unknown CLIENT CMD" +#~ msgstr "Ordre de client desconeguda" + +#~ msgid "%d has declined the file %s" +#~ msgstr "%d ha refusat el fitxer %s" + +#~ msgid "File Send" +#~ msgstr "S'ha enviat el fitxer" + +#~ msgid "%d cancelled the transfer of %s" +#~ msgstr "%d ha cancel·lat la transferència de %s" + +#~ msgid "Voice and Video Settings" +#~ msgstr "Configuració de la veu i el vídeo" + #~ msgid "Automatically reject from users not in buddy list" #~ msgstr "" #~ "Rebutja automàticament dels usuaris que no estiguin a la llista d'amics" @@ -15720,9 +15809,6 @@ #~ msgid "How do you feel right now?" #~ msgstr "Com us trobeu ara mateix?" -#~ msgid "Change Mood..." -#~ msgstr "Canvia l'estat d'ànim..." - #~ msgid "Orientation" #~ msgstr "Orientació" @@ -15895,9 +15981,6 @@ #~ msgid "Auto-away" #~ msgstr "Auto-absència" -#~ msgid "Change _status to:" -#~ msgstr "Canvia l'_estat a:" - #~ msgid "Send instant messages over multiple protocols" #~ msgstr "Envieu missatges instantanis en múltiples protocols" @@ -16338,9 +16421,6 @@ #~ msgid "Please provide a shortcut to associate with the smiley." #~ msgstr "Especifiqueu una drecera associada a l'emoticona." -#~ msgid "Please select an image for the smiley." -#~ msgstr "Seleccioneu una imatge per a l'emoticona." - #~ msgid "Activate which ID?" #~ msgstr "Quin ID voleu activar?" @@ -16362,9 +16442,6 @@ #~ msgid "Widget Sizes" #~ msgstr "Mides del giny" -#~ msgid "Invite message" -#~ msgstr "Missatge d'invitació" - #~ msgid "" #~ "Please enter the name of the user you wish to invite,\n" #~ "along with an optional invite message." diff -r ea4bb5fe1fdc -r 0d4702446530 po/de.po --- a/po/de.po Thu May 05 03:40:29 2011 +0000 +++ b/po/de.po Mon May 09 04:26:46 2011 +0000 @@ -11,9 +11,9 @@ msgstr "" "Project-Id-Version: de\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2011-03-06 12:25+0100\n" -"PO-Revision-Date: 2011-03-06 12:25+0100\n" -"Last-Translator: Jochen Kemnade \n" +"POT-Creation-Date: 2011-05-08 00:19+0200\n" +"PO-Revision-Date: 2011-05-08 00:17+0200\n" +"Last-Translator: Björn Voigt \n" "Language-Team: German \n" "Language: de\n" "MIME-Version: 1.0\n" @@ -219,6 +219,9 @@ msgid "Alias (optional)" msgstr "Alias (optional)" +msgid "Invite message (optional)" +msgstr "Einladungsnachricht (optional)" + msgid "Add in group" msgstr "Zu Gruppe hinzufügen" @@ -1954,6 +1957,9 @@ msgid "Unknown reason" msgstr "Unbekannter Grund" +msgid "Aborting DNS lookup in Tor Proxy mode." +msgstr "DNS-Anfrage im Tor-Proxy-Modus abgebrochen" + #, c-format msgid "" "Error reading %s: \n" @@ -3208,6 +3214,21 @@ msgid "Change Gadu-Gadu Password" msgstr "Gadu-Gadu Passwort ändern" +msgid "Show status to:" +msgstr "Zeige Status:" + +msgid "All people" +msgstr "Allen Leuten" + +msgid "Only buddies" +msgstr "Nur Buddys" + +msgid "Change status broadcasting" +msgstr "Statusveröffentlichung ändern" + +msgid "Please, select who can see your status" +msgstr "Bitte wählen Sie, wer Ihren Status sehen darf" + #, c-format msgid "Select a chat for buddy: %s" msgstr "Wählen Sie einen Chat für den Benutzer: %s" @@ -3351,6 +3372,19 @@ msgid "GG server" msgstr "GG-Server" +msgid "Don't use encryption" +msgstr "Keine Verschlüsselung benutzen" + +msgid "Use encryption if available" +msgstr "Verschlüsselung benutzen, wenn verfügbar" + +#. TODO +msgid "Require encryption" +msgstr "Verschlüsselung fordern" + +msgid "Connection security" +msgstr "Verbindungssicherheit" + #, c-format msgid "Unknown command: %s" msgstr "Unbekanntes Kommando: %s" @@ -3386,7 +3420,6 @@ #. * buffer that stores what is "being sent" until the #. * PurpleHTTPConnection reports it is fully sent. #. -#. TODO: what to do here - do we really have to disconnect? #. TODO: do we really want to disconnect on a failure to write? #, c-format msgid "Lost connection with server: %s" @@ -3642,6 +3675,9 @@ msgid "action <action to perform>: Perform an action." msgstr "action <Aktion>: Führe eine Aktion durch." +msgid "authserv: Send a command to authserv" +msgstr "authserv: Sendet ein Kommando zum Authserv" + msgid "" "away [message]: Set an away message, or use no message to return from being " "away." @@ -4782,18 +4818,9 @@ msgid "Domain" msgstr "Domain" -msgid "Require encryption" -msgstr "Verschlüsselung fordern" - -msgid "Use encryption if available" -msgstr "Verschlüsselung benutzen, wenn verfügbar" - msgid "Use old-style SSL" msgstr "Alte SSL-Methode verwenden" -msgid "Connection security" -msgstr "Verbindungssicherheit" - msgid "Allow plaintext auth over unencrypted streams" msgstr "Erlaube Klartext-Authentifikation über einen unverschlüsselten Kanal" @@ -4905,6 +4932,7 @@ "Kann die Datei nicht an %s senden, da der Client des Benutzers keine " "Dateiübertragung unterstützt" +#. not success msgid "File Send Failed" msgstr "Senden der Datei gescheitert" @@ -5632,18 +5660,6 @@ msgid "Unable to Add" msgstr "Kann nicht hinzufügen" -msgid "Authorization Request Message:" -msgstr "Autorisierungsanfrage:" - -msgid "Please authorize me!" -msgstr "Bitte autorisiere mich!" - -#. * -#. * A wrapper for purple_request_action() that uses @c OK and @c Cancel buttons. -#. -msgid "_OK" -msgstr "_OK" - msgid "Error retrieving profile" msgstr "Fehler beim Empfangen des Profils" @@ -5856,6 +5872,11 @@ msgid "Mobile message was not sent because it was too long." msgstr "Mobile Nachricht wurde nicht gesendet, da sie zu lang war." +msgid "Mobile message was not sent because an unknown error occurred." +msgstr "" +"Mobile Nachricht konnte nicht gesendet werden, da ein unbekannter Fehler " +"aufgetreten ist." + #, c-format msgid "" "The MSN server will shut down for maintenance in %d minute. You will " @@ -6037,18 +6058,6 @@ msgid "The username specified is invalid." msgstr "Der angegebene Benutzername ist ungültig." -msgid "The PIN you entered is invalid." -msgstr "Der eingegebene PIN ist ungültig." - -msgid "The PIN you entered has an invalid length [4-10]." -msgstr "Die eingegebene PIN hat eine ungültige Länge [4-10]." - -msgid "The PIN is invalid. It should only consist of digits [0-9]." -msgstr "Die PIN ist ungültig. Sie sollte nur aus Ziffern [0-9] bestehen." - -msgid "The two PINs you entered do not match." -msgstr "Die beiden PINs, die Sie eingegeben haben, stimmen nicht überein." - msgid "The Display Name you entered is invalid." msgstr "Der eingegebene Anzeigename ist ungültig." @@ -6072,35 +6081,65 @@ "Ihre Profil-Informationen wurden noch nicht abgerufen. Bitte versuchen Sie " "es später noch einmal." -msgid "Your UID" -msgstr "Ihre UID" +#. display name +#. nick name (required) +msgid "Display Name" +msgstr "Anzeigename" + +#. about me +msgid "About Me" +msgstr "Über mich" + +#. where I live +msgid "Where I Live" +msgstr "Wo ich wohne" + +#. mobile number +msgid "Mobile Number" +msgstr "Handynummer" + +#. is searchable +msgid "Can be searched" +msgstr "Kann gesucht werden" + +#. is suggestable +msgid "Can be suggested" +msgstr "Kann vorgeschlagen werden" + +msgid "Update your MXit Profile" +msgstr "Aktualisieren Sie Ihr MXit-Profil" + +msgid "The PIN you entered is invalid." +msgstr "Die eingegebene PIN ist ungültig." + +msgid "The PIN you entered has an invalid length [4-10]." +msgstr "Die eingegebene PIN hat eine ungültige Länge [4-10]." + +msgid "The PIN is invalid. It should only consist of digits [0-9]." +msgstr "Die PIN ist ungültig. Sie sollte nur aus Ziffern [0-9] bestehen." + +msgid "The two PINs you entered do not match." +msgstr "Die beiden PINs, die Sie eingegeben haben, stimmen nicht überein." + +#. show error to user +msgid "PIN Update Error" +msgstr "PIN-Aktualisierungsfehler" #. pin #. pin (required) msgid "PIN" msgstr "PIN" +#. verify pin msgid "Verify PIN" msgstr "PIN bestätigen" -#. display name -#. nick name (required) -msgid "Display Name" -msgstr "Anzeigename" - -#. hidden -msgid "Hide my number" -msgstr "Meine Nummer verstecken" - -#. mobile number -msgid "Mobile Number" -msgstr "Handynummer" - -msgid "Update your Profile" -msgstr "Aktualisieren Sie Ihr Profil" - -msgid "Here you can update your MXit profile" -msgstr "Hier können Sie Ihr MXit-Profil aktualisieren" +#. (reference: "libpurple/request.h") +msgid "Change PIN" +msgstr "PIN ändern" + +msgid "Change MXit PIN" +msgstr "MXit-PIN ändern" msgid "View Splash" msgstr "Startbildschirm anschauen" @@ -6111,10 +6150,34 @@ msgid "About" msgstr "Info" +msgid "Search for user" +msgstr "Suche nach einem Benutzer" + +msgid "Search for a MXit contact" +msgstr "Suche nach einem MXit-Kontakt" + +msgid "Type search information" +msgstr "Eingabe der Benutzer-Information" + +msgid "_Search" +msgstr "_Suchen" + #. display / change profile msgid "Change Profile..." msgstr "Profil ändern..." +#. change PIN +msgid "Change PIN..." +msgstr "PIN ändern..." + +#. suggested friends +msgid "Suggested friends..." +msgstr "Vorgeschlagene Freunde..." + +#. search for contacts +msgid "Search for contacts..." +msgstr "Suche nach Kontakten..." + #. display splash-screen msgid "View Splash..." msgstr "Startbildschirm anzeigen..." @@ -6227,13 +6290,12 @@ msgid "Retrieving User Information..." msgstr "Abrufen der Benutzerinformationen..." -#. you were kicked +msgid "was kicked" +msgstr "wurde hinausgeworfen" + msgid "You have been kicked from this MultiMX." msgstr "Sie wurden von MultiMX hinausgeworfen." -msgid "was kicked" -msgstr "wurde hinausgeworfen" - msgid "_Room Name:" msgstr "_Raumname:" @@ -6281,6 +6343,31 @@ msgid "Last Online" msgstr "Zuletzt online" +msgid "Invite Message" +msgstr "Einladungsnachricht" + +msgid "No results" +msgstr "Keine Ergebnisse" + +msgid "No contacts found." +msgstr "Keine Kontakte gefunden." + +#. define columns +msgid "UserId" +msgstr "Benutzer-Id" + +msgid "Where I live" +msgstr "Wo ich wohne" + +#, c-format +msgid "You have %i suggested friends." +msgstr "Sie haben %i vorgeschlagene(n) Freund(e)." + +#, c-format +msgid "We found %i contacts that match your search." +msgstr "" +"Wir fanden %i Kontakt(e), die Ihrer Suchanfrage entspricht/entsprechen." + #. we must have lost the connection, so terminate it so that we can reconnect msgid "We have lost the connection to MXit. Please reconnect." msgstr "" @@ -7035,6 +7122,12 @@ msgid "Authorization Denied Message:" msgstr "Nachricht für die Ablehnung der Autorisierung:" +#. * +#. * A wrapper for purple_request_action() that uses @c OK and @c Cancel buttons. +#. +msgid "_OK" +msgstr "_OK" + #, c-format msgid "Received unexpected response from %s: %s" msgstr "Unerwartete Antwort von %s erhalten: %s" @@ -7395,7 +7488,6 @@ msgstr "Autorisierung empfangen" #. Unregistered username -#. uid is not exist #. the username does not exist msgid "Username does not exist" msgstr "Benutzername existiert nicht" @@ -7890,9 +7982,6 @@ msgid "Type the email address of the buddy you are searching for." msgstr "Geben Sie die E-Mail-Adresse des Buddys ein, nach dem Sie suchen." -msgid "_Search" -msgstr "_Suchen" - msgid "Set User Info (web)..." msgstr "Benutzer-Info (Web) setzen..." @@ -7929,9 +8018,6 @@ msgid "Search for Buddy by Email Address..." msgstr "Suche Buddys nach E-Mail-Adresse..." -msgid "Don't use encryption" -msgstr "Keine Verschlüsselung benutzen" - msgid "Use clientLogin" msgstr "clientLogin benutzen" @@ -8206,722 +8292,6 @@ msgid "These buddies will always see you as offline" msgstr "Für diese Buddys werden Sie immer als offline angezeigt" -msgid "Aquarius" -msgstr "Wassermann" - -msgid "Pisces" -msgstr "Fische" - -msgid "Aries" -msgstr "Widder" - -msgid "Taurus" -msgstr "Stier" - -msgid "Gemini" -msgstr "Zwillinge" - -msgid "Cancer" -msgstr "Krebs" - -msgid "Leo" -msgstr "Löwe" - -msgid "Virgo" -msgstr "Jungfrau" - -msgid "Libra" -msgstr "Waage" - -msgid "Scorpio" -msgstr "Skorpion" - -msgid "Sagittarius" -msgstr "Schütze" - -msgid "Capricorn" -msgstr "Steinbock" - -msgid "Rat" -msgstr "Ratte" - -msgid "Ox" -msgstr "Ochse" - -msgid "Tiger" -msgstr "Tiger" - -msgid "Rabbit" -msgstr "Kaninchen" - -msgid "Dragon" -msgstr "Drache" - -msgid "Snake" -msgstr "Schlange" - -msgid "Horse" -msgstr "Pferd" - -msgid "Goat" -msgstr "Gans" - -msgid "Monkey" -msgstr "Affe" - -msgid "Rooster" -msgstr "Hahn" - -msgid "Dog" -msgstr "Hund" - -msgid "Pig" -msgstr "Schwein" - -msgid "Other" -msgstr "Andere" - -msgid "Visible" -msgstr "Sichtbar" - -msgid "Friend Only" -msgstr "Nur Freund" - -msgid "Private" -msgstr "Privat" - -msgid "QQ Number" -msgstr "QQ-Nummer" - -msgid "Country/Region" -msgstr "Land/Region" - -msgid "Province/State" -msgstr "Provinz/Staat" - -msgid "Zipcode" -msgstr "PLZ" - -msgid "Phone Number" -msgstr "Telefonnummer" - -msgid "Authorize adding" -msgstr "Hinzufügen autorisieren" - -msgid "Cellphone Number" -msgstr "Handy-Telefonnummer" - -msgid "Personal Introduction" -msgstr "Persönliche Vorstellung" - -msgid "City/Area" -msgstr "Stadt/Gegend" - -msgid "Publish Mobile" -msgstr "Handy veröffentlichen" - -msgid "Publish Contact" -msgstr "Kontakt veröffentlichen" - -msgid "College" -msgstr "College" - -msgid "Horoscope" -msgstr "Horoskop" - -msgid "Zodiac" -msgstr "Sternzeichen" - -msgid "Blood" -msgstr "Blutgruppe" - -msgid "True" -msgstr "Wahr" - -msgid "False" -msgstr "Falsch" - -msgid "Modify Contact" -msgstr "Kontakt bearbeiten" - -msgid "Modify Address" -msgstr "Adresse bearbeiten" - -msgid "Modify Extended Information" -msgstr "Erweiterte Informationen bearbeiten" - -msgid "Modify Information" -msgstr "Informationen bearbeiten" - -msgid "Update" -msgstr "Aktualisieren" - -msgid "Could not change buddy information." -msgstr "Konnte Buddy-Informationen nicht bearbeiten." - -msgid "Note" -msgstr "Bemerkung" - -#. callback -msgid "Buddy Memo" -msgstr "Buddy-Notiz" - -msgid "Change his/her memo as you like" -msgstr "Ändern Sie seine/ihre Notiz wie Sie möchten" - -msgid "_Modify" -msgstr "_Bearbeiten" - -msgid "Memo Modify" -msgstr "Memo bearbeiten" - -msgid "Server says:" -msgstr "Server meldet:" - -msgid "Your request was accepted." -msgstr "Ihre Anfrage wurde akzeptiert." - -msgid "Your request was rejected." -msgstr "Ihre Anfrage wurde abgelehnt." - -#, c-format -msgid "%u requires verification: %s" -msgstr "%u erfordert Überprüfung: %s" - -msgid "Add buddy question" -msgstr "Buddy-Frage hinzufügen" - -msgid "Enter answer here" -msgstr "Antwort hier eingeben" - -msgid "Send" -msgstr "Senden" - -msgid "Invalid answer." -msgstr "Ungültige Antwort." - -msgid "Authorization denied message:" -msgstr "Nachricht für die Ablehnung der Autorisierung:" - -msgid "Sorry, you're not my style." -msgstr "Tut mir Leid, du bist nicht mein Typ." - -#, c-format -msgid "%u needs authorization" -msgstr "%u benötigt Autorisierung" - -msgid "Add buddy authorize" -msgstr "Buddy-Autorisierung hinzufügen" - -msgid "Enter request here" -msgstr "Anfrage hier eingeben" - -msgid "Would you be my friend?" -msgstr "Möchten Sie mein Freund sein?" - -msgid "QQ Buddy" -msgstr "QQ-Buddy" - -msgid "Add buddy" -msgstr "Buddy hinzufügen" - -msgid "Invalid QQ Number" -msgstr "Ungültige QQ-Nummer" - -msgid "Failed sending authorize" -msgstr "Senden der Autorisierung fehlgeschlagen" - -#, c-format -msgid "Failed removing buddy %u" -msgstr "Kontakt %u konnte nicht entfernt werden" - -#, c-format -msgid "Failed removing me from %d's buddy list" -msgstr "Entfernen von %ds Buddy-Liste fehlgeschlagen" - -msgid "No reason given" -msgstr "Kein Grund angegeben" - -#. only need to get value -#, c-format -msgid "You have been added by %s" -msgstr "Sie wurden von %s hinzugefügt" - -msgid "Would you like to add him?" -msgstr "Möchten Sie ihn hinzufügen?" - -#, c-format -msgid "Rejected by %s" -msgstr "Abgelehnt von %s" - -#, c-format -msgid "Message: %s" -msgstr "Nachricht: %s" - -msgid "ID: " -msgstr "ID: " - -msgid "Group ID" -msgstr "Gruppen-ID" - -msgid "QQ Qun" -msgstr "QQ-Qun" - -msgid "Please enter Qun number" -msgstr "Bitte geben Sie die Qun-Nummer ein" - -msgid "You can only search for permanent Qun\n" -msgstr "Sie können nur nach permanenten Qun suchen\n" - -msgid "(Invalid UTF-8 string)" -msgstr "(Ungültige UTF8-Zeichenkette)" - -msgid "Not member" -msgstr "Kein Mitglied" - -msgid "Member" -msgstr "Mitglied" - -msgid "Requesting" -msgstr "Frage an" - -msgid "Admin" -msgstr "Admin" - -#. XXX: Should this be "Topic"? -msgid "Room Title" -msgstr "Raumtitel" - -msgid "Notice" -msgstr "Bemerkung" - -msgid "Detail" -msgstr "Detail" - -msgid "Creator" -msgstr "Ersteller" - -msgid "About me" -msgstr "Über mich" - -msgid "Category" -msgstr "Kategorie" - -msgid "The Qun does not allow others to join" -msgstr "Diesen Qun können andere nicht beitreten" - -msgid "Join QQ Qun" -msgstr "QQ-Qun betreten" - -msgid "Input request here" -msgstr "Anfrage hier eingeben" - -#, c-format -msgid "Successfully joined Qun %s (%u)" -msgstr "Qun %s (%u) erfolgreich betreten" - -msgid "Successfully joined Qun" -msgstr "Qun erfolgreich betreten" - -#, c-format -msgid "Qun %u denied from joining" -msgstr "Qun %u hat Ihren Beitritt abgelehnt" - -msgid "QQ Qun Operation" -msgstr "QQ-Qun-Operation" - -msgid "Failed:" -msgstr "Gescheitert:" - -msgid "Join Qun, Unknown Reply" -msgstr "Qun-Beitritt, Unbekannte Antwort" - -msgid "Quit Qun" -msgstr "Qun verlassen" - -msgid "" -"Note, if you are the creator, \n" -"this operation will eventually remove this Qun." -msgstr "" -"Beachten Sie, dass diese Operation den Qun entfernen könnte, \n" -"wenn Sie der Ersteller sind." - -msgid "Sorry, you are not our style" -msgstr "Tut mir Leid, du bist nicht unser Typ" - -msgid "Successfully changed Qun members" -msgstr "Qun-Mitglieder erfolgreich geändert" - -msgid "Successfully changed Qun information" -msgstr "Qun-Informationen erfolgreich bearbeitet" - -msgid "You have successfully created a Qun" -msgstr "Sie haben einen Qun angelegt" - -msgid "Would you like to set up detailed information now?" -msgstr "Möchten Sie jetzt Detail-Informationen einstellen?" - -msgid "Setup" -msgstr "Setup" - -#, c-format -msgid "%u requested to join Qun %u for %s" -msgstr "%u möchte dem Qun %u wegen %s beitreten" - -#, c-format -msgid "%u request to join Qun %u" -msgstr "%u möchte dem Qun %u beitreten" - -#, c-format -msgid "Failed to join Qun %u, operated by admin %u" -msgstr "Dem Qun %u, moderiert von admin %u, konnte nicht beigetreten werden" - -#, c-format -msgid "Joining Qun %u is approved by admin %u for %s" -msgstr "" -"Das Betreten des Qun %u wurde vom Admin bestätigt wegen by admin %u for " -"%s" - -#, c-format -msgid "Removed buddy %u." -msgstr "Buddy %u entfernt" - -#, c-format -msgid "New buddy %u joined." -msgstr "Neuer Buddy %u ist beigetreten." - -#, c-format -msgid "Unknown-%d" -msgstr "Unbekannt-%d" - -msgid "Level" -msgstr "Stufe" - -msgid " VIP" -msgstr " VIP" - -msgid " TCP" -msgstr " TCP" - -msgid " FromMobile" -msgstr " FromMobile" - -msgid " BindMobile" -msgstr " BindMobile" - -msgid " Video" -msgstr " Video" - -msgid " Zone" -msgstr " Zone" - -msgid "Flag" -msgstr "Flagge" - -msgid "Ver" -msgstr "Ver" - -msgid "Invalid name" -msgstr "QQ: Ungültiger Name" - -msgid "Select icon..." -msgstr "Icon wählen..." - -#, c-format -msgid "Login time: %d-%d-%d, %d:%d:%d
\n" -msgstr "Anmeldezeit: %d-%d-%d, %d:%d:%d
\n" - -#, c-format -msgid "Total Online Buddies: %d
\n" -msgstr "Insgesamt online: %d
\n" - -#, c-format -msgid "Last Refresh: %d-%d-%d, %d:%d:%d
\n" -msgstr "Letzte Aktualisierung: %d-%d-%d, %d:%d:%d
\n" - -#, c-format -msgid "Server: %s
\n" -msgstr "Server: %s
\n" - -#, c-format -msgid "Client Tag: %s
\n" -msgstr "Marke des Clients: %s
\n" - -#, c-format -msgid "Connection Mode: %s
\n" -msgstr "Verbindungsmodus: %s
\n" - -#, c-format -msgid "My Internet IP: %s:%d
\n" -msgstr "Meine Internet-IP: %s:%d
\n" - -#, c-format -msgid "Sent: %lu
\n" -msgstr "Gesendet: %lu
\n" - -#, c-format -msgid "Resend: %lu
\n" -msgstr "Erneut senden: %lu
\n" - -#, c-format -msgid "Lost: %lu
\n" -msgstr "Verloren: %lu
\n" - -#, c-format -msgid "Received: %lu
\n" -msgstr "Empfangen: %lu
\n" - -#, c-format -msgid "Received Duplicate: %lu
\n" -msgstr "Duplikat empfangen: %lu
\n" - -#, c-format -msgid "Time: %d-%d-%d, %d:%d:%d
\n" -msgstr "Zeit: %d-%d-%d, %d:%d:%d
\n" - -#, c-format -msgid "IP: %s
\n" -msgstr "IP: %s
\n" - -msgid "Login Information" -msgstr "Login-Informationen" - -msgid "

Original Author:
\n" -msgstr "

Original-Autor:
\n" - -msgid "

Code Contributors:
\n" -msgstr "

Code-Mitwirkende:
\n" - -msgid "

Lovely Patch Writers:
\n" -msgstr "

Wunderbare Patch-Schreiber:
\n" - -msgid "

Acknowledgement:
\n" -msgstr "

Bestätigung:
\n" - -msgid "

Scrupulous Testers:
\n" -msgstr "

Gewissenhafte Tester:
\n" - -msgid "and more, please let me know... thank you!))" -msgstr "und andere, bitten sagen Sie mir Bescheid... Danke!))" - -msgid "

And, all the boys in the backroom...
\n" -msgstr "

Und all die Jungs im Hinterzimmer...
\n" - -msgid "Feel free to join us! :)" -msgstr "Treten Sie uns bei, wenn Sie mögen! :)" - -#, c-format -msgid "About OpenQ %s" -msgstr "Über OpenQ %s" - -msgid "Change Icon" -msgstr "Icon ändern" - -msgid "Change Password" -msgstr "Passwort ändern" - -msgid "Account Information" -msgstr "Kontoinformationen" - -msgid "Update all QQ Quns" -msgstr "Alle QQ-Quns aktualisieren" - -msgid "About OpenQ" -msgstr "Über OpenQ" - -msgid "Modify Buddy Memo" -msgstr "Buddy-Notiz bearbeiten" - -#. *< type -#. *< ui_requirement -#. *< flags -#. *< dependencies -#. *< priority -#. *< id -#. *< name -#. *< version -#. * summary -#. * description -msgid "QQ Protocol Plugin" -msgstr "QQ-Protokoll-Plugin" - -msgid "Auto" -msgstr "Auto" - -msgid "Select Server" -msgstr "Server wählen" - -msgid "QQ2008" -msgstr "QQ2008" - -msgid "QQ2007" -msgstr "QQ2007" - -msgid "QQ2005" -msgstr "QQ2005" - -msgid "Connect by TCP" -msgstr "Über TCP verbinden" - -msgid "Show server notice" -msgstr "Server-Nachricht anzeigen" - -msgid "Show server news" -msgstr "Server-News anzeigen" - -msgid "Show chat room when msg comes" -msgstr "Chatraum zeigen, wenn Nachricht empfangen wird" - -msgid "Use default font" -msgstr "Standardschriftart benutzen" - -msgid "Keep alive interval (seconds)" -msgstr "Intervall zum Aufrechterhalten der Verbindung (Sekunden)" - -msgid "Update interval (seconds)" -msgstr "Aktualisierungsintervall (Sekunden)" - -msgid "Unable to decrypt server reply" -msgstr "Kann die Antwort des Servers nicht entschlüsseln" - -#, c-format -msgid "Failed requesting token, 0x%02X" -msgstr "Fehler beim Anfordern des Tokens, 0x%02X" - -#, c-format -msgid "Invalid token len, %d" -msgstr "Ungültige Länge des Tokens, %d" - -#. extend redirect used in QQ2006 -msgid "Redirect_EX is not currently supported" -msgstr "Redirect_EX wird im Moment nicht unterstützt" - -#. need activation -#. need activation -#. need activation -msgid "Activation required" -msgstr "Aktivierung erforderlich" - -#, c-format -msgid "Unknown reply code when logging in (0x%02X)" -msgstr "Unbekannte Antwort bei der Anmeldung (0x%02X)" - -msgid "Requesting captcha" -msgstr "Captcha anfordern" - -msgid "Checking captcha" -msgstr "Captcha überprüfen" - -msgid "Failed captcha verification" -msgstr "Captcha-Überprüfung fehlgeschlagen" - -msgid "Captcha Image" -msgstr "Captcha-Bild" - -msgid "Enter code" -msgstr "Geben Sie den Code ein" - -msgid "QQ Captcha Verification" -msgstr "QQ-Captcha-Überprüfung" - -msgid "Enter the text from the image" -msgstr "Bitte geben Sie den Text aus dem Bild ein" - -#, c-format -msgid "Unknown reply when checking password (0x%02X)" -msgstr "Unbekannte Antwort bei Überprüfungen des Passwortes (0x%02X)" - -#, c-format -msgid "" -"Unknown reply code when logging in (0x%02X):\n" -"%s" -msgstr "" -"Unbekannte Antwort bei der Anmeldung (0x%02X):\n" -"%s" - -msgid "Socket error" -msgstr "Socket-Fehler" - -msgid "Getting server" -msgstr "Hole server" - -msgid "Requesting token" -msgstr "Fordere Token an" - -msgid "Unable to resolve hostname" -msgstr "Hostname konnte nicht aufgelöst werden" - -msgid "Invalid server or port" -msgstr "Ungültiger Server oder Port" - -msgid "Connecting to server" -msgstr "Verbinde mit Server" - -msgid "QQ Error" -msgstr "QQ-Fehler" - -#, c-format -msgid "" -"Server News:\n" -"%s\n" -"%s\n" -"%s" -msgstr "" -"Server-News:\n" -"%s\n" -"%s\n" -"%s" - -#, c-format -msgid "%s:%s" -msgstr "%s:%s" - -#, c-format -msgid "From %s:" -msgstr "Von %s:" - -#, c-format -msgid "" -"Server notice From %s: \n" -"%s" -msgstr "" -"Servernotiz von %s: \n" -"%s" - -msgid "Unknown SERVER CMD" -msgstr "Unbekanntes SERVER-CMD" - -#, c-format -msgid "" -"Error reply of %s(0x%02X)\n" -"Room %u, reply 0x%02X" -msgstr "" -"Fehlerantwort von %s(0x%02X)\n" -"Raum %u, Antwort 0x%02X" - -msgid "QQ Qun Command" -msgstr "QQ-Qun-Kommando" - -msgid "Unable to decrypt login reply" -msgstr "Konnte die Antwort der Anmeldung nicht entschlüsseln" - -msgid "Unknown LOGIN CMD" -msgstr "Unbekanntes LOGIN-CMD" - -msgid "Unknown CLIENT CMD" -msgstr "Unbekanntes CLIENT-CMD" - -#, c-format -msgid "%d has declined the file %s" -msgstr "%d hat die Datei %s abgelehnt" - -msgid "File Send" -msgstr "Dateiübertragung" - -#, c-format -msgid "%d cancelled the transfer of %s" -msgstr "%d hat die Übertragung von %s abgebrochen" - #, c-format msgid "Group Title: %s
" msgstr "Gruppentitel: %s
" @@ -9700,6 +9070,9 @@ msgid "Unit" msgstr "Abteilung" +msgid "Note" +msgstr "Bemerkung" + msgid "Join Chat" msgstr "Chat betreten" @@ -10358,6 +9731,9 @@ msgid "Unable to create listen socket" msgstr "Lauschender Socket konnte nicht erstellt werden" +msgid "Unable to resolve hostname" +msgstr "Hostname konnte nicht aufgelöst werden" + msgid "SIP usernames may not contain whitespaces or @ symbols" msgstr "SIP-Benutzernamen dürfen keine Leerzeichen oder @-Symbole enthalten" @@ -10474,6 +9850,9 @@ msgid "Yahoo! system message for %s:" msgstr "Yahoo!-Systemnachricht für %s:" +msgid "Authorization denied message:" +msgstr "Nachricht für die Ablehnung der Autorisierung:" + #, c-format msgid "" "%s has (retroactively) denied your request to add them to your list for the " @@ -11272,15 +10651,18 @@ msgid "No Proxy" msgstr "Kein Proxy" -msgid "HTTP" -msgstr "HTTP" - msgid "SOCKS 4" msgstr "SOCKS 4" msgid "SOCKS 5" msgstr "SOCKS 5" +msgid "Tor/Privacy (SOCKS5)" +msgstr "Tor/Privatsphäre (SOCKS5)" + +msgid "HTTP" +msgstr "HTTP" + msgid "Use Environmental Settings" msgstr "Benutze Umgebungsvariablen" @@ -11308,6 +10690,12 @@ msgid "Pa_ssword:" msgstr "P_asswort:" +msgid "Use _silence suppression" +msgstr "Benutze _Geräuschunterdrückung" + +msgid "_Voice and Video" +msgstr "Sprache und _Video" + msgid "Unable to save new account" msgstr "Kann neues Konto nicht speichern" @@ -11357,10 +10745,21 @@ "bearbeiten oder löschen" #, c-format +msgid "" +"%s%s%s%s wants to add you (%s) to his or her buddy " +"list%s%s" +msgstr "" +"%s%s%s%s möchte Sie (%s) zu seiner oder ihrer Buddy-" +"Liste hinzufügen%s%s" + +#, c-format msgid "%s%s%s%s wants to add you (%s) to his or her buddy list%s%s" msgstr "" "%s%s%s%s möchte Sie (%s) zu seiner oder ihrer Buddy-Liste hinzufügen%s%s" +msgid "Send Instant Message" +msgstr "Sofortnachricht senden" + #. Buddy List msgid "Background Color" msgstr "Hintergrundfarbe" @@ -11918,6 +11317,9 @@ msgid "(Optional) A_lias:" msgstr "(Optionaler) A_lias:" +msgid "(Optional) _Invite message:" +msgstr "(Optionale) _Einladungsnachricht:" + msgid "Add buddy to _group:" msgstr "Buddy zu folgender _Gruppe hinzufügen:" @@ -13271,7 +12673,7 @@ "\n" msgid "DIR" -msgstr "VERZ" +msgstr "DIR" msgid "use DIR for config files" msgstr "DIR als Konfigurationsverzeichnis benutzen" @@ -13300,13 +12702,12 @@ " Without this only the first account will be enabled)." msgstr "" "angegebene Konten aktivieren (optionales Argument NAME\n" -" bestimmt Konto(n), die benutzt werden sollen,\n" -" getrennt durch Kommata.\n" -" Ohne diesen Parameter wird nur das erste " -"Konto aktiviert)." +" bestimmt Konto(n), das/die benutzt werden soll(en),\n" +" getrennt durch Kommata. Ohne diesen Parameter wird \n" +" nur das erste Konto aktiviert)." msgid "X display to use" -msgstr "das zu benutzenden X-Display" +msgstr "das zu benutzende X-Display" msgid "display the current version and exit" msgstr "zeigt die aktuelle Version und beendet das Programm" @@ -13404,6 +12805,13 @@ msgid "New Pounces" msgstr "Neuer Alarm" +#. Translators: Make sure you translate "Dismiss" differently than +#. "close"! This string is used in the "You have pounced" dialog +#. that appears when one of your Buddy Pounces is triggered. In +#. this context "Dismiss" means "I acknowledge that I've seen that +#. this pounce was triggered--remove it from this list." Translating +#. it as "Remove" is acceptable if you can't think of a more precise +#. word. msgid "Dismiss" msgstr "Verwerfen" @@ -14530,6 +13938,9 @@ msgid "PubSub Leaf" msgstr "PubSub-Blatt" +msgid "Other" +msgstr "Andere" + msgid "" "\n" "Description: " @@ -15394,6 +14805,21 @@ msgid "D_evice" msgstr "G_erät" +msgid "DROP" +msgstr "Stille, da unterhalb des Schwellwerts" + +msgid "Volume:" +msgstr "Lautstärke:" + +msgid "Silence threshold:" +msgstr "Schwellwert für Stille:" + +msgid "Input and Output Settings" +msgstr "Ein- und Ausgabeeinstellungen" + +msgid "Microphone Test" +msgstr "Mikrofontest" + #. *< magic #. *< major version #. *< minor version @@ -15406,9 +14832,6 @@ msgid "Voice/Video Settings" msgstr "Sprach-/Video-Einstellungen" -msgid "Voice and Video Settings" -msgstr "Sprach- und Video-Einstellungen" - #. *< name #. *< version msgid "Configure your microphone and webcam." diff -r ea4bb5fe1fdc -r 0d4702446530 po/en_CA.po --- a/po/en_CA.po Thu May 05 03:40:29 2011 +0000 +++ b/po/en_CA.po Mon May 09 04:26:46 2011 +0000 @@ -1,32 +1,35 @@ # Canadian English translation of Pidgin # Copyright (C) 2004-2005 Adam Weinberger and the Pidgin project +# Copyright (C) 2011 Elliott Sales de Andrade and the Pidgin project # This file is distributed under the same licence as the Pidgin package. # Adam Weinberger , 2004, 2005. +# Elliott Sales de Andrade 2011. # # msgid "" msgstr "" "Project-Id-Version: Pidgin\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-12-19 13:33-0500\n" -"PO-Revision-Date: 2005-03-17 19:45-0400\n" -"Last-Translator: Adam Weinberger \n" +"POT-Creation-Date: 2011-05-05 03:14-0400\n" +"PO-Revision-Date: 2011-05-05 02:50-0400\n" +"Last-Translator: Elliott Sales de Andrade \n" "Language-Team: Canadian English \n" -"Language: \n" +"Language: Canadian English\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Language: en_CA\n" +"X-Source-Language: C\n" #. Translators may want to transliterate the name. #. It is not to be translated. -#, fuzzy msgid "Finch" -msgstr "Finch" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "%s. Try `%s -h' for more information.\n" -msgstr "Pidgin %s. Try `%s -h' for more information.\n" +msgstr "" #, c-format msgid "" @@ -49,15 +52,13 @@ #. the user did not fill in the captcha msgid "Error" -msgstr "Error" - -#, fuzzy +msgstr "" + msgid "Account was not modified" -msgstr "Account has been disabled" - -#, fuzzy +msgstr "" + msgid "Account was not added" -msgstr "Account has been disabled" +msgstr "" msgid "Username of an account must be non-empty." msgstr "" @@ -71,10 +72,10 @@ msgstr "" msgid "New mail notifications" -msgstr "New mail notifications" +msgstr "" msgid "Remember password" -msgstr "Remember password" +msgstr "" msgid "There are no protocol plugins installed." msgstr "" @@ -83,88 +84,81 @@ msgstr "" msgid "Modify Account" -msgstr "Modify Account" - -#, fuzzy +msgstr "" + msgid "New Account" -msgstr "Account" +msgstr "" msgid "Protocol:" -msgstr "Protocol:" - -#, fuzzy +msgstr "" + msgid "Username:" -msgstr "_Username:" +msgstr "" msgid "Password:" -msgstr "Password:" +msgstr "" msgid "Alias:" -msgstr "Alias:" +msgstr "" #. Register checkbox -#, fuzzy msgid "Create this account on the server" -msgstr "You were disconnected from the server." +msgstr "" #. Cancel button #. Cancel msgid "Cancel" -msgstr "Cancel" +msgstr "" #. Save button #. Save msgid "Save" -msgstr "Save" +msgstr "" #, c-format msgid "Are you sure you want to delete %s?" -msgstr "Are you sure you want to delete %s?" - -#, fuzzy +msgstr "" + msgid "Delete Account" -msgstr "Account" +msgstr "" #. Delete button msgid "Delete" -msgstr "Delete" +msgstr "" msgid "Accounts" -msgstr "Accounts" - -#, fuzzy +msgstr "" + msgid "You can enable/disable accounts from the following list." -msgstr "You are awaiting authorization from the following buddies" +msgstr "" #. Add button msgid "Add" -msgstr "Add" +msgstr "" #. Modify button -#, fuzzy msgid "Modify" -msgstr "_Modify" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "%s%s%s%s has made %s his or her buddy%s%s" -msgstr "%s%s%s%s has made %s his or her buddy%s%s%s" +msgstr "" msgid "Add buddy to your list?" -msgstr "Add buddy to your list?" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "%s%s%s%s wants to add %s to his or her buddy list%s%s" -msgstr "The user %s wants to add %s to his or her buddy list." - -#, fuzzy +msgstr "" + msgid "Authorize buddy?" -msgstr "Authorize" +msgstr "" msgid "Authorize" -msgstr "Authorize" +msgstr "" msgid "Deny" -msgstr "Deny" +msgstr "" #, c-format msgid "" @@ -172,154 +166,131 @@ "Total: %d" msgstr "" -#, fuzzy, c-format +#, c-format msgid "Account: %s (%s)" -msgstr "%s on %s (%s)" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "" "\n" "Last Seen: %s ago" msgstr "" -"\n" -"%s: %s" - -#, fuzzy + msgid "Default" -msgstr "Gnome Default" - -#, fuzzy +msgstr "" + msgid "You must provide a username for the buddy." -msgstr "Please enter the name of the group to be added." +msgstr "" msgid "You must provide a group." msgstr "" -#, fuzzy msgid "You must select an account." -msgstr "You must specify a nick" +msgstr "" msgid "The selected account is not online." msgstr "" -#, fuzzy msgid "Error adding buddy" msgstr "" -"Error reading %s: \n" -"%s.\n" msgid "Username" -msgstr "Username" - -#, fuzzy +msgstr "" + msgid "Alias (optional)" -msgstr "Message Notification" - -#, fuzzy +msgstr "" + +msgid "Invite message (optional)" +msgstr "" + msgid "Add in group" -msgstr "Add Group" +msgstr "" msgid "Account" -msgstr "Account" +msgstr "" msgid "Add Buddy" -msgstr "Add Buddy" - -#, fuzzy +msgstr "" + msgid "Please enter buddy information." -msgstr "Please enter a buddy to pounce." +msgstr "" msgid "Chats" -msgstr "Chats" +msgstr "" #. Extract their Name and put it in msgid "Name" -msgstr "Name" +msgstr "" msgid "Alias" -msgstr "Alias" - -#, fuzzy +msgstr "" + msgid "Group" -msgstr "Group:" - -#, fuzzy +msgstr "" + msgid "Auto-join" -msgstr "Auto-Join" +msgstr "" msgid "Add Chat" -msgstr "Add Chat" +msgstr "" msgid "You can edit more information from the context menu later." msgstr "" -#, fuzzy msgid "Error adding group" msgstr "" -"Error reading %s: \n" -"%s.\n" - -#, fuzzy + msgid "You must give a name for the group to add." -msgstr "Please enter the name of the group to be added." +msgstr "" msgid "Add Group" -msgstr "Add Group" - -#, fuzzy +msgstr "" + msgid "Enter the name of the group" -msgstr "Please enter the name of the group to be added." - -#, fuzzy +msgstr "" + msgid "Edit Chat" -msgstr "Add Chat" +msgstr "" msgid "Please Update the necessary fields." msgstr "" -#, fuzzy msgid "Edit" -msgstr "_Edit" - -#, fuzzy +msgstr "" + msgid "Edit Settings" -msgstr "Use Environmental Settings" +msgstr "" msgid "Information" -msgstr "Information" - -#, fuzzy +msgstr "" + msgid "Retrieving..." -msgstr "Connecting..." +msgstr "" msgid "Get Info" -msgstr "Get Info" - -#, fuzzy +msgstr "" + msgid "Add Buddy Pounce" -msgstr "Add Buddy _Pounce" +msgstr "" msgid "Send File" -msgstr "Send File" +msgstr "" msgid "Blocked" -msgstr "Blocked" - -#, fuzzy +msgstr "" + msgid "Show when offline" -msgstr "Not allowed when offline" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Please enter the new name for %s" -msgstr "Please enter a new name for the selected group." - -#, fuzzy +msgstr "" + msgid "Rename" -msgstr "_Rename" - -#, fuzzy +msgstr "" + msgid "Set Alias" -msgstr "Alias" +msgstr "" msgid "Enter empty string to reset the name." msgstr "" @@ -330,21 +301,20 @@ msgid "Removing this group will also remove all the buddies in the group" msgstr "" -#, fuzzy, c-format +#, c-format msgid "Are you sure you want to remove %s?" -msgstr "Are you sure you want to delete %s?" +msgstr "" #. XXX: anything to do with the returned ui-handle? -#, fuzzy msgid "Confirm Remove" -msgstr "Confirm Account" +msgstr "" msgid "Remove" -msgstr "Remove" +msgstr "" #. Buddy List msgid "Buddy List" -msgstr "Buddy List" +msgstr "" msgid "Place tagged" msgstr "" @@ -352,151 +322,124 @@ msgid "Toggle Tag" msgstr "" -#, fuzzy msgid "View Log" -msgstr "View _Log" +msgstr "" #. General msgid "Nickname" -msgstr "Nickname" +msgstr "" #. Never know what those translations might end up like... #. Idle stuff msgid "Idle" -msgstr "Idle" - -#, fuzzy +msgstr "" + msgid "On Mobile" -msgstr "Send to Mobile" +msgstr "" msgid "New..." -msgstr "New..." - -#, fuzzy +msgstr "" + msgid "Saved..." -msgstr "Save File..." +msgstr "" msgid "Plugins" -msgstr "Plugins" - -#, fuzzy +msgstr "" + msgid "Block/Unblock" -msgstr "Block" +msgstr "" msgid "Block" -msgstr "Block" - -#, fuzzy +msgstr "" + msgid "Unblock" -msgstr "Block" - -#, fuzzy +msgstr "" + msgid "" "Please enter the username or alias of the person you would like to Block/" "Unblock." -msgstr "Please enter the screen name of the person you would like to IM." +msgstr "" #. Not multiline #. Not masked? #. No hints? msgid "OK" -msgstr "OK" +msgstr "" msgid "New Instant Message" -msgstr "New Instant Message" - -#, fuzzy +msgstr "" + msgid "Please enter the username or alias of the person you would like to IM." -msgstr "Please enter the screen name of the person you would like to IM." - -#, fuzzy +msgstr "" + msgid "Channel" -msgstr "_Channel:" +msgstr "" msgid "Join a Chat" -msgstr "Join a Chat" - -#, fuzzy +msgstr "" + msgid "Please enter the name of the chat you want to join." -msgstr "Please enter the URL of the link that you want to insert." - -#, fuzzy +msgstr "" + msgid "Join" -msgstr "_Join" - -#, fuzzy +msgstr "" + msgid "" "Please enter the username or alias of the person whose log you would like to " "view." msgstr "" -"Please enter the screen name of the person whose log you would like to view." #. Create the "Options" frame. -#, fuzzy msgid "Options" -msgstr "/_Options" - -#, fuzzy +msgstr "" + msgid "Send IM..." -msgstr "Save File..." - -#, fuzzy +msgstr "" + msgid "Block/Unblock..." -msgstr "Block" - -#, fuzzy +msgstr "" + msgid "Join Chat..." -msgstr "Join A Chat..." - -#, fuzzy +msgstr "" + msgid "View Log..." -msgstr "View _Log" - -#, fuzzy +msgstr "" + msgid "View All Logs" -msgstr "View _Log" +msgstr "" msgid "Show" msgstr "" -#, fuzzy msgid "Empty groups" -msgstr "By group" - -#, fuzzy +msgstr "" + msgid "Offline buddies" -msgstr "Dim i_dle buddies" - -#, fuzzy +msgstr "" + msgid "Sort" -msgstr "Port" - -#, fuzzy +msgstr "" + msgid "By Status" -msgstr "By status" - -#, fuzzy +msgstr "" + msgid "Alphabetically" -msgstr "Alphabetical" - -#, fuzzy +msgstr "" + msgid "By Log Size" -msgstr "By log size" - -#, fuzzy +msgstr "" + msgid "Buddy" -msgstr "_Buddy:" +msgstr "" msgid "Chat" -msgstr "Chat" - -#, fuzzy +msgstr "" + msgid "Grouping" -msgstr "Group:" - -#, fuzzy +msgstr "" + msgid "Certificate Import" -msgstr "Connect" +msgstr "" msgid "Specify a hostname" msgstr "" @@ -516,9 +459,8 @@ msgid "X.509 certificate import failed" msgstr "" -#, fuzzy msgid "Select a PEM certificate" -msgstr "Select a file" +msgstr "" #, c-format msgid "" @@ -560,24 +502,23 @@ msgid "Certificate Manager" msgstr "" -#, fuzzy msgid "Hostname" -msgstr "Last name:" +msgstr "" msgid "Info" -msgstr "Info" +msgstr "" #. Close button msgid "Close" -msgstr "Close" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "%s (%s)" -msgstr "%s on %s (%s)" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "%s disconnected." -msgstr "Disconnected." +msgstr "" #, c-format msgid "" @@ -591,47 +532,42 @@ msgstr "" msgid "No such command." -msgstr "No such command." +msgstr "" msgid "Syntax Error: You typed the wrong number of arguments to that command." msgstr "" -"Syntax Error: You typed the wrong number of arguments to that command." msgid "Your command failed for an unknown reason." -msgstr "Your command failed for an unknown reason." - -#, fuzzy +msgstr "" + msgid "That command only works in chats, not IMs." -msgstr "That command only works in Chats, not IMs." - -#, fuzzy +msgstr "" + msgid "That command only works in IMs, not chats." -msgstr "That command only works in IMs, not Chats." +msgstr "" msgid "That command doesn't work on this protocol." -msgstr "That command doesn't work on this protocol." - -#, fuzzy +msgstr "" + msgid "Message was not sent, because you are not signed on." -msgstr "Message could not be sent because the user is offline:" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "%s (%s -- %s)" -msgstr "%s on %s (%s)" +msgstr "" #, c-format msgid "%s [%s]" msgstr "" -#, fuzzy, c-format +#, c-format msgid "" "\n" "%s is typing..." -msgstr "User is typing..." - -#, fuzzy +msgstr "" + msgid "You have left this chat." -msgstr "You talk in chat" +msgstr "" msgid "" "The account has disconnected and you are no longer in this chat. You will be " @@ -645,98 +581,82 @@ "Logging stopped. Future messages in this conversation will not be logged." msgstr "" -#, fuzzy msgid "Send To" -msgstr "_Send As" - -#, fuzzy +msgstr "" + msgid "Conversation" -msgstr "Conversations" +msgstr "" msgid "Clear Scrollback" msgstr "" -#, fuzzy msgid "Show Timestamps" -msgstr "Timestamps" - -#, fuzzy +msgstr "" + msgid "Add Buddy Pounce..." -msgstr "Add Buddy _Pounce" - -#, fuzzy +msgstr "" + msgid "Invite..." -msgstr "Invite" - -#, fuzzy +msgstr "" + msgid "Enable Logging" -msgstr "/Options/Enable Logging" - -#, fuzzy +msgstr "" + msgid "Enable Sounds" -msgstr "/Options/Enable Sounds" - -#, fuzzy +msgstr "" + msgid "You are not connected." -msgstr "Could not connect" - -#, fuzzy +msgstr "" + msgid " " -msgstr "(%s) %s : %s\n" +msgstr "" #, c-format msgid "List of %d user:\n" msgid_plural "List of %d users:\n" msgstr[0] "" -msgstr[1] "" - -#, fuzzy + msgid "Supported debug options are: plugins version" -msgstr "Supported debug options are: version" +msgstr "" msgid "No such command (in this context)." -msgstr "No such command (in this context)." +msgstr "" msgid "" "Use \"/help <command>\" for help on a specific command.\n" "The following commands are available in this context:\n" msgstr "" -"Use \"/help <command>\" for help on a specific command.\n" -"The following commands are available in this context:\n" #, c-format msgid "" "%s is not a valid message class. See '/help msgcolor' for valid message " "classes." msgstr "" +"%s is not a valid message class. See '/help msgcolour' for valid message " +"classes." #, c-format msgid "%s is not a valid color. See '/help msgcolor' for valid colors." -msgstr "" +msgstr "%s is not a valid colour. See '/help msgcolour' for valid colours." msgid "" "say <message>: Send a message normally as if you weren't using a " "command." msgstr "" -"say <message>: Send a message normally as if you weren't using a " -"command." msgid "me <action>: Send an IRC style action to a buddy or chat." -msgstr "me <action>: Send an IRC style action to a buddy or chat." +msgstr "" msgid "" "debug <option>: Send various debug information to the current " "conversation." msgstr "" -"debug <option>: Send various debug information to the current " -"conversation." - -#, fuzzy + msgid "clear: Clears the conversation scrollback." -msgstr "%s has closed the conversation window." +msgstr "" msgid "help <command>: Help on a specific command." -msgstr "help <command>: Help on a specific command." +msgstr "" msgid "users: Show the list of users in the chat." msgstr "" @@ -766,113 +686,108 @@ "background>: black, red, green, blue, white, gray, darkgray, magenta, " "cyan, default

EXAMPLE:
msgcolor send cyan default" msgstr "" +"msgcolour <class> <foreground> <background>: Set the " +"colour for different classes of messages in the conversation window.
" +"<class>: receive, send, highlight, action, timestamp
<" +"foreground/background>: black, red, green, blue, white, grey, darkgrey, " +"magenta, cyan, default

EXAMPLE:
msgcolour send cyan default" msgid "Unable to open file." -msgstr "Unable to open file." +msgstr "" msgid "Debug Window" -msgstr "Debug Window" +msgstr "" #. XXX: Setting the GROW_Y for the following widgets don't make sense. But right now #. * it's necessary to make the width of the debug window resizable ... like I said, #. * it doesn't make sense. The bug is likely in the packing in gntbox.c. #. -#, fuzzy msgid "Clear" -msgstr "Close" - -#, fuzzy +msgstr "" + msgid "Filter:" -msgstr "Failed" +msgstr "" msgid "Pause" -msgstr "Pause" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "File Transfers - %d%% of %d file" msgid_plural "File Transfers - %d%% of %d files" -msgstr[0] "File transfer to %s aborted.\n" -msgstr[1] "File transfer to %s aborted.\n" +msgstr[0] "" #. Create the window. msgid "File Transfers" -msgstr "File Transfers" +msgstr "" msgid "Progress" -msgstr "Progress" +msgstr "" msgid "Filename" -msgstr "Filename" +msgstr "" msgid "Size" -msgstr "Size" - -#, fuzzy +msgstr "" + msgid "Speed" -msgstr "Speed:" +msgstr "" msgid "Remaining" -msgstr "Remaining" +msgstr "" #. XXX: Use of ggp_str_to_uin() is an ugly hack! #. presence msgid "Status" -msgstr "Status" +msgstr "" msgid "Close this window when all transfers finish" msgstr "" -#, fuzzy msgid "Clear finished transfers" -msgstr "_Clear finished transfers" - -#, fuzzy +msgstr "" + msgid "Stop" -msgstr "Hiptop" +msgstr "" msgid "Waiting for transfer to begin" -msgstr "Waiting for transfer to begin" +msgstr "" msgid "Cancelled" -msgstr "Cancelled" +msgstr "" msgid "Failed" -msgstr "Failed" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "%.2f KiB/s" -msgstr "%.2f KB/s" - -#, fuzzy +msgstr "" + msgid "Sent" -msgstr "_Set" - -#, fuzzy +msgstr "" + msgid "Received" -msgstr "Send Message" +msgstr "" msgid "Finished" -msgstr "Finished" +msgstr "" #, c-format msgid "The file was saved as %s." msgstr "" -#, fuzzy msgid "Sending" -msgstr "Send" - -#, fuzzy +msgstr "" + msgid "Receiving" -msgstr "Remaining" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Conversation in %s on %s" -msgstr "Conversations with %s" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Conversation with %s on %s" -msgstr "Conversations with %s" +msgstr "" msgid "%B %Y" msgstr "" @@ -894,43 +809,39 @@ msgid "No logs were found" msgstr "" -#, fuzzy msgid "Total log size:" -msgstr "By log size" +msgstr "" #. Search box ********* msgid "Scroll/Search: " msgstr "" -#, fuzzy, c-format +#, c-format msgid "Conversations in %s" -msgstr "Conversations with %s" +msgstr "" #, c-format msgid "Conversations with %s" -msgstr "Conversations with %s" - -#, fuzzy +msgstr "" + msgid "All Conversations" -msgstr "Conversations" +msgstr "" msgid "System Log" -msgstr "System Log" - -#, fuzzy +msgstr "" + msgid "Calling..." -msgstr "Calculating..." +msgstr "" msgid "Hangup" msgstr "" #. Number of actions msgid "Accept" -msgstr "Accept" - -#, fuzzy +msgstr "" + msgid "Reject" -msgstr "Reset" +msgstr "" msgid "Call in progress." msgstr "" @@ -946,71 +857,62 @@ msgid "%s is trying to start an unsupported media session type with you." msgstr "" -#, fuzzy msgid "You have rejected the call." -msgstr "You have parted the channel%s%s" +msgstr "" msgid "call: Make an audio call." msgstr "" -#, fuzzy msgid "Emails" -msgstr "Email" +msgstr "" msgid "You have mail!" msgstr "" -#, fuzzy msgid "Sender" -msgstr "Gender" +msgstr "" msgid "Subject" msgstr "" -#, fuzzy, c-format +#, c-format msgid "%s (%s) has %d new message." msgid_plural "%s (%s) has %d new messages." -msgstr[0] "%s has %d new message." -msgstr[1] "%s has %d new messages." - -#, fuzzy +msgstr[0] "" + msgid "New Mail" -msgstr "Email" +msgstr "" #, c-format msgid "Info for %s" -msgstr "Info for %s" +msgstr "" msgid "Buddy Information" -msgstr "Buddy Information" - -#, fuzzy +msgstr "" + msgid "Continue" -msgstr "Connecting" +msgstr "" msgid "IM" -msgstr "IM" +msgstr "" msgid "Invite" -msgstr "Invite" - -#, fuzzy +msgstr "" + msgid "(none)" -msgstr "(no name)" +msgstr "" #. XXX: The following expects that finch_notify_message gets called. This #. * may not always happen, e.g. when another plugin sets its own #. * notify_message. So tread carefully. -#, fuzzy msgid "URI" -msgstr "UIN" +msgstr "" msgid "ERROR" msgstr "" -#, fuzzy msgid "loading plugin failed" -msgstr "Ping failed" +msgstr "" msgid "unloading plugin failed" msgstr "" @@ -1031,9 +933,8 @@ msgid "No configuration options for this plugin." msgstr "" -#, fuzzy msgid "Error loading plugin" -msgstr "Provides support for loading perl plugins." +msgstr "" msgid "The selected file is not a valid plugin." msgstr "" @@ -1042,20 +943,17 @@ "Please open the debug window and try again to see the exact error message." msgstr "" -#, fuzzy msgid "Select plugin to install" -msgstr "Select a file" - -#, fuzzy +msgstr "" + msgid "You can (un)load plugins from the following list." -msgstr "You are awaiting authorization from the following buddies" +msgstr "" msgid "Install Plugin..." msgstr "" -#, fuzzy msgid "Configure Plugin" -msgstr "Configure Room" +msgstr "" #. copy the preferences to tmp values... #. * I liked "take affect immediately" Oh well :-( @@ -1063,108 +961,88 @@ #. Back to instant-apply! I win! BU-HAHAHA! #. Create the window msgid "Preferences" -msgstr "Preferences" +msgstr "" msgid "Please enter a buddy to pounce." -msgstr "Please enter a buddy to pounce." +msgstr "" msgid "New Buddy Pounce" -msgstr "New Buddy Pounce" +msgstr "" msgid "Edit Buddy Pounce" -msgstr "Edit Buddy Pounce" +msgstr "" msgid "Pounce Who" -msgstr "Pounce Who" +msgstr "" #. Account: msgid "Account:" -msgstr "Account:" - -#, fuzzy +msgstr "" + msgid "Buddy name:" -msgstr "_Buddy name:" +msgstr "" #. Create the "Pounce When Buddy..." frame. -#, fuzzy msgid "Pounce When Buddy..." -msgstr "Pounce When" - -#, fuzzy +msgstr "" + msgid "Signs on" -msgstr "Si_gn on" - -#, fuzzy +msgstr "" + msgid "Signs off" -msgstr "Sign _off" - -#, fuzzy +msgstr "" + msgid "Goes away" -msgstr "When away" - -#, fuzzy +msgstr "" + msgid "Returns from away" -msgstr "_Return from away" - -#, fuzzy +msgstr "" + msgid "Becomes idle" -msgstr "%s became idle" - -#, fuzzy +msgstr "" + msgid "Is no longer idle" -msgstr "%s is no longer idle." - -#, fuzzy +msgstr "" + msgid "Starts typing" -msgstr "Buddy starts _typing" - -#, fuzzy +msgstr "" + msgid "Pauses while typing" -msgstr "User is typing..." - -#, fuzzy +msgstr "" + msgid "Stops typing" -msgstr "Buddy stops t_yping" - -#, fuzzy +msgstr "" + msgid "Sends a message" -msgstr "Send a _message" +msgstr "" #. Create the "Action" frame. -#, fuzzy msgid "Action" -msgstr "Location" - -#, fuzzy +msgstr "" + msgid "Open an IM window" -msgstr "Op_en an IM window" - -#, fuzzy +msgstr "" + msgid "Pop up a notification" -msgstr "_Popup notification" - -#, fuzzy +msgstr "" + msgid "Send a message" -msgstr "Send a _message" - -#, fuzzy +msgstr "" + msgid "Execute a command" -msgstr "E_xecute a command" - -#, fuzzy +msgstr "" + msgid "Play a sound" -msgstr "P_lay a sound" - -#, fuzzy +msgstr "" + msgid "Pounce only when my status is not Available" -msgstr "Chat in %s is not available." +msgstr "" msgid "Recurring" msgstr "" -#, fuzzy msgid "Cannot create pounce" -msgstr "Cannot change nick" +msgstr "" msgid "You do not have any accounts." msgstr "" @@ -1172,181 +1050,164 @@ msgid "You must create an account first before you can create a pounce." msgstr "" -#, fuzzy, c-format +#, c-format msgid "Are you sure you want to delete the pounce on %s for %s?" -msgstr "Are you sure you want to delete %s?" - -#, fuzzy +msgstr "" + msgid "Buddy Pounces" -msgstr "New Buddy Pounce" +msgstr "" #, c-format msgid "%s has started typing to you (%s)" -msgstr "%s has started typing to you (%s)" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "%s has paused while typing to you (%s)" -msgstr "%s has started typing to you (%s)" +msgstr "" #, c-format msgid "%s has signed on (%s)" -msgstr "%s has signed on (%s)" +msgstr "" #, c-format msgid "%s has returned from being idle (%s)" -msgstr "%s has returned from being idle (%s)" +msgstr "" #, c-format msgid "%s has returned from being away (%s)" -msgstr "%s has returned from being away (%s)" +msgstr "" #, c-format msgid "%s has stopped typing to you (%s)" -msgstr "%s has stopped typing to you (%s)" +msgstr "" #, c-format msgid "%s has signed off (%s)" -msgstr "%s has signed off (%s)" +msgstr "" #, c-format msgid "%s has become idle (%s)" -msgstr "%s has become idle (%s)" +msgstr "" #, c-format msgid "%s has gone away. (%s)" -msgstr "%s has gone away. (%s)" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "%s has sent you a message. (%s)" -msgstr "%s wants to send you %s (%s)" +msgstr "" msgid "Unknown pounce event. Please report this!" -msgstr "Unknown pounce event. Please report this!" +msgstr "" msgid "Based on keyboard use" msgstr "" -#, fuzzy msgid "From last sent message" -msgstr "C_ontrol-Enter sends message" +msgstr "" msgid "Never" -msgstr "Never" - -#, fuzzy +msgstr "" + msgid "Show Idle Time" -msgstr "Set Account Idle Time" - -#, fuzzy +msgstr "" + msgid "Show Offline Buddies" -msgstr "/Buddies/Show Offline Buddies" - -#, fuzzy +msgstr "" + msgid "Notify buddies when you are typing" -msgstr "_Notify buddies that you are typing to them" - -#, fuzzy +msgstr "" + msgid "Log format" -msgstr "Log _Format:" +msgstr "" msgid "Log IMs" msgstr "" -#, fuzzy msgid "Log chats" -msgstr "Log all c_hats" +msgstr "" msgid "Log status change events" msgstr "" -#, fuzzy msgid "Report Idle time" -msgstr "Show idle _times" - -#, fuzzy +msgstr "" + msgid "Change status when idle" -msgstr "Set away _when idle" - -#, fuzzy +msgstr "" + msgid "Minutes before changing status" -msgstr "_Minutes before setting away:" - -#, fuzzy +msgstr "" + msgid "Change status to" -msgstr "Change Address To:" +msgstr "" msgid "Conversations" -msgstr "Conversations" +msgstr "" msgid "Logging" -msgstr "Logging" +msgstr "" msgid "You must fill all the required fields." msgstr "" -#, fuzzy msgid "The required fields are underlined." -msgstr "The required plugin %s was unable to load." - -#, fuzzy +msgstr "" + msgid "Not implemented yet." -msgstr "Feature Not Implemented" +msgstr "" msgid "Save File..." -msgstr "Save File..." +msgstr "" msgid "Open File..." -msgstr "Open File..." - -#, fuzzy +msgstr "" + msgid "Choose Location..." -msgstr "Location" +msgstr "" msgid "Hit 'Enter' to find more rooms of this category." msgstr "" -#, fuzzy msgid "Get" -msgstr "_Set" +msgstr "" #. Create the window. msgid "Room List" -msgstr "Room List" +msgstr "" msgid "Buddy logs in" -msgstr "Buddy logs in" +msgstr "" msgid "Buddy logs out" -msgstr "Buddy logs out" +msgstr "" msgid "Message received" -msgstr "Message received" +msgstr "" msgid "Message received begins conversation" -msgstr "Message received begins conversation" +msgstr "" msgid "Message sent" -msgstr "Message sent" +msgstr "" msgid "Person enters chat" -msgstr "Person enters chat" +msgstr "" msgid "Person leaves chat" -msgstr "Person leaves chat" +msgstr "" msgid "You talk in chat" -msgstr "You talk in chat" +msgstr "" msgid "Others talk in chat" -msgstr "Others talk in chat" - -#, fuzzy +msgstr "" + msgid "Someone says your username in chat" -msgstr "Someone says your name in chat" - -#, fuzzy +msgstr "" + msgid "Attention received" -msgstr "Registration Required" +msgstr "" msgid "GStreamer Failure" msgstr "" @@ -1354,109 +1215,93 @@ msgid "GStreamer failed to initialize." msgstr "" -#, fuzzy msgid "(default)" -msgstr "Gnome Default" - -#, fuzzy +msgstr "" + msgid "Select Sound File ..." -msgstr "Select a file" - -#, fuzzy +msgstr "" + msgid "Sound Preferences" -msgstr "Preferences" - -#, fuzzy +msgstr "" + msgid "Profiles" -msgstr "Profile" +msgstr "" msgid "Automatic" -msgstr "Automatic" - -#, fuzzy +msgstr "" + msgid "Console Beep" -msgstr "Console beep" +msgstr "" msgid "Command" -msgstr "Command" - -#, fuzzy +msgstr "" + msgid "No Sound" -msgstr "Sounds" +msgstr "" msgid "Sound Method" -msgstr "Sound Method" - -#, fuzzy +msgstr "" + msgid "Method: " -msgstr "_Method:" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "" "Sound Command\n" "(%s for filename)" msgstr "" -"Sound c_ommand:\n" -"(%s for filename)" #. Sound options msgid "Sound Options" -msgstr "Sound Options" - -#, fuzzy +msgstr "" + msgid "Sounds when conversation has focus" -msgstr "Sounds when conversation has _focus" - -#, fuzzy +msgstr "" + msgid "Always" -msgstr "Away" - -#, fuzzy +msgstr "" + msgid "Only when available" -msgstr "Unavailable" - -#, fuzzy +msgstr "" + msgid "Only when not available" -msgstr "Chat in %s is not available." +msgstr "" msgid "Volume(0-100):" msgstr "" #. Sound events msgid "Sound Events" -msgstr "Sound Events" +msgstr "" msgid "Event" -msgstr "Event" - -#, fuzzy +msgstr "" + msgid "File" -msgstr "Failed" +msgstr "" msgid "Test" -msgstr "Test" +msgstr "" msgid "Reset" -msgstr "Reset" +msgstr "" msgid "Choose..." -msgstr "Choose..." - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Are you sure you want to delete \"%s\"" -msgstr "Are you sure you want to delete %s?" - -#, fuzzy +msgstr "" + msgid "Delete Status" -msgstr "Online Status" - -#, fuzzy +msgstr "" + msgid "Saved Statuses" -msgstr "Server Statistics" +msgstr "" #. title msgid "Title" -msgstr "Title" +msgstr "" msgid "Type" msgstr "" @@ -1470,73 +1315,60 @@ #. not independent #. Attributes - each status can have a message. msgid "Message" -msgstr "Message" +msgstr "" #. Use -#, fuzzy msgid "Use" -msgstr "_Use" - -#, fuzzy +msgstr "" + msgid "Invalid title" -msgstr "Invalid authzid" - -#, fuzzy +msgstr "" + msgid "Please enter a non-empty title for the status." -msgstr "Please enter a new name for the selected group." - -#, fuzzy +msgstr "" + msgid "Duplicate title" -msgstr "Public key file" - -#, fuzzy +msgstr "" + msgid "Please enter a different title for the status." -msgstr "Please enter a new name for the selected group." - -#, fuzzy +msgstr "" + msgid "Substatus" -msgstr "Status" +msgstr "" msgid "Status:" -msgstr "Status:" - -#, fuzzy +msgstr "" + msgid "Message:" -msgstr "_Message:" - -#, fuzzy +msgstr "" + msgid "Edit Status" -msgstr "Marital Status" +msgstr "" msgid "Use different status for following accounts" msgstr "" #. Save & Use -#, fuzzy msgid "Save & Use" -msgstr "Sa_ve & Use" +msgstr "" msgid "Certificates" msgstr "" msgid "Sounds" -msgstr "Sounds" - -#, fuzzy +msgstr "" + msgid "Statuses" -msgstr "Status" - -#, fuzzy +msgstr "" + msgid "Error loading the plugin." -msgstr "Provides support for loading perl plugins." - -#, fuzzy +msgstr "" + msgid "Couldn't find X display" -msgstr "Cannot send file" - -#, fuzzy +msgstr "" + msgid "Couldn't find window" -msgstr "Cannot send file" +msgstr "" msgid "This plugin cannot be loaded because it was not built with X11 support." msgstr "" @@ -1552,40 +1384,37 @@ "X, if possible." msgstr "" -#, fuzzy, c-format +#, c-format msgid "%s just signed on" -msgstr "%s signed on" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "%s just signed off" -msgstr "%s signed off" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "%s sent you a message" -msgstr "%s wants to send you a file" +msgstr "" #, c-format msgid "%s said your nick in %s" msgstr "" -#, fuzzy, c-format +#, c-format msgid "%s sent a message in %s" -msgstr "Send a _message" - -#, fuzzy +msgstr "" + msgid "Buddy signs on/off" -msgstr "Buddy is offline:" +msgstr "" msgid "You receive an IM" msgstr "" -#, fuzzy msgid "Someone speaks in a chat" -msgstr "Someone says your name in chat" - -#, fuzzy +msgstr "" + msgid "Someone says your name in a chat" -msgstr "Someone says your name in chat" +msgstr "" msgid "Notify with a toaster when" msgstr "" @@ -1602,9 +1431,9 @@ msgid "Toaster plugin" msgstr "" -#, fuzzy, c-format +#, c-format msgid "Conversation with %s on %s:
" -msgstr "Conversations with %s" +msgstr "" msgid "History Plugin Requires Logging" msgstr "" @@ -1616,19 +1445,16 @@ "the same conversation type(s)." msgstr "" -#, fuzzy msgid "GntHistory" -msgstr "History" +msgstr "" msgid "Shows recently logged conversations in new conversations." -msgstr "Shows recently logged conversations in new conversations." +msgstr "" msgid "" "When a new conversation is opened this plugin will insert the last " "conversation into the current conversation." msgstr "" -"When a new conversation is opened this plugin will insert the last " -"conversation into the current conversation." #, c-format msgid "" @@ -1649,9 +1475,8 @@ msgid "TinyURL (or other) address prefix" msgstr "" -#, fuzzy msgid "TinyURL" -msgstr "URL" +msgstr "" msgid "TinyURL plugin" msgstr "" @@ -1660,30 +1485,26 @@ msgstr "" msgid "Online" -msgstr "Online" +msgstr "" #. primitive, no, id, name msgid "Offline" -msgstr "Offline" - -#, fuzzy +msgstr "" + msgid "Online Buddies" -msgstr "Dim i_dle buddies" - -#, fuzzy +msgstr "" + msgid "Offline Buddies" -msgstr "Dim i_dle buddies" - -#, fuzzy +msgstr "" + msgid "Online/Offline" -msgstr "Online since" +msgstr "" msgid "Meebo" msgstr "" -#, fuzzy msgid "No Grouping" -msgstr "Sounds" +msgstr "" msgid "Nested Subgroup" msgstr "" @@ -1691,9 +1512,8 @@ msgid "Nested Grouping (experimental)" msgstr "" -#, fuzzy msgid "Provides alternate buddylist grouping options." -msgstr "Provides integration with Ximian Evolution." +msgstr "" msgid "Lastlog" msgstr "" @@ -1708,79 +1528,72 @@ msgid "Lastlog plugin." msgstr "" -#, fuzzy msgid "accounts" -msgstr "Accounts" - -#, fuzzy +msgstr "" + msgid "Password is required to sign on." -msgstr "Password has expired" +msgstr "" #, c-format msgid "Enter password for %s (%s)" -msgstr "Enter password for %s (%s)" - -#, fuzzy +msgstr "" + msgid "Enter Password" -msgstr "Change Password" - -#, fuzzy +msgstr "" + msgid "Save password" -msgstr "New password" +msgstr "" #, c-format msgid "Missing protocol plugin for %s" -msgstr "Missing protocol plugin for %s" +msgstr "" msgid "Connection Error" -msgstr "Connection Error" +msgstr "" msgid "New passwords do not match." -msgstr "New passwords do not match." +msgstr "" msgid "Fill out all fields completely." -msgstr "Fill out all fields completely." +msgstr "" msgid "Original password" -msgstr "Original password" +msgstr "" msgid "New password" -msgstr "New password" +msgstr "" msgid "New password (again)" -msgstr "New password (again)" +msgstr "" #, c-format msgid "Change password for %s" -msgstr "Change password for %s" +msgstr "" msgid "Please enter your current password and your new password." -msgstr "Please enter your current password and your new password." +msgstr "" #, c-format msgid "Change user information for %s" -msgstr "Change user information for %s" +msgstr "" msgid "Set User Info" -msgstr "Set User Info" - -#, fuzzy +msgstr "" + msgid "This protocol does not support setting a public alias." -msgstr "This protocol does not support chat rooms." - -#, fuzzy +msgstr "" + msgid "This protocol does not support fetching the public alias." -msgstr "This protocol does not support chat rooms." +msgstr "" msgid "Unknown" -msgstr "Unknown" +msgstr "" msgid "Buddies" -msgstr "Buddies" - -#, fuzzy +msgstr "" + msgid "buddy list" -msgstr "Buddy List" +msgstr "" msgid "The certificate is self-signed and cannot be automatically checked." msgstr "" @@ -1809,16 +1622,14 @@ "validated." msgstr "" -#, fuzzy msgid "The certificate chain presented is invalid." -msgstr "The SecurID key entered is invalid." +msgstr "" msgid "The certificate has been revoked." msgstr "" -#, fuzzy msgid "An unknown certificate error occurred." -msgstr "An unknown signon error has occurred: %s." +msgstr "" msgid "(DOES NOT MATCH)" msgstr "" @@ -1849,9 +1660,9 @@ msgstr "" #. Make messages -#, fuzzy, c-format +#, c-format msgid "Accept certificate for %s?" -msgstr "Accept chat invitation?" +msgstr "" #. TODO: Find what the handle ought to be msgid "SSL Certificate Verification" @@ -1868,9 +1679,8 @@ msgid "SSL Certificate Error" msgstr "" -#, fuzzy msgid "Unable to validate certificate" -msgstr "Unable to authenticate: %s" +msgstr "" #, c-format msgid "" @@ -1890,205 +1700,184 @@ msgstr "" #. TODO: Find what the handle ought to be -#, fuzzy msgid "Certificate Information" -msgstr "Profile Information" +msgstr "" #. show error to user msgid "Registration Error" -msgstr "Registration Error" - -#, fuzzy +msgstr "" + msgid "Unregistration Error" -msgstr "Registration Error" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "+++ %s signed on" -msgstr "%s signed on" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "+++ %s signed off" -msgstr "%s signed off" +msgstr "" #. Undocumented #. Unknown error msgid "Unknown error" -msgstr "Unknown error" - -#, fuzzy +msgstr "" + msgid "Unable to send message: The message is too large." -msgstr "Unable to send message. The message is too large." - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Unable to send message to %s." -msgstr "Unable to send message to %s:" +msgstr "" msgid "The message is too large." -msgstr "The message is too large." +msgstr "" msgid "Unable to send message." -msgstr "Unable to send message." +msgstr "" msgid "Send Message" -msgstr "Send Message" - -#, fuzzy +msgstr "" + msgid "_Send Message" -msgstr "Send Message" +msgstr "" #, c-format msgid "%s entered the room." -msgstr "%s entered the room." +msgstr "" #, c-format msgid "%s [%s] entered the room." -msgstr "%s [%s] entered the room." +msgstr "" #, c-format msgid "You are now known as %s" -msgstr "You are now known as %s" +msgstr "" #, c-format msgid "%s is now known as %s" -msgstr "%s is now known as %s" +msgstr "" #, c-format msgid "%s left the room." -msgstr "%s left the room." +msgstr "" #, c-format msgid "%s left the room (%s)." -msgstr "%s left the room (%s)." - -#, fuzzy +msgstr "" + msgid "Invite to chat" -msgstr "Initiate Conference" +msgstr "" #. Put our happy label in it. msgid "" "Please enter the name of the user you wish to invite, along with an optional " "invite message." msgstr "" -"Please enter the name of the user you wish to invite, along with an optional " -"invite message." - -#, fuzzy, c-format + +#, c-format msgid "Failed to get connection: %s" -msgstr "Failed to set cmodes for %s" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Failed to get name: %s" -msgstr "Failed to store image: %s\n" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Failed to get serv name: %s" -msgstr "Failed to store image: %s\n" +msgstr "" msgid "Purple's D-BUS server is not running for the reason listed below" msgstr "" -#, fuzzy msgid "No name" -msgstr "Last name:" - -#, fuzzy +msgstr "" + msgid "Unable to create new resolver process\n" -msgstr "Unable to create socket" - -#, fuzzy +msgstr "" + msgid "Unable to send request to resolver process\n" -msgstr "Unable to send message to %s:" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "" "Error resolving %s:\n" "%s" msgstr "" -"Error reading %s: \n" -"%s.\n" - -#, fuzzy, c-format + +#, c-format msgid "Error resolving %s: %d" msgstr "" -"Error reading %s: \n" -"%s.\n" - -#, fuzzy, c-format + +#, c-format msgid "" "Error reading from resolver process:\n" "%s" -msgstr "Error while reading from socket." +msgstr "" #, c-format msgid "Resolver process exited without answering our request" msgstr "" -#, fuzzy, c-format +#, c-format msgid "Error converting %s to punycode: %d" msgstr "" -"Error reading %s: \n" -"%s.\n" - -#, fuzzy, c-format + +#, c-format msgid "Thread creation failure: %s" -msgstr "Authentication Failure" - -#, fuzzy +msgstr "" + msgid "Unknown reason" -msgstr "Unknown reason." +msgstr "" + +msgid "Aborting DNS lookup in Tor Proxy mode." +msgstr "" #, c-format msgid "" "Error reading %s: \n" "%s.\n" msgstr "" -"Error reading %s: \n" -"%s.\n" #, c-format msgid "" "Error writing %s: \n" "%s.\n" msgstr "" -"Error writing %s: \n" -"%s.\n" #, c-format msgid "" "Error accessing %s: \n" "%s.\n" msgstr "" -"Error accessing %s: \n" -"%s.\n" msgid "Directory is not writable." msgstr "" msgid "Cannot send a file of 0 bytes." -msgstr "Cannot send a file of 0 bytes." +msgstr "" msgid "Cannot send a directory." -msgstr "Cannot send a directory." +msgstr "" #, c-format msgid "%s is not a regular file. Cowardly refusing to overwrite it.\n" -msgstr "%s is not a regular file. Cowardly refusing to overwrite it.\n" - -#, fuzzy +msgstr "" + msgid "File is not readable." -msgstr "Chat in %s is not available." +msgstr "" #, c-format msgid "%s wants to send you %s (%s)" -msgstr "%s wants to send you %s (%s)" +msgstr "" #, c-format msgid "%s wants to send you a file" -msgstr "%s wants to send you a file" +msgstr "" #, c-format msgid "Accept file transfer request from %s?" -msgstr "Accept file transfer request from %s?" +msgstr "" #, c-format msgid "" @@ -2096,59 +1885,56 @@ "Remote host: %s\n" "Remote port: %d" msgstr "" -"A file is available for download from:\n" -"Remote host: %s\n" -"Remote port: %d" - -#, fuzzy, c-format + +#, c-format msgid "%s is offering to send file %s" -msgstr "Offering to send %s to %s" +msgstr "" #, c-format msgid "%s is not a valid filename.\n" -msgstr "%s is not a valid filename.\n" +msgstr "" #, c-format msgid "Offering to send %s to %s" -msgstr "Offering to send %s to %s" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Starting transfer of %s from %s" -msgstr "Accept file transfer request from %s?" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Transfer of file %s complete" -msgstr "Transfer of file %s complete" +msgstr "" #, c-format msgid "Transfer of file %s complete" -msgstr "Transfer of file %s complete" +msgstr "" msgid "File transfer complete" -msgstr "File transfer complete" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "You cancelled the transfer of %s" -msgstr "You cancelled the transfer of %s" +msgstr "" msgid "File transfer cancelled" -msgstr "File transfer cancelled" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "%s cancelled the transfer of %s" -msgstr "%s cancelled the transfer of %s" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "%s cancelled the file transfer" -msgstr "%s cancelled the file transfer" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "File transfer to %s failed." -msgstr "File transfer to %s aborted.\n" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "File transfer from %s failed." -msgstr "File transfer from %s aborted.\n" +msgstr "" msgid "Run the command in a terminal" msgstr "" @@ -2271,13 +2057,13 @@ msgstr "" msgid "The logger has no read function" -msgstr "The logger has no read function" +msgstr "" msgid "HTML" -msgstr "HTML" +msgstr "" msgid "Plain text" -msgstr "Plain text" +msgstr "" msgid "Old flat format" msgstr "" @@ -2286,34 +2072,30 @@ msgstr "" msgid "XML" -msgstr "XML" +msgstr "" #, c-format msgid "" "(%s) %s <AUTO-" "REPLY>: %s
\n" msgstr "" -"(%s) %s <AUTO-" -"REPLY>: %s
\n" #, c-format msgid "" "(%s) %s <AUTO-" "REPLY>: %s
\n" msgstr "" -"(%s) %s <AUTO-" -"REPLY>: %s
\n" msgid "Unable to find log path!" -msgstr "Unable to find log path!" +msgstr "" #, c-format msgid "Could not read file: %s" -msgstr "Could not read file: %s" +msgstr "" #, c-format msgid "(%s) %s : %s\n" -msgstr "(%s) %s : %s\n" +msgstr "" msgid "" "No codecs found. Install some GStreamer codecs found in GStreamer plugins " @@ -2324,9 +2106,8 @@ "No codecs left. Your codec preferences in fs-codecs.conf are too strict." msgstr "" -#, fuzzy msgid "A non-recoverable Farsight2 error has occurred." -msgstr "An unknown signon error has occurred: %s." +msgstr "" msgid "Error with your microphone" msgstr "" @@ -2334,13 +2115,12 @@ msgid "Error with your webcam" msgstr "" -#, fuzzy msgid "Conference error" -msgstr "Connection Closed" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Error creating session: %s" -msgstr "Error creating connection" +msgstr "" #, c-format msgid "You are using %s, but this plugin requires %s." @@ -2366,67 +2146,58 @@ "The required plugin %s was not found. Please install this plugin and try " "again." msgstr "" -"The required plugin %s was not found. Please install this plugin and try " -"again." - -#, fuzzy + msgid "Unable to load the plugin" -msgstr "Pidgin was unable to load your plugin." +msgstr "" #, c-format msgid "The required plugin %s was unable to load." -msgstr "The required plugin %s was unable to load." - -#, fuzzy +msgstr "" + msgid "Unable to load your plugin." -msgstr "Pidgin was unable to load your plugin." - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "%s requires %s, but it failed to unload." -msgstr "The required plugin %s was unable to load." - -#, fuzzy +msgstr "" + msgid "Autoaccept" -msgstr "Accept" - -#, fuzzy +msgstr "" + msgid "Auto-accept file transfer requests from selected users." -msgstr "Accept file transfer request from %s?" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Autoaccepted file transfer of \"%s\" from \"%s\" completed." -msgstr "Accept file transfer request from %s?" +msgstr "" msgid "Autoaccept complete" msgstr "" -#, fuzzy, c-format +#, c-format msgid "When a file-transfer request arrives from %s" -msgstr "Accept file transfer request from %s?" +msgstr "" msgid "Set Autoaccept Setting" msgstr "" msgid "_Save" -msgstr "_Save" +msgstr "" msgid "_Cancel" -msgstr "_Cancel" +msgstr "" msgid "Ask" msgstr "" -#, fuzzy msgid "Auto Accept" -msgstr "Accept" - -#, fuzzy +msgstr "" + msgid "Auto Reject" -msgstr "Auto-Reconnect" - -#, fuzzy +msgstr "" + msgid "Autoaccept File Transfers..." -msgstr "File Transfers" +msgstr "" #. XXX: Is there a better way than this? There really should be. msgid "" @@ -2434,22 +2205,24 @@ "(Please provide the full path)" msgstr "" -#, fuzzy -msgid "Automatically reject from users not in buddy list" -msgstr "Allow only the users on my buddy list" +msgid "" +"When a file-transfer request arrives from a user who is\n" +"*not* on your buddy list:" +msgstr "" msgid "" "Notify with a popup when an autoaccepted file transfer is complete\n" "(only when there's no conversation with the sender)" msgstr "" -#, fuzzy msgid "Create a new directory for each user" -msgstr "Select a conference server to query" - -#, fuzzy +msgstr "" + +msgid "Escape the filenames" +msgstr "" + msgid "Notes" -msgstr "Note" +msgstr "" msgid "Enter your notes below..." msgstr "" @@ -2465,9 +2238,8 @@ #. *< dependencies #. *< priority #. *< id -#, fuzzy msgid "Buddy Notes" -msgstr "Buddies" +msgstr "" #. *< name #. *< version @@ -2475,9 +2247,8 @@ msgstr "" #. *< summary -#, fuzzy msgid "Adds the option to store notes for buddies on your buddy list." -msgstr "Add the user to your buddy list" +msgstr "" #. *< type #. *< ui_requirement @@ -2517,42 +2288,38 @@ #. *< dependencies #. *< priority #. *< id -#, fuzzy msgid "File Control" -msgstr "Pidgin File Control" +msgstr "" #. *< name #. *< version #. * summary #. * description -#, fuzzy msgid "Allows control by entering commands in a file." -msgstr "Allows you to control Pidgin by entering commands in a file." +msgstr "" msgid "Minutes" -msgstr "Minutes" +msgstr "" #. This is a cultural reference. Dy'er Mak'er is a song by Led Zeppelin. #. If that doesn't translate well into your language, drop the 's before translating. msgid "I'dle Mak'er" -msgstr "I'dle Mak'er" +msgstr "" msgid "Set Account Idle Time" -msgstr "Set Account Idle Time" +msgstr "" msgid "_Set" -msgstr "_Set" +msgstr "" msgid "None of your accounts are idle." msgstr "" -#, fuzzy msgid "Unset Account Idle Time" -msgstr "Set Account Idle Time" - -#, fuzzy +msgstr "" + msgid "_Unset" -msgstr "_Use" +msgstr "" msgid "Set Idle Time for All Accounts" msgstr "" @@ -2560,9 +2327,8 @@ msgid "Unset Idle Time for All Idled Accounts" msgstr "" -#, fuzzy msgid "Allows you to hand-configure how long you've been idle" -msgstr "Allows you to hand-configure how long you've been idle for" +msgstr "" #. *< type #. *< ui_requirement @@ -2571,21 +2337,19 @@ #. *< priority #. *< id msgid "IPC Test Client" -msgstr "IPC Test Client" +msgstr "" #. *< name #. *< version #. * summary msgid "Test plugin IPC support, as a client." -msgstr "Test plugin IPC support, as a client." +msgstr "" #. * description msgid "" "Test plugin IPC support, as a client. This locates the server plugin and " "calls the commands registered." msgstr "" -"Test plugin IPC support, as a client. This locates the server plugin and " -"calls the commands registered." #. *< type #. *< ui_requirement @@ -2594,21 +2358,20 @@ #. *< priority #. *< id msgid "IPC Test Server" -msgstr "IPC Test Server" +msgstr "" #. *< name #. *< version #. * summary msgid "Test plugin IPC support, as a server." -msgstr "Test plugin IPC support, as a server." +msgstr "" #. * description msgid "Test plugin IPC support, as a server. This registers the IPC commands." -msgstr "Test plugin IPC support, as a server. This registers the IPC commands." - -#, fuzzy +msgstr "" + msgid "Hide Joins/Parts" -msgstr "Hide Login Errors" +msgstr "" #. Translators: Followed by an input request a number of people msgid "For rooms with more than this many people" @@ -2648,36 +2411,32 @@ msgid "(UTC)" msgstr "" -#, fuzzy msgid "User is offline." -msgstr "User is offline" - -#, fuzzy +msgstr "" + msgid "Auto-response sent:" -msgstr "Auto-Reconnect" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "%s has signed off." -msgstr "%s has signed off (%s)" +msgstr "" msgid "One or more messages may have been undeliverable." msgstr "" msgid "You were disconnected from the server." -msgstr "You were disconnected from the server." +msgstr "" msgid "" "You are currently disconnected. Messages will not be received unless you are " "logged in." msgstr "" -#, fuzzy msgid "Message could not be sent because the maximum length was exceeded." -msgstr "Message could not be sent because the user is offline:" - -#, fuzzy +msgstr "" + msgid "Message could not be sent." -msgstr "Your Yahoo! message did not get sent." +msgstr "" #. The names of IM clients are marked for translation at the request of #. translators who wanted to transliterate them. Many translators @@ -2688,16 +2447,14 @@ #. The names of IM clients are marked for translation at the request of #. translators who wanted to transliterate them. Many translators #. choose to leave them alone. Choose what's best for your language. -#, fuzzy msgid "Fire" -msgstr "Firefox" +msgstr "" #. The names of IM clients are marked for translation at the request of #. translators who wanted to transliterate them. Many translators #. choose to leave them alone. Choose what's best for your language. -#, fuzzy msgid "Messenger Plus!" -msgstr "Message from %s" +msgstr "" #. The names of IM clients are marked for translation at the request of #. translators who wanted to transliterate them. Many translators @@ -2708,9 +2465,8 @@ #. The names of IM clients are marked for translation at the request of #. translators who wanted to transliterate them. Many translators #. choose to leave them alone. Choose what's best for your language. -#, fuzzy msgid "MSN Messenger" -msgstr "Send Message" +msgstr "" #. The names of IM clients are marked for translation at the request of #. translators who wanted to transliterate them. Many translators @@ -2721,14 +2477,12 @@ #. The names of IM clients are marked for translation at the request of #. translators who wanted to transliterate them. Many translators #. choose to leave them alone. Choose what's best for your language. -#, fuzzy msgid "aMSN" -msgstr "MSN" +msgstr "" #. Add general preferences. -#, fuzzy msgid "General Log Reading Configuration" -msgstr "Tray Icon Configuration" +msgstr "" msgid "Fast size calculations" msgstr "" @@ -2737,9 +2491,8 @@ msgstr "" #. Add Log Directory preferences. -#, fuzzy msgid "Log Directory" -msgstr "_Search for:" +msgstr "" #. *< type #. *< ui_requirement @@ -2747,9 +2500,8 @@ #. *< dependencies #. *< priority #. *< id -#, fuzzy msgid "Log Reader" -msgstr "Login server" +msgstr "" #. *< name #. *< version @@ -2766,9 +2518,8 @@ "at your own risk!" msgstr "" -#, fuzzy msgid "Mono Plugin Loader" -msgstr "Tcl Plugin Loader" +msgstr "" msgid "Loads .NET plugins with Mono." msgstr "" @@ -2776,9 +2527,8 @@ msgid "Add new line in IMs" msgstr "" -#, fuzzy msgid "Add new line in Chats" -msgstr "Alias Chat" +msgstr "" #. *< magic #. *< major version @@ -2789,15 +2539,13 @@ #. *< dependencies #. *< priority #. *< id -#, fuzzy msgid "New Line" -msgstr "New window" +msgstr "" #. *< name #. *< version -#, fuzzy msgid "Prepends a newline to displayed message." -msgstr "Unable to send message." +msgstr "" #. *< summary msgid "" @@ -2822,18 +2570,17 @@ "a pounce and automatically send them when \"%s\" logs back in?" msgstr "" -#, fuzzy msgid "Offline Message" -msgstr "Offline " +msgstr "" msgid "You can edit/delete the pounce from the `Buddy Pounces' dialog" msgstr "" msgid "Yes" -msgstr "Yes" +msgstr "" msgid "No" -msgstr "No" +msgstr "" msgid "Save offline messages in pounce" msgstr "" @@ -2841,9 +2588,8 @@ msgid "Do not ask. Always save in pounce." msgstr "" -#, fuzzy msgid "One Time Password" -msgstr "Change Password" +msgstr "" #. *< type #. *< ui_requirement @@ -2874,13 +2620,13 @@ #. *< priority #. *< id msgid "Perl Plugin Loader" -msgstr "Perl Plugin Loader" +msgstr "" #. *< name #. *< version #. *< summary msgid "Provides support for loading perl plugins." -msgstr "Provides support for loading perl plugins." +msgstr "" msgid "Psychic Mode" msgstr "" @@ -2896,20 +2642,17 @@ msgid "You feel a disturbance in the force..." msgstr "" -#, fuzzy msgid "Only enable for users on the buddy list" -msgstr "Allow only the users on my buddy list" - -#, fuzzy +msgstr "" + msgid "Disable when away" -msgstr "%s went away" +msgstr "" msgid "Display notification message in conversations" msgstr "" -#, fuzzy msgid "Raise psychic conversations" -msgstr "IM Conversation Windows" +msgstr "" #. *< type #. *< ui_requirement @@ -2918,14 +2661,14 @@ #. *< priority #. *< id msgid "Signals Test" -msgstr "Signals Test" +msgstr "" #. *< name #. *< version #. * summary #. * description msgid "Test to see that all signals are working properly." -msgstr "Test to see that all signals are working properly." +msgstr "" #. *< type #. *< ui_requirement @@ -2934,14 +2677,14 @@ #. *< priority #. *< id msgid "Simple Plugin" -msgstr "Simple Plugin" +msgstr "" #. *< name #. *< version #. * summary #. * description msgid "Tests to see that most things are working." -msgstr "Tests to see that most things are working." +msgstr "" #. Scheme name msgid "X.509 Certificates" @@ -2954,14 +2697,14 @@ #. *< priority #. *< id msgid "GNUTLS" -msgstr "GNUTLS" +msgstr "" #. *< name #. *< version #. * summary #. * description msgid "Provides SSL support through GNUTLS." -msgstr "Provides SSL support through GNUTLS." +msgstr "" #. *< type #. *< ui_requirement @@ -2970,14 +2713,14 @@ #. *< priority #. *< id msgid "NSS" -msgstr "NSS" +msgstr "" #. *< name #. *< version #. * summary #. * description msgid "Provides SSL support through Mozilla NSS." -msgstr "Provides SSL support through Mozilla NSS." +msgstr "" #. *< type #. *< ui_requirement @@ -2986,47 +2729,46 @@ #. *< priority #. *< id msgid "SSL" -msgstr "SSL" +msgstr "" #. *< name #. *< version #. * summary #. * description msgid "Provides a wrapper around SSL support libraries." -msgstr "Provides a wrapper around SSL support libraries." +msgstr "" #, c-format msgid "%s is no longer away." -msgstr "%s is no longer away." +msgstr "" #, c-format msgid "%s has gone away." -msgstr "%s has gone away." +msgstr "" #, c-format msgid "%s has become idle." -msgstr "%s has become idle." +msgstr "" #, c-format msgid "%s is no longer idle." -msgstr "%s is no longer idle." - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "%s has signed on." -msgstr "%s has signed on (%s)" +msgstr "" msgid "Notify When" -msgstr "Notify When" +msgstr "" msgid "Buddy Goes _Away" -msgstr "Buddy Goes _Away" +msgstr "" msgid "Buddy Goes _Idle" -msgstr "Buddy Goes _Idle" - -#, fuzzy +msgstr "" + msgid "Buddy _Signs On/Off" -msgstr "Buddy logs in" +msgstr "" #. *< type #. *< ui_requirement @@ -3035,7 +2777,7 @@ #. *< priority #. *< id msgid "Buddy State Notification" -msgstr "Buddy State Notification" +msgstr "" #. *< name #. *< version @@ -3045,14 +2787,12 @@ "Notifies in a conversation window when a buddy goes or returns from away or " "idle." msgstr "" -"Notifies in a conversation window when a buddy goes or returns from away or " -"idle." msgid "Tcl Plugin Loader" -msgstr "Tcl Plugin Loader" +msgstr "" msgid "Provides support for loading Tcl plugins" -msgstr "Provides support for loading Tcl plugins" +msgstr "" msgid "" "Unable to detect ActiveTCL installation. If you wish to use TCL plugins, " @@ -3064,33 +2804,28 @@ "im/BonjourWindows for more information." msgstr "" -#, fuzzy msgid "Unable to listen for incoming IM connections" -msgstr "Unable to create new connection." +msgstr "" msgid "" "Unable to establish connection with the local mDNS server. Is it running?" msgstr "" -#, fuzzy msgid "First name" -msgstr "First name:" - -#, fuzzy +msgstr "" + msgid "Last name" -msgstr "Last name:" +msgstr "" #. email msgid "Email" -msgstr "Email" - -#, fuzzy +msgstr "" + msgid "AIM Account" -msgstr "Add Account" - -#, fuzzy +msgstr "" + msgid "XMPP Account" -msgstr "Account" +msgstr "" #. *< type #. *< ui_requirement @@ -3102,156 +2837,132 @@ #. *< version #. * summary #. * description -#, fuzzy msgid "Bonjour Protocol Plugin" -msgstr "Yahoo Protocol Plugin" - -#, fuzzy +msgstr "" + msgid "Purple Person" -msgstr "New Person" +msgstr "" #. Creating the options for the protocol -#, fuzzy msgid "Local Port" -msgstr "Locality" +msgstr "" msgid "Bonjour" msgstr "" -#, fuzzy, c-format +#, c-format msgid "%s has closed the conversation." -msgstr "%s has been invited to this conversation." - -#, fuzzy +msgstr "" + msgid "Unable to send the message, the conversation couldn't be started." -msgstr "Unable to send message. The message is too large." - -#, fuzzy +msgstr "" + msgid "Error communicating with local mDNSResponder." -msgstr "Error communicating with server" +msgstr "" msgid "Invalid proxy settings" -msgstr "Invalid proxy settings" +msgstr "" msgid "" "Either the host name or port number specified for your given proxy type is " "invalid." msgstr "" -"Either the host name or port number specified for your given proxy type is " -"invalid." - -#, fuzzy + msgid "Token Error" -msgstr "Unknown Error" - -#, fuzzy +msgstr "" + msgid "Unable to fetch the token.\n" -msgstr "Unable to fetch room list." - -#, fuzzy +msgstr "" + msgid "Save Buddylist..." -msgstr "Send Buddy List" +msgstr "" msgid "Your buddylist is empty, nothing was written to the file." msgstr "" -#, fuzzy msgid "Buddylist saved successfully!" -msgstr "Password changed successfully" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Couldn't write buddy list for %s to %s" -msgstr "Couldn't Import Buddy List from Server" - -#, fuzzy +msgstr "" + msgid "Couldn't load buddylist" -msgstr "Couldn't export buddy list" - -#, fuzzy +msgstr "" + msgid "Load Buddylist..." -msgstr "_Alias Buddy..." - -#, fuzzy +msgstr "" + msgid "Buddylist loaded successfully!" -msgstr "Password changed successfully" - -#, fuzzy +msgstr "" + msgid "Save buddylist..." -msgstr "Send Buddy List" - -#, fuzzy +msgstr "" + msgid "Load buddylist from file..." -msgstr "Import Buddy List from Server" +msgstr "" msgid "You must fill in all registration fields" msgstr "" -#, fuzzy msgid "Passwords do not match" -msgstr "New passwords do not match." - -#, fuzzy +msgstr "" + msgid "Unable to register new account. An unknown error occurred." -msgstr "Unable to create new connection." +msgstr "" msgid "New Gadu-Gadu Account Registered" msgstr "" -#, fuzzy msgid "Registration completed successfully!" -msgstr "Registration Successful" +msgstr "" msgid "Password" -msgstr "Password" +msgstr "" msgid "Password (again)" -msgstr "Password (again)" +msgstr "" msgid "Enter captcha text" msgstr "" -#, fuzzy msgid "Captcha" -msgstr "Save Image" - -#, fuzzy +msgstr "" + msgid "Register New Gadu-Gadu Account" -msgstr "Register New XMPP Account" +msgstr "" msgid "Please, fill in the following fields" msgstr "" msgid "City" -msgstr "City" +msgstr "" msgid "Year of birth" msgstr "" #. gender msgid "Gender" -msgstr "Gender" +msgstr "" msgid "Male or female" msgstr "" #. 0 msgid "Male" -msgstr "Male" +msgstr "" msgid "Female" -msgstr "Female" - -#, fuzzy +msgstr "" + msgid "Only online" -msgstr "Online" - -#, fuzzy +msgstr "" + msgid "Find buddies" -msgstr "Dim i_dle buddies" - -#, fuzzy +msgstr "" + msgid "Please, enter your search criteria below" -msgstr "Please enter your new password" +msgstr "" msgid "Fill in the fields." msgstr "" @@ -3259,184 +2970,166 @@ msgid "Your current password is different from the one that you specified." msgstr "" -#, fuzzy msgid "Unable to change password. Error occurred.\n" -msgstr "Unable to change Gadu-Gadu password" - -#, fuzzy +msgstr "" + msgid "Change password for the Gadu-Gadu account" -msgstr "Change password for %s" - -#, fuzzy +msgstr "" + msgid "Password was changed successfully!" -msgstr "Password changed successfully" - -#, fuzzy +msgstr "" + msgid "Current password" -msgstr "Incorrect password." - -#, fuzzy +msgstr "" + msgid "Password (retype)" -msgstr "Password sent" - -#, fuzzy +msgstr "" + msgid "Enter current token" -msgstr "%s not currently logged in." - -#, fuzzy +msgstr "" + msgid "Current token" -msgstr "Currently on" - -#, fuzzy +msgstr "" + msgid "Please, enter your current password and your new password for UIN: " -msgstr "Please enter your current password and your new password." - -#, fuzzy +msgstr "" + msgid "Change Gadu-Gadu Password" -msgstr "Unable to change Gadu-Gadu password" - -#, fuzzy, c-format +msgstr "" + +msgid "Show status to:" +msgstr "" + +msgid "All people" +msgstr "" + +msgid "Only buddies" +msgstr "" + +msgid "Change status broadcasting" +msgstr "" + +msgid "Please, select who can see your status" +msgstr "" + +#, c-format msgid "Select a chat for buddy: %s" -msgstr "Remove the chat from your buddy list" - -#, fuzzy +msgstr "" + msgid "Add to chat..." -msgstr "Add a C_hat" +msgstr "" #. 0 #. Global msgid "Available" -msgstr "Available" +msgstr "" #. 2 msgid "Chatty" -msgstr "Chatty" +msgstr "" #. 3 msgid "Do Not Disturb" -msgstr "Do Not Disturb" +msgstr "" #. 1 #. get_yahoo_status_from_purple_status() returns YAHOO_STATUS_CUSTOM for #. * the generic away state (YAHOO_STATUS_TYPE_AWAY) with no message #. Away stuff msgid "Away" -msgstr "Away" +msgstr "" msgid "UIN" -msgstr "UIN" +msgstr "" #. first name -#. purple_notify_user_info_add_pair( info, _( "Hidden Number" ), profile->hidden ? _( "Yes" ) : _( "No" ) ); #. optional information -#. purple_notify_user_info_add_pair( info, _( "Title" ), profile->title ); msgid "First Name" -msgstr "First Name" +msgstr "" msgid "Birth Year" -msgstr "Birth Year" - -#, fuzzy +msgstr "" + msgid "Unable to display the search results." -msgstr "Unable to invite user (%s)." +msgstr "" msgid "Gadu-Gadu Public Directory" msgstr "" -#, fuzzy msgid "Search results" -msgstr "Search Results" - -#, fuzzy +msgstr "" + msgid "No matching users found" -msgstr "Non-matching Hosts" - -#, fuzzy +msgstr "" + msgid "There are no users matching your search criteria." -msgstr "Please enter your new password" - -#, fuzzy +msgstr "" + msgid "Unable to read from socket" -msgstr "Unable to read socket" - -#, fuzzy +msgstr "" + msgid "Buddy list downloaded" -msgstr "Buddy is idle:" - -#, fuzzy +msgstr "" + msgid "Your buddy list was downloaded from the server." -msgstr "You were disconnected from the server." - -#, fuzzy +msgstr "" + msgid "Buddy list uploaded" -msgstr "Buddy Display" - -#, fuzzy +msgstr "" + msgid "Your buddy list was stored on the server." -msgstr "There is no Buddy List stored on the Gadu-Gadu server." +msgstr "" #. 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). -#, fuzzy msgid "Connected" -msgstr "Connect" +msgstr "" msgid "Connection failed" -msgstr "Connection failed" - -#, fuzzy +msgstr "" + msgid "Add to chat" -msgstr "Add Chat" - -#, fuzzy +msgstr "" + msgid "Chat _name:" -msgstr "Last name:" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Unable to resolve hostname '%s': %s" -msgstr "Unable to ping server" +msgstr "" #. 1. connect to server #. connect to the server msgid "Connecting" -msgstr "Connecting" - -#, fuzzy +msgstr "" + msgid "Chat error" -msgstr "Read error" - -#, fuzzy +msgstr "" + msgid "This chat name is already in use" -msgstr "That file already exists" - -#, fuzzy +msgstr "" + msgid "Not connected to the server" -msgstr "You were disconnected from the server." - -#, fuzzy +msgstr "" + msgid "Find buddies..." -msgstr "Dim i_dle buddies" - -#, fuzzy +msgstr "" + msgid "Change password..." -msgstr "Change Password..." - -#, fuzzy +msgstr "" + msgid "Upload buddylist to Server" -msgstr "Export Buddy List to Server" - -#, fuzzy +msgstr "" + msgid "Download buddylist from Server" -msgstr "Delete Buddy List from Server" - -#, fuzzy +msgstr "" + msgid "Delete buddylist from Server" -msgstr "Delete Buddy List from Server" - -#, fuzzy +msgstr "" + msgid "Save buddylist to file..." -msgstr "Send Buddy List" +msgstr "" #. magic #. major_version @@ -3450,96 +3143,103 @@ #. name #. version msgid "Gadu-Gadu Protocol Plugin" -msgstr "Gadu-Gadu Protocol Plugin" +msgstr "" #. summary msgid "Polish popular IM" msgstr "" -#, fuzzy msgid "Gadu-Gadu User" -msgstr "Gadu-Gadu Search Engine" - -#, fuzzy +msgstr "" + msgid "GG server" -msgstr "Set User Info..." +msgstr "" + +msgid "Don't use encryption" +msgstr "" + +msgid "Use encryption if available" +msgstr "" + +#. TODO +msgid "Require encryption" +msgstr "" + +msgid "Connection security" +msgstr "" #, c-format msgid "Unknown command: %s" -msgstr "Unknown command: %s" +msgstr "" #, c-format msgid "current topic is: %s" -msgstr "current topic is: %s" +msgstr "" msgid "No topic is set" -msgstr "No topic is set" - -#, fuzzy +msgstr "" + msgid "File Transfer Failed" -msgstr "File transfer cancelled" - -#, fuzzy +msgstr "" + msgid "Unable to open a listening port." -msgstr "Pidgin could not open a listening port." +msgstr "" msgid "Error displaying MOTD" -msgstr "Error displaying MOTD" +msgstr "" msgid "No MOTD available" -msgstr "No MOTD available" +msgstr "" msgid "There is no MOTD associated with this connection." -msgstr "There is no MOTD associated with this connection." +msgstr "" #, c-format msgid "MOTD for %s" -msgstr "MOTD for %s" +msgstr "" #. #. * TODO: Handle this better. Probably requires a PurpleBOSHConnection #. * buffer that stores what is "being sent" until the #. * PurpleHTTPConnection reports it is fully sent. #. -#. TODO: what to do here - do we really have to disconnect? #. TODO: do we really want to disconnect on a failure to write? -#, fuzzy, c-format +#, c-format msgid "Lost connection with server: %s" -msgstr "You were disconnected from the server." +msgstr "" msgid "View MOTD" -msgstr "View MOTD" +msgstr "" msgid "_Channel:" -msgstr "_Channel:" +msgstr "" msgid "_Password:" -msgstr "_Password:" - -#, fuzzy +msgstr "" + msgid "IRC nick and server may not contain whitespace" -msgstr "IRC nicks may not contain whitespace" +msgstr "" msgid "SSL support unavailable" -msgstr "SSL support unavailable" +msgstr "" msgid "Unable to connect" -msgstr "Unable to connect" +msgstr "" #. this is a regular connect, error out -#, fuzzy, c-format +#, c-format msgid "Unable to connect: %s" -msgstr "Unable to connect to server." - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Server closed the connection" -msgstr "Error creating connection" +msgstr "" msgid "Users" -msgstr "Users" +msgstr "" msgid "Topic" -msgstr "Topic" +msgstr "" #. *< type #. *< ui_requirement @@ -3550,383 +3250,335 @@ #. *< name #. *< version msgid "IRC Protocol Plugin" -msgstr "IRC Protocol Plugin" +msgstr "" #. * summary msgid "The IRC Protocol Plugin that Sucks Less" -msgstr "The IRC Protocol Plugin that Sucks Less" +msgstr "" #. host to connect to msgid "Server" -msgstr "Server" +msgstr "" #. port to connect to msgid "Port" -msgstr "Port" +msgstr "" msgid "Encodings" -msgstr "Encodings" +msgstr "" msgid "Auto-detect incoming UTF-8" msgstr "" msgid "Real name" -msgstr "Real name" +msgstr "" #. #. option = purple_account_option_string_new(_("Quit message"), "quitmsg", IRC_DEFAULT_QUIT); #. prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); #. -#, fuzzy msgid "Use SSL" -msgstr "SSL" +msgstr "" msgid "Bad mode" -msgstr "Bad mode" +msgstr "" #, c-format msgid "Ban on %s by %s, set %s ago" msgstr "" -#, fuzzy, c-format +#, c-format msgid "Ban on %s" -msgstr "Cannot join %s:" - -#, fuzzy +msgstr "" + msgid "End of ban list" -msgstr "Not on list" +msgstr "" #, c-format msgid "You are banned from %s." -msgstr "You are banned from %s." +msgstr "" msgid "Banned" -msgstr "Banned" +msgstr "" #, c-format msgid "Cannot ban %s: banlist is full" -msgstr "Cannot ban %s: banlist is full" +msgstr "" msgid " (ircop)" -msgstr " (ircop)" +msgstr "" msgid " (identified)" -msgstr " (identified)" +msgstr "" msgid "Nick" -msgstr "Nick" +msgstr "" msgid "Currently on" -msgstr "Currently on" - -#, fuzzy +msgstr "" + msgid "Idle for" -msgstr "Idle" +msgstr "" msgid "Online since" -msgstr "Online since" - -#, fuzzy +msgstr "" + msgid "Defining adjective:" -msgstr "
Defining adjective: Glorious
" +msgstr "" msgid "Glorious" msgstr "" #, c-format msgid "%s has changed the topic to: %s" -msgstr "%s has changed the topic to: %s" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "%s has cleared the topic." -msgstr "%s has changed the topic to: %s" +msgstr "" #, c-format msgid "The topic for %s is: %s" -msgstr "The topic for %s is: %s" +msgstr "" #, c-format msgid "Unknown message '%s'" -msgstr "Unknown message '%s'" +msgstr "" msgid "Unknown message" -msgstr "Unknown message" - -#, fuzzy +msgstr "" + msgid "The IRC server received a message it did not understand." -msgstr "Pidgin has sent a message the IRC server did not understand." +msgstr "" #, c-format msgid "Users on %s: %s" -msgstr "Users on %s: %s" +msgstr "" msgid "Time Response" -msgstr "Time Response" +msgstr "" msgid "The IRC server's local time is:" -msgstr "The IRC server's local time is:" +msgstr "" msgid "No such channel" -msgstr "No such channel" +msgstr "" #. does this happen? msgid "no such channel" -msgstr "no such channel" +msgstr "" msgid "User is not logged in" -msgstr "User is not logged in" +msgstr "" msgid "No such nick or channel" -msgstr "No such nick or channel" +msgstr "" msgid "Could not send" -msgstr "Could not send" +msgstr "" #, c-format msgid "Joining %s requires an invitation." -msgstr "Joining %s requires an invitation." +msgstr "" msgid "Invitation only" -msgstr "Invitation only" +msgstr "" #, c-format msgid "You have been kicked by %s: (%s)" -msgstr "You have been kicked by %s: (%s)" +msgstr "" #. Remove user from channel #, c-format msgid "Kicked by %s (%s)" -msgstr "Kicked by %s (%s)" +msgstr "" #, c-format msgid "mode (%s %s) by %s" -msgstr "mode (%s %s) by %s" - -#, fuzzy +msgstr "" + msgid "Invalid nickname" -msgstr "Invalid Username" - -#, fuzzy +msgstr "" + msgid "" "Your selected nickname was rejected by the server. It probably contains " "invalid characters." msgstr "" -"Your selected account name was rejected by the server. It probably contains " -"invalid characters." msgid "" "Your selected account name was rejected by the server. It probably contains " "invalid characters." msgstr "" -"Your selected account name was rejected by the server. It probably contains " -"invalid characters." #. We only want to do the following dance if the connection #. has not been successfully completed. If it has, just #. notify the user that their /nick command didn't go. -#, fuzzy, c-format +#, c-format msgid "The nickname \"%s\" is already being used." -msgstr "That file already exists" - -#, fuzzy +msgstr "" + msgid "Nickname in use" -msgstr "Nickname" +msgstr "" msgid "Cannot change nick" -msgstr "Cannot change nick" +msgstr "" msgid "Could not change nick" -msgstr "Could not change nick" +msgstr "" #, c-format msgid "You have parted the channel%s%s" -msgstr "You have parted the channel%s%s" +msgstr "" msgid "Error: invalid PONG from server" -msgstr "Error: invalid PONG from server" +msgstr "" #, c-format msgid "PING reply -- Lag: %lu seconds" -msgstr "PING reply -- Lag: %lu seconds" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Cannot join %s: Registration is required." -msgstr "Registration Required" +msgstr "" msgid "Cannot join channel" -msgstr "Cannot join channel" - -#, fuzzy +msgstr "" + msgid "Nick or channel is temporarily unavailable." -msgstr "The service is temporarily unavailable." +msgstr "" #, c-format msgid "Wallops from %s" -msgstr "Wallops from %s" +msgstr "" msgid "action <action to perform>: Perform an action." -msgstr "action <action to perform>: Perform an action." +msgstr "" + +msgid "authserv: Send a command to authserv" +msgstr "" msgid "" "away [message]: Set an away message, or use no message to return from being " "away." msgstr "" -"away [message]: Set an away message, or use no message to return from being " -"away." msgid "ctcp : sends ctcp msg to nick." msgstr "" -#, fuzzy msgid "chanserv: Send a command to chanserv" -msgstr "quote [...]: Send a raw command to the server." +msgstr "" msgid "" "deop <nick1> [nick2] ...: Remove channel operator status from " "someone. You must be a channel operator to do this." msgstr "" -"deop <nick1> [nick2] ...: Remove channel operator status from " -"someone. You must be a channel operator to do this." msgid "" "devoice <nick1> [nick2] ...: Remove channel voice status from " "someone, preventing them from speaking if the channel is moderated (+m). You " "must be a channel operator to do this." msgstr "" -"devoice <nick1> [nick2] ...: Remove channel voice status from " -"someone, preventing them from speaking if the channel is moderated (+m). You " -"must be a channel operator to do this." msgid "" "invite <nick> [room]: Invite someone to join you in the specified " "channel, or the current channel." msgstr "" -"invite <nick> [room]: Invite someone to join you in the specified " -"channel, or the current channel." msgid "" "j <room1>[,room2][,...] [key1[,key2][,...]]: Enter one or more " "channels, optionally providing a channel key for each if needed." msgstr "" -"j <room1>[,room2][,...] [key1[,key2][,...]]: Enter one or more " -"channels, optionally providing a channel key for each if needed." msgid "" "join <room1>[,room2][,...] [key1[,key2][,...]]: Enter one or more " "channels, optionally providing a channel key for each if needed." msgstr "" -"join <room1>[,room2][,...] [key1[,key2][,...]]: Enter one or more " -"channels, optionally providing a channel key for each if needed." msgid "" "kick <nick> [message]: Remove someone from a channel. You must be a " "channel operator to do this." msgstr "" -"kick <nick> [message]: Remove someone from a channel. You must be a " -"channel operator to do this." msgid "" "list: Display a list of chat rooms on the network. Warning, some servers " "may disconnect you upon doing this." msgstr "" -"list: Display a list of chat rooms on the network. Warning, some servers " -"may disconnect you upon doing this." msgid "me <action to perform>: Perform an action." -msgstr "me <action to perform>: Perform an action." - -#, fuzzy +msgstr "" + msgid "memoserv: Send a command to memoserv" -msgstr "quote [...]: Send a raw command to the server." +msgstr "" msgid "" "mode <+|-><A-Za-z> <nick|channel>: Set or unset a channel " "or user mode." msgstr "" -"mode <+|-><A-Za-z> <nick|channel>: Set or unset a channel " -"or user mode." msgid "" "msg <nick> <message>: Send a private message to a user (as " "opposed to a channel)." msgstr "" -"msg <nick> <message>: Send a private message to a user (as " -"opposed to a channel)." msgid "names [channel]: List the users currently in a channel." -msgstr "names [channel]: List the users currently in a channel." +msgstr "" msgid "nick <new nickname>: Change your nickname." -msgstr "nick <new nickname>: Change your nickname." - -#, fuzzy +msgstr "" + msgid "nickserv: Send a command to nickserv" -msgstr "quote [...]: Send a raw command to the server." - -#, fuzzy +msgstr "" + msgid "notice <target<: Send a notice to a user or channel." -msgstr "me <action>: Send an IRC style action to a buddy or chat." +msgstr "" msgid "" "op <nick1> [nick2] ...: Grant channel operator status to someone. You " "must be a channel operator to do this." msgstr "" -"op <nick1> [nick2] ...: Grant channel operator status to someone. You " -"must be a channel operator to do this." msgid "" "operwall <message>: If you don't know what this is, you probably " "can't use it." msgstr "" -"operwall <message>: If you don't know what this is, you probably " -"can't use it." - -#, fuzzy + msgid "operserv: Send a command to operserv" -msgstr "quote [...]: Send a raw command to the server." +msgstr "" msgid "" "part [room] [message]: Leave the current channel, or a specified channel, " "with an optional message." msgstr "" -"part [room] [message]: Leave the current channel, or a specified channel, " -"with an optional message." msgid "" "ping [nick]: Asks how much lag a user (or the server if no user specified) " "has." msgstr "" -"ping [nick]: Asks how much lag a user (or the server if no user specified) " -"has." msgid "" "query <nick> <message>: Send a private message to a user (as " "opposed to a channel)." msgstr "" -"query <nick> <message>: Send a private message to a user (as " -"opposed to a channel)." msgid "quit [message]: Disconnect from the server, with an optional message." -msgstr "quit [message]: Disconnect from the server, with an optional message." +msgstr "" msgid "quote [...]: Send a raw command to the server." -msgstr "quote [...]: Send a raw command to the server." +msgstr "" msgid "" "remove <nick> [message]: Remove someone from a room. You must be a " "channel operator to do this." msgstr "" -"remove <nick> [message]: Remove someone from a room. You must be a " -"channel operator to do this." msgid "time: Displays the current local time at the IRC server." -msgstr "time: Displays the current local time at the IRC server." +msgstr "" msgid "topic [new topic]: View or change the channel topic." -msgstr "topic [new topic]: View or change the channel topic." +msgstr "" msgid "umode <+|-><A-Za-z>: Set or unset a user mode." -msgstr "umode <+|-><A-Za-z>: Set or unset a user mode." +msgstr "" msgid "version [nick]: send CTCP VERSION request to a user" msgstr "" @@ -3935,105 +3587,92 @@ "voice <nick1> [nick2] ...: Grant channel voice status to someone. You " "must be a channel operator to do this." msgstr "" -"voice <nick1> [nick2] ...: Grant channel voice status to someone. You " -"must be a channel operator to do this." msgid "" "wallops <message>: If you don't know what this is, you probably can't " "use it." msgstr "" -"wallops <message>: If you don't know what this is, you probably can't " -"use it." msgid "whois [server] <nick>: Get information on a user." -msgstr "whois [server] <nick>: Get information about a user." - -#, fuzzy +msgstr "" + msgid "whowas <nick>: Get information on a user that has logged off." -msgstr "whois [server] <nick>: Get information about a user." +msgstr "" #, c-format msgid "Reply time from %s: %lu seconds" -msgstr "Reply time from %s: %lu seconds" +msgstr "" msgid "PONG" -msgstr "PONG" +msgstr "" msgid "CTCP PING reply" -msgstr "CTCP PING reply" +msgstr "" msgid "Disconnected." -msgstr "Disconnected." +msgstr "" msgid "Unknown Error" -msgstr "Unknown Error" - -#, fuzzy +msgstr "" + msgid "Ad-Hoc Command Failed" -msgstr "Command disabled" - -#, fuzzy +msgstr "" + msgid "execute" -msgstr "Not expected" +msgstr "" msgid "Server requires plaintext authentication over an unencrypted stream" -msgstr "Server requires plaintext authentication over an unencrypted stream" - -#. This should never happen! -#, fuzzy +msgstr "" + +#. This happens when the server sends back jibberish +#. * in the "additional data with success" case. +#. * Seen with Wildfire 3.0.1. +#. msgid "Invalid response from server" -msgstr "Invalid response from server." +msgstr "" msgid "Server does not use any supported authentication method" -msgstr "Server does not use any supported authentication method" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "" "%s requires plaintext authentication over an unencrypted connection. Allow " "this and continue authentication?" msgstr "" -"This server requires plaintext authentication over an unencrypted " -"connection. Allow this and continue authentication?" msgid "Plaintext Authentication" -msgstr "Plaintext Authentication" +msgstr "" msgid "You require encryption, but it is not available on this server." msgstr "" msgid "Invalid challenge from server" -msgstr "Invalid challenge from server" +msgstr "" msgid "Server thinks authentication is complete, but client does not" msgstr "" -#, fuzzy msgid "Server may require plaintext authentication over an unencrypted stream" -msgstr "Server requires plaintext authentication over an unencrypted stream" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "" "%s may require plaintext authentication over an unencrypted connection. " "Allow this and continue authentication?" msgstr "" -"This server requires plaintext authentication over an unencrypted " -"connection. Allow this and continue authentication?" - -#, fuzzy + msgid "SASL authentication failed" -msgstr "Authentication failed" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "SASL error: %s" -msgstr "Read error" - -#, fuzzy +msgstr "" + msgid "Invalid Encoding" -msgstr "Finalizing connection" - -#, fuzzy +msgstr "" + msgid "Unsupported Extension" -msgstr "Unsupported Version" +msgstr "" msgid "" "Unexpected response from the server. This may indicate a possible MITM " @@ -4045,77 +3684,66 @@ "it. This indicates a likely MITM attack" msgstr "" -#, fuzzy msgid "Server does not support channel binding" -msgstr "Server does not use any supported authentication method" - -#, fuzzy +msgstr "" + msgid "Unsupported channel binding method" -msgstr "Unsupported Encoding" +msgstr "" msgid "User not found" -msgstr "User not found" - -#, fuzzy +msgstr "" + msgid "Invalid Username Encoding" -msgstr "Invalid Username" +msgstr "" msgid "Resource Constraint" -msgstr "Resource Constraint" - -#, fuzzy +msgstr "" + msgid "Unable to canonicalize username" -msgstr "Unable to configure" - -#, fuzzy +msgstr "" + msgid "Unable to canonicalize password" -msgstr "Pidgin could not open a listening port." - -#, fuzzy +msgstr "" + msgid "Malicious challenge from server" -msgstr "Invalid challenge from server" - -#, fuzzy +msgstr "" + msgid "Unexpected response from server" -msgstr "Invalid response from server." +msgstr "" msgid "The BOSH connection manager terminated your session." msgstr "" -#, fuzzy msgid "No session ID given" -msgstr "No reason given." - -#, fuzzy +msgstr "" + msgid "Unsupported version of BOSH protocol" -msgstr "Unsupported Version" - -#, fuzzy +msgstr "" + msgid "Unable to establish a connection with the server" -msgstr "Unable to make SSL connection to server." - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Unable to establish a connection with the server: %s" -msgstr "Unable to make SSL connection to server." - -#, fuzzy +msgstr "" + msgid "Unable to establish SSL connection" -msgstr "Unable to create new connection." +msgstr "" msgid "Full Name" -msgstr "Full Name" +msgstr "" msgid "Family Name" -msgstr "Family Name" +msgstr "" msgid "Given Name" -msgstr "Given Name" +msgstr "" msgid "URL" -msgstr "URL" +msgstr "" msgid "Street Address" -msgstr "Street Address" +msgstr "" #. #. * EXTADD is correct, EXTADR is generated by other @@ -4123,143 +3751,131 @@ #. * EXTADR. #. msgid "Extended Address" -msgstr "Extended Address" +msgstr "" msgid "Locality" -msgstr "Locality" +msgstr "" msgid "Region" -msgstr "Region" +msgstr "" msgid "Postal Code" -msgstr "Postal Code" - -#. purple_notify_user_info_add_pair( info, _( "Email" ), profile->email ); +msgstr "" + msgid "Country" -msgstr "Country" +msgstr "" #. lots of clients (including purple) do this, but it's #. * out of spec msgid "Telephone" -msgstr "Telephone" +msgstr "" msgid "Organization Name" -msgstr "Organization Name" +msgstr "" msgid "Organization Unit" -msgstr "Organization Unit" +msgstr "" msgid "Job Title" -msgstr "Job Title" +msgstr "" msgid "Role" -msgstr "Role" +msgstr "" #. birthday #. birthday (required) msgid "Birthday" -msgstr "Birthday" +msgstr "" msgid "Description" -msgstr "Description" +msgstr "" msgid "Edit XMPP vCard" -msgstr "Edit XMPP vCard" +msgstr "" msgid "" "All items below are optional. Enter only the information with which you feel " "comfortable." msgstr "" -"All items below are optional. Enter only the information with which you feel " -"comfortable." - -#, fuzzy + msgid "Client" -msgstr "City" - -#, fuzzy +msgstr "" + msgid "Operating System" -msgstr "Hide Operating System" - -#, fuzzy +msgstr "" + msgid "Local Time" -msgstr "Local Users" - -#, fuzzy +msgstr "" + msgid "Priority" -msgstr "Port" +msgstr "" msgid "Resource" -msgstr "Resource" - -#, fuzzy +msgstr "" + msgid "Uptime" -msgstr "Last Updated" - -#, fuzzy +msgstr "" + msgid "Logged Off" -msgstr "Logged out" +msgstr "" #, c-format msgid "%s ago" msgstr "" msgid "Middle Name" -msgstr "Middle Name" +msgstr "" msgid "Address" -msgstr "Address" +msgstr "" msgid "P.O. Box" -msgstr "P.O. Box" +msgstr "" msgid "Photo" -msgstr "Photo" +msgstr "" msgid "Logo" -msgstr "Logo" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "" "%s will no longer be able to see your status updates. Do you want to " "continue?" msgstr "" -"You are about to remove %s from your buddy list. Do you want to continue?" msgid "Cancel Presence Notification" -msgstr "Cancel Presence Notification" +msgstr "" msgid "Un-hide From" -msgstr "Un-hide From" +msgstr "" msgid "Temporarily Hide From" -msgstr "Temporarily Hide From" +msgstr "" msgid "(Re-)Request authorization" -msgstr "(Re-)Request authorization" +msgstr "" #. shouldn't this just happen automatically when the buddy is #. removed? msgid "Unsubscribe" -msgstr "Unsubscribe" +msgstr "" msgid "Initiate _Chat" -msgstr "Initiate _Chat" - -#, fuzzy +msgstr "" + msgid "Log In" -msgstr "Login" - -#, fuzzy +msgstr "" + msgid "Log Out" -msgstr "Logged out" +msgstr "" msgid "JID" msgstr "" #. last name msgid "Last Name" -msgstr "Last Name" +msgstr "" msgid "The following are the results of your search" msgstr "" @@ -4270,140 +3886,126 @@ "Each field supports wild card searches (%)" msgstr "" -#, fuzzy msgid "Directory Query Failed" -msgstr "Direct Connect failed" - -#, fuzzy +msgstr "" + msgid "Could not query the directory server." -msgstr "Could not start the file transfer" +msgstr "" #. Try to translate the message (see static message #. list in jabber_user_dir_comments[]) -#, fuzzy, c-format +#, c-format msgid "Server Instructions: %s" -msgstr "Server Information" +msgstr "" msgid "Fill in one or more fields to search for any matching XMPP users." msgstr "" msgid "Email Address" -msgstr "Email Address" - -#, fuzzy +msgstr "" + msgid "Search for XMPP users" -msgstr "Search for a buddy by email address" +msgstr "" #. "Search" msgid "Search" -msgstr "Search" - -#, fuzzy +msgstr "" + msgid "Invalid Directory" -msgstr "Invalid error" - -#, fuzzy +msgstr "" + msgid "Enter a User Directory" -msgstr "Cannot send a directory." - -#, fuzzy +msgstr "" + msgid "Select a user directory to search" -msgstr "Select a conference server to query" - -#, fuzzy +msgstr "" + msgid "Search Directory" -msgstr "_Search for:" +msgstr "" msgid "_Room:" -msgstr "_Room:" +msgstr "" msgid "_Server:" -msgstr "_Server:" +msgstr "" msgid "_Handle:" -msgstr "_Handle:" +msgstr "" #, c-format msgid "%s is not a valid room name" -msgstr "%s is not a valid room name" +msgstr "" msgid "Invalid Room Name" -msgstr "Invalid Room Name" +msgstr "" #, c-format msgid "%s is not a valid server name" -msgstr "%s is not a valid server name" +msgstr "" msgid "Invalid Server Name" -msgstr "Invalid Server Name" +msgstr "" #, c-format msgid "%s is not a valid room handle" -msgstr "%s is not a valid room handle" +msgstr "" msgid "Invalid Room Handle" -msgstr "Invalid Room Handle" +msgstr "" msgid "Configuration error" -msgstr "Configuration error" +msgstr "" msgid "Unable to configure" -msgstr "Unable to configure" +msgstr "" msgid "Room Configuration Error" -msgstr "Room Configuration Error" +msgstr "" msgid "This room is not capable of being configured" -msgstr "This room is not capable of being configured" +msgstr "" msgid "Registration error" -msgstr "Registration error" +msgstr "" msgid "Nick changing not supported in non-MUC chatrooms" -msgstr "Nick changing not supported in non-MUC chatrooms" - -#, fuzzy +msgstr "" + msgid "Error retrieving room list" -msgstr "Error retreiving roomlist" +msgstr "" msgid "Invalid Server" -msgstr "Invalid Server" +msgstr "" msgid "Enter a Conference Server" -msgstr "Enter a Conference Server" +msgstr "" msgid "Select a conference server to query" -msgstr "Select a conference server to query" +msgstr "" msgid "Find Rooms" -msgstr "Find Rooms" - -#, fuzzy +msgstr "" + msgid "Affiliations:" -msgstr "Alias:" - -#, fuzzy +msgstr "" + msgid "No users found" -msgstr "Non-matching Hosts" - -#, fuzzy +msgstr "" + msgid "Roles:" -msgstr "Role" - -#, fuzzy +msgstr "" + msgid "Server requires TLS/SSL, but no TLS/SSL support was found." -msgstr "Server requires TLS/SSL for login. No TLS/SSL support found." - -#, fuzzy +msgstr "" + msgid "You require encryption, but no TLS/SSL support was found." -msgstr "Server requires TLS/SSL for login. No TLS/SSL support found." - -#, fuzzy +msgstr "" + msgid "Ping timed out" -msgstr "Plain text" +msgstr "" msgid "Invalid XMPP ID" -msgstr "Invalid XMPP ID" +msgstr "" msgid "Invalid XMPP ID. Username portion must be set." msgstr "" @@ -4411,151 +4013,138 @@ msgid "Invalid XMPP ID. Domain must be set." msgstr "" -#, fuzzy msgid "Malformed BOSH URL" -msgstr "Failed to connect to server." +msgstr "" #, c-format msgid "Registration of %s@%s successful" -msgstr "Registration of %s@%s successful" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Registration to %s successful" -msgstr "Registration of %s@%s successful" +msgstr "" msgid "Registration Successful" -msgstr "Registration Successful" +msgstr "" msgid "Registration Failed" -msgstr "Registration Failed" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Registration from %s successfully removed" -msgstr "Registration of %s@%s successful" - -#, fuzzy +msgstr "" + msgid "Unregistration Successful" -msgstr "Registration Successful" - -#, fuzzy +msgstr "" + msgid "Unregistration Failed" -msgstr "Registration Failed" +msgstr "" msgid "State" -msgstr "Province/Territory" - -#, fuzzy +msgstr "" + msgid "Postal code" -msgstr "Postal Code" +msgstr "" msgid "Phone" -msgstr "Phone" +msgstr "" msgid "Date" -msgstr "Date" +msgstr "" msgid "Already Registered" -msgstr "Already Registered" - -#, fuzzy +msgstr "" + msgid "Unregister" -msgstr "Register" - -#, fuzzy +msgstr "" + msgid "" "Please fill out the information below to change your account registration." -msgstr "Please fill out the information below to register your new account." +msgstr "" msgid "Please fill out the information below to register your new account." -msgstr "Please fill out the information below to register your new account." +msgstr "" msgid "Register New XMPP Account" -msgstr "Register New XMPP Account" +msgstr "" msgid "Register" -msgstr "Register" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Change Account Registration at %s" -msgstr "Change user information for %s" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Register New Account at %s" -msgstr "Register New XMPP Account" - -#, fuzzy +msgstr "" + msgid "Change Registration" -msgstr "Registration Error" - -#, fuzzy +msgstr "" + msgid "Error unregistering account" -msgstr "Error Changing Account Info" +msgstr "" msgid "Account successfully unregistered" msgstr "" msgid "Initializing Stream" -msgstr "Initializing Stream" - -#, fuzzy +msgstr "" + msgid "Initializing SSL/TLS" -msgstr "Initializing Stream" +msgstr "" msgid "Authenticating" -msgstr "Authenticating" +msgstr "" msgid "Re-initializing Stream" -msgstr "Re-initializing Stream" +msgstr "" msgid "Server doesn't support blocking" msgstr "" msgid "Not Authorized" -msgstr "Not Authorized" +msgstr "" msgid "Mood" -msgstr "Mood" +msgstr "" msgid "Now Listening" msgstr "" msgid "Both" -msgstr "Both" +msgstr "" msgid "From (To pending)" -msgstr "From (To pending)" +msgstr "" msgid "From" -msgstr "From" +msgstr "" msgid "To" -msgstr "To" +msgstr "" msgid "None (To pending)" -msgstr "None (To pending)" +msgstr "" msgid "None" -msgstr "None" +msgstr "" #. subscription type msgid "Subscription" -msgstr "Subscription" - -#, fuzzy +msgstr "" + msgid "Mood Text" -msgstr "Mood" - -#, fuzzy +msgstr "" + msgid "Allow Buzz" -msgstr "Allow" - -#, fuzzy +msgstr "" + msgid "Mood Name" -msgstr "Middle Name" - -#, fuzzy +msgstr "" + msgid "Mood Comment" -msgstr "Buddy Comment" +msgstr "" #. primitive #. ID @@ -4566,9 +4155,8 @@ msgid "Tune Artist" msgstr "" -#, fuzzy msgid "Tune Title" -msgstr "Title" +msgstr "" msgid "Tune Album" msgstr "" @@ -4576,16 +4164,14 @@ msgid "Tune Genre" msgstr "" -#, fuzzy msgid "Tune Comment" -msgstr "Buddy Comment" +msgstr "" msgid "Tune Track" msgstr "" -#, fuzzy msgid "Tune Time" -msgstr "Time" +msgstr "" msgid "Tune Year" msgstr "" @@ -4594,286 +4180,277 @@ msgstr "" msgid "Password Changed" -msgstr "Password Changed" +msgstr "" msgid "Your password has been changed." -msgstr "Your password has been changed." +msgstr "" msgid "Error changing password" -msgstr "Error changing password" +msgstr "" msgid "Change XMPP Password" -msgstr "Change XMPP Password" +msgstr "" msgid "Please enter your new password" -msgstr "Please enter your new password" +msgstr "" msgid "Set User Info..." -msgstr "Set User Info..." +msgstr "" #. if (js->protocol_options & CHANGE_PASSWORD) { msgid "Change Password..." -msgstr "Change Password..." +msgstr "" #. } -#, fuzzy msgid "Search for Users..." -msgstr "_Search for:" +msgstr "" msgid "Bad Request" -msgstr "Bad Request" +msgstr "" msgid "Conflict" -msgstr "Conflict" +msgstr "" msgid "Feature Not Implemented" -msgstr "Feature Not Implemented" +msgstr "" msgid "Forbidden" -msgstr "Forbidden" +msgstr "" msgid "Gone" -msgstr "Gone" +msgstr "" msgid "Internal Server Error" -msgstr "Internal Server Error" +msgstr "" msgid "Item Not Found" -msgstr "Item Not Found" +msgstr "" msgid "Malformed XMPP ID" -msgstr "Malformed XMPP ID" +msgstr "" msgid "Not Acceptable" -msgstr "Not Acceptable" +msgstr "" msgid "Not Allowed" -msgstr "Not Allowed" +msgstr "" msgid "Payment Required" -msgstr "Payment Required" +msgstr "" msgid "Recipient Unavailable" -msgstr "Recipient Unavailable" +msgstr "" msgid "Registration Required" -msgstr "Registration Required" +msgstr "" msgid "Remote Server Not Found" -msgstr "Remote Server Not Found" +msgstr "" msgid "Remote Server Timeout" -msgstr "Remote Server Timeout" +msgstr "" msgid "Server Overloaded" -msgstr "Server Overloaded" +msgstr "" msgid "Service Unavailable" -msgstr "Service Unavailable" +msgstr "" msgid "Subscription Required" -msgstr "Subscription Required" +msgstr "" msgid "Unexpected Request" -msgstr "Unexpected Request" +msgstr "" msgid "Authorization Aborted" -msgstr "Authorization Aborted" +msgstr "" msgid "Incorrect encoding in authorization" -msgstr "Incorrect encoding in authorization" +msgstr "" msgid "Invalid authzid" -msgstr "Invalid authzid" +msgstr "" msgid "Invalid Authorization Mechanism" -msgstr "Invalid Authorization Mechanism" +msgstr "" msgid "Authorization mechanism too weak" -msgstr "Authorization mechanism too weak" +msgstr "" msgid "Temporary Authentication Failure" -msgstr "Temporary Authentication Failure" +msgstr "" msgid "Authentication Failure" -msgstr "Authentication Failure" +msgstr "" msgid "Bad Format" -msgstr "Bad Format" +msgstr "" msgid "Bad Namespace Prefix" -msgstr "Bad Namespace Prefix" +msgstr "" msgid "Resource Conflict" -msgstr "Resource Conflict" +msgstr "" msgid "Connection Timeout" -msgstr "Connection Timeout" +msgstr "" msgid "Host Gone" -msgstr "Host Gone" +msgstr "" msgid "Host Unknown" -msgstr "Host Unknown" +msgstr "" msgid "Improper Addressing" -msgstr "Improper Addressing" +msgstr "" msgid "Invalid ID" -msgstr "Invalid ID" +msgstr "" msgid "Invalid Namespace" -msgstr "Invalid Namespace" +msgstr "" msgid "Invalid XML" -msgstr "Invalid XML" +msgstr "" msgid "Non-matching Hosts" -msgstr "Non-matching Hosts" +msgstr "" msgid "Policy Violation" -msgstr "Policy Violation" +msgstr "" msgid "Remote Connection Failed" -msgstr "Remote Connection Failed" +msgstr "" msgid "Restricted XML" -msgstr "Restricted XML" +msgstr "" msgid "See Other Host" -msgstr "See Other Host" +msgstr "" msgid "System Shutdown" -msgstr "System Shutdown" +msgstr "" msgid "Undefined Condition" -msgstr "Undefined Condition" +msgstr "" msgid "Unsupported Encoding" -msgstr "Unsupported Encoding" +msgstr "" msgid "Unsupported Stanza Type" -msgstr "Unsupported Stanza Type" +msgstr "" msgid "Unsupported Version" -msgstr "Unsupported Version" +msgstr "" msgid "XML Not Well Formed" -msgstr "XML Not Well Formed" +msgstr "" msgid "Stream Error" -msgstr "Stream Error" +msgstr "" #, c-format msgid "Unable to ban user %s" -msgstr "Unable to ban user %s" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Unknown affiliation: \"%s\"" -msgstr "Unknown command: %s" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Unable to affiliate user %s as \"%s\"" -msgstr "Unable to invite user (%s)." - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Unknown role: \"%s\"" -msgstr "Unknown command: %s" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Unable to set role \"%s\" for user: %s" -msgstr "Unable to send message: %s" +msgstr "" #, c-format msgid "Unable to kick user %s" -msgstr "Unable to kick user %s" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Unable to ping user %s" -msgstr "Unable to ban user %s" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Unable to buzz, because there is nothing known about %s." -msgstr "Unable to play sound because the chosen file (%s) does not exist." - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Unable to buzz, because %s might be offline." -msgstr "Unable to play sound because the chosen file (%s) does not exist." - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "" "Unable to buzz, because %s does not support it or does not wish to receive " "buzzes now." -msgstr "Unable to play sound because the chosen file (%s) does not exist." +msgstr "" #. Yahoo only supports one attention command: the 'buzz'. #. This is index number YAHOO_BUZZ. -#, fuzzy msgid "Buzz" -msgstr "Buzz!!" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "%s has buzzed you!" -msgstr "The user has blocked you" +msgstr "" #, c-format msgid "Buzzing %s..." msgstr "" -#, fuzzy, c-format +#, c-format msgid "Unable to initiate media with %s: invalid JID" -msgstr "Unable to send message to %s:" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Unable to initiate media with %s: user is not online" -msgstr "Unable to send file to %s, user does not support file transfers" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Unable to initiate media with %s: not subscribed to user presence" -msgstr "Unable to send file to %s, user does not support file transfers" - -#, fuzzy +msgstr "" + msgid "Media Initiation Failed" -msgstr "Registration Failed" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "" "Please select the resource of %s with which you would like to start a media " "session." msgstr "" -"Please enter the screen name of the person whose info you would like to view." - -#, fuzzy + msgid "Select a Resource" -msgstr "Select a file" - -#, fuzzy +msgstr "" + msgid "Initiate Media" -msgstr "Initiate _Chat" - -#, fuzzy +msgstr "" + msgid "Account does not support PEP, can't set mood" -msgstr "This protocol does not support chat rooms." +msgstr "" msgid "config: Configure a chat room." -msgstr "config: Configure a chat room." +msgstr "" msgid "configure: Configure a chat room." -msgstr "configure: Configure a chat room." - -#, fuzzy +msgstr "" + msgid "part [message]: Leave the room." -msgstr "part [room]: Leave the room." +msgstr "" msgid "register: Register with a chat room." -msgstr "register: Register with a chat room." +msgstr "" msgid "topic [new topic]: View or change the topic." -msgstr "topic [new topic]: View or change the topic." - -#, fuzzy +msgstr "" + msgid "ban <user> [reason]: Ban a user from the room." -msgstr "ban <user> [room]: Ban a user from the room." +msgstr "" msgid "" "affiliate <owner|admin|member|outcast|none> [nick1] [nick2] ...: Get " @@ -4885,22 +4462,18 @@ "users with a role or set users' role with the room." msgstr "" -#, fuzzy msgid "invite <user> [message]: Invite a user to the room." -msgstr "invite <user> [room]: Invite a user to the room." - -#, fuzzy +msgstr "" + msgid "join: <room> [password]: Join a chat on this server." -msgstr "join: <room> [server]: Join a chat on this server." - -#, fuzzy +msgstr "" + msgid "kick <user> [reason]: Kick a user from the room." -msgstr "kick <user> [room]: Kick a user from the room." +msgstr "" msgid "" "msg <user> <message>: Send a private message to another user." msgstr "" -"msg <user> <message>: Send a private message to another user." msgid "ping <jid>:\tPing a user/component/server." msgstr "" @@ -4908,12 +4481,11 @@ msgid "buzz: Buzz a user to get their attention" msgstr "" -#, fuzzy msgid "mood: Set current user mood" -msgstr "Select correct user" +msgstr "" msgid "Extended Away" -msgstr "Extended Away" +msgstr "" #. *< type #. *< ui_requirement @@ -4926,44 +4498,29 @@ #. * summary #. * description msgid "XMPP Protocol Plugin" -msgstr "XMPP Protocol Plugin" +msgstr "" #. Translators: 'domain' is used here in the context of Internet domains, e.g. pidgin.im -#, fuzzy msgid "Domain" -msgstr "Romanian" - -#, fuzzy -msgid "Require encryption" -msgstr "Request Authorization" - -#, fuzzy -msgid "Use encryption if available" -msgstr "Use TLS if available" +msgstr "" msgid "Use old-style SSL" msgstr "" -#, fuzzy -msgid "Connection security" -msgstr "Connection Closed" - msgid "Allow plaintext auth over unencrypted streams" -msgstr "Allow plaintext auth over unencrypted streams" - -#, fuzzy +msgstr "" + msgid "Connect port" -msgstr "Connect" +msgstr "" #. TODO: default to automatically try different ports. Make the user be #. * able to set the first port to try (like LastConnectedPort in Windows client). #. Account options msgid "Connect server" -msgstr "Connect server" - -#, fuzzy +msgstr "" + msgid "File transfer proxies" -msgstr "File transfer port" +msgstr "" msgid "BOSH URL" msgstr "" @@ -4973,36 +4530,35 @@ msgid "Show Custom Smileys" msgstr "" -#, fuzzy, c-format +#, c-format msgid "%s has left the conversation." -msgstr "%s has been invited to this conversation." +msgstr "" #, c-format msgid "Message from %s" -msgstr "Message from %s" +msgstr "" #, c-format msgid "%s has set the topic to: %s" -msgstr "%s has set the topic to: %s" +msgstr "" #, c-format msgid "The topic is: %s" -msgstr "The topic is: %s" +msgstr "" #, c-format msgid "Message delivery to %s failed: %s" -msgstr "Message delivery to %s failed: %s" +msgstr "" msgid "XMPP Message Error" -msgstr "XMPP Message Error" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "(Code %s)" -msgstr " (Code %s)" - -#, fuzzy +msgstr "" + msgid "A custom smiley in the message is too large to send." -msgstr "Unable to send message. The message is too large." +msgstr "" msgid "XMPP stream header missing" msgstr "" @@ -5014,215 +4570,184 @@ msgstr "" msgid "XML Parse error" -msgstr "XML Parse error" +msgstr "" #, c-format msgid "Error joining chat %s" -msgstr "Error joining chat %s" +msgstr "" #, c-format msgid "Error in chat %s" -msgstr "Error in chat %s" +msgstr "" msgid "Create New Room" -msgstr "Create New Room" +msgstr "" msgid "" "You are creating a new room. Would you like to configure it, or accept the " "default settings?" msgstr "" -"You are creating a new room. Would you like to configure it, or accept the " -"default settings?" - -#, fuzzy + msgid "_Configure Room" -msgstr "Configure Room" - -#, fuzzy +msgstr "" + msgid "_Accept Defaults" -msgstr "Accept Defaults" - -#, fuzzy +msgstr "" + msgid "No reason" -msgstr "No reason given." - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "You have been kicked: (%s)" -msgstr "You have been kicked by %s: (%s)" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Kicked (%s)" -msgstr "Kicked by %s (%s)" +msgstr "" msgid "Unknown Error in presence" -msgstr "Unknown Error in presence" +msgstr "" #, c-format msgid "Unable to send file to %s, user does not support file transfers" -msgstr "Unable to send file to %s, user does not support file transfers" - +msgstr "" + +#. not success msgid "File Send Failed" -msgstr "File Send Failed" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Unable to send file to %s, invalid JID" -msgstr "Unable to send message to %s:" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Unable to send file to %s, user is not online" -msgstr "Unable to send file to %s, user does not support file transfers" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Unable to send file to %s, not subscribed to user presence" -msgstr "Unable to send file to %s, user does not support file transfers" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Please select the resource of %s to which you would like to send a file" msgstr "" -"Please enter the screen name of the person whose info you would like to view." - -#, fuzzy + msgid "Afraid" -msgstr "Amharic" - -#, fuzzy +msgstr "" + msgid "Amazed" -msgstr "Ashamed" +msgstr "" msgid "Amorous" msgstr "" msgid "Angry" -msgstr "Angry" - -#, fuzzy +msgstr "" + msgid "Annoyed" -msgstr "Banned" +msgstr "" msgid "Anxious" -msgstr "Anxious" - -#, fuzzy +msgstr "" + msgid "Aroused" -msgstr "You send" +msgstr "" msgid "Ashamed" -msgstr "Ashamed" +msgstr "" msgid "Bored" -msgstr "Bored" - -#, fuzzy +msgstr "" + msgid "Brave" -msgstr "Save" - -#, fuzzy +msgstr "" + msgid "Calm" -msgstr "Realname" - -#, fuzzy +msgstr "" + msgid "Cautious" -msgstr "Chats" - -#, fuzzy +msgstr "" + msgid "Cold" -msgstr "Bold" - -#, fuzzy +msgstr "" + msgid "Confident" -msgstr "Conflict" - -#, fuzzy +msgstr "" + msgid "Confused" -msgstr "Connecting" - -#, fuzzy +msgstr "" + msgid "Contemplative" -msgstr "Account Info" - -#, fuzzy +msgstr "" + msgid "Contented" -msgstr "Connect" - -#, fuzzy +msgstr "" + msgid "Cranky" -msgstr "Company" +msgstr "" msgid "Crazy" msgstr "" -#, fuzzy msgid "Creative" -msgstr "Date" - -#, fuzzy +msgstr "" + msgid "Curious" -msgstr "Turkish" - -#, fuzzy +msgstr "" + msgid "Dejected" -msgstr "Reset" - -#, fuzzy +msgstr "" + msgid "Depressed" -msgstr "Delete" - -#, fuzzy +msgstr "" + msgid "Disappointed" -msgstr "Disconnected." +msgstr "" msgid "Disgusted" msgstr "" -#, fuzzy msgid "Dismayed" -msgstr "Visible" - -#, fuzzy +msgstr "" + msgid "Distracted" -msgstr "Detached" +msgstr "" msgid "Embarrassed" msgstr "" -#, fuzzy msgid "Envious" -msgstr "Anxious" +msgstr "" msgid "Excited" -msgstr "Excited" +msgstr "" msgid "Flirtatious" msgstr "" -#, fuzzy msgid "Frustrated" -msgstr "First name:" +msgstr "" msgid "Grateful" msgstr "" -#, fuzzy msgid "Grieving" -msgstr "Connecting..." - -#, fuzzy +msgstr "" + msgid "Grumpy" -msgstr "Group:" - -#, fuzzy +msgstr "" + msgid "Guilty" -msgstr "City" +msgstr "" msgid "Happy" -msgstr "Happy" +msgstr "" msgid "Hopeful" msgstr "" -#, fuzzy msgid "Hot" -msgstr "_Host:" +msgstr "" msgid "Humbled" msgstr "" @@ -5230,9 +4755,8 @@ msgid "Humiliated" msgstr "" -#, fuzzy msgid "Hungry" -msgstr "Angry" +msgstr "" msgid "Hurt" msgstr "" @@ -5240,91 +4764,74 @@ msgid "Impressed" msgstr "" -#, fuzzy msgid "In awe" -msgstr "In Love" - -#, fuzzy +msgstr "" + msgid "In love" -msgstr "In Love" - -#, fuzzy +msgstr "" + msgid "Indignant" -msgstr "Macedonian" - -#, fuzzy +msgstr "" + msgid "Interested" -msgstr "_Insert" - -#, fuzzy +msgstr "" + msgid "Intoxicated" -msgstr "Invite" +msgstr "" msgid "Invincible" -msgstr "Invincible" +msgstr "" msgid "Jealous" -msgstr "Jealous" - -#, fuzzy +msgstr "" + msgid "Lonely" -msgstr "None" - -#, fuzzy +msgstr "" + msgid "Lost" -msgstr "Sounds" +msgstr "" msgid "Lucky" msgstr "" -#, fuzzy msgid "Mean" -msgstr "German" - -#, fuzzy +msgstr "" + msgid "Moody" -msgstr "Mood" +msgstr "" msgid "Nervous" msgstr "" -#, fuzzy msgid "Neutral" -msgstr "Details" - -#, fuzzy +msgstr "" + msgid "Offended" -msgstr "Offline" +msgstr "" msgid "Outraged" msgstr "" -#, fuzzy msgid "Playful" -msgstr "Play" - -#, fuzzy +msgstr "" + msgid "Proud" -msgstr "Load" - -#, fuzzy +msgstr "" + msgid "Relaxed" -msgstr "Realname" - -#, fuzzy +msgstr "" + msgid "Relieved" -msgstr "Send Message" - -#, fuzzy +msgstr "" + msgid "Remorseful" -msgstr "Remove" - -#, fuzzy +msgstr "" + msgid "Restless" -msgstr "Register" +msgstr "" msgid "Sad" -msgstr "Sad" +msgstr "" msgid "Sarcastic" msgstr "" @@ -5332,35 +4839,30 @@ msgid "Satisfied" msgstr "" -#, fuzzy msgid "Serious" -msgstr "Sounds" - -#, fuzzy +msgstr "" + msgid "Shocked" -msgstr "Blocked" +msgstr "" msgid "Shy" msgstr "" -#, fuzzy msgid "Sick" -msgstr "Nick" +msgstr "" #. Sleepy / Tired msgid "Sleepy" -msgstr "Sleepy" +msgstr "" msgid "Spontaneous" msgstr "" -#, fuzzy msgid "Stressed" -msgstr "Speed:" - -#, fuzzy +msgstr "" + msgid "Strong" -msgstr "_Sorting:" +msgstr "" msgid "Surprised" msgstr "" @@ -5371,275 +4873,245 @@ msgid "Thirsty" msgstr "" -#, fuzzy msgid "Tired" -msgstr "Firefox" - -#, fuzzy +msgstr "" + msgid "Undefined" -msgstr "Underline" - -#, fuzzy +msgstr "" + msgid "Weak" -msgstr "Back" - -#, fuzzy +msgstr "" + msgid "Worried" -msgstr "Bored" - -#, fuzzy +msgstr "" + msgid "Set User Nickname" -msgstr "Set User Limit" - -#, fuzzy +msgstr "" + msgid "Please specify a new nickname for you." -msgstr "Please enter a new name for the selected group." +msgstr "" msgid "" "This information is visible to all contacts on your contact list, so choose " "something appropriate." msgstr "" -#, fuzzy msgid "Set" -msgstr "_Set" - -#, fuzzy +msgstr "" + msgid "Set Nickname..." -msgstr "Nickname" - -#, fuzzy +msgstr "" + msgid "Actions" -msgstr "Accounts" - -#, fuzzy +msgstr "" + msgid "Select an action" -msgstr "Select a file" +msgstr "" #. only notify the user about problems adding to the friends list #. * maybe we should do something else for other lists, but it probably #. * won't cause too many problems if we just ignore it -#, fuzzy, c-format +#, c-format msgid "Unable to add \"%s\"." -msgstr "Unable to read file %s." - -#, fuzzy +msgstr "" + msgid "Buddy Add error" -msgstr "Buddy List Error" - -#, fuzzy +msgstr "" + msgid "The username specified does not exist." -msgstr "The SecurID key entered is invalid." +msgstr "" msgid "Unable to parse message" -msgstr "Unable to parse message" - -#, fuzzy +msgstr "" + msgid "Syntax Error (probably a client bug)" -msgstr "Syntax Error (probably a Pidgin bug)" +msgstr "" msgid "Invalid email address" -msgstr "Invalid email address" +msgstr "" msgid "User does not exist" -msgstr "User does not exist" - -#, fuzzy +msgstr "" + msgid "Fully qualified domain name missing" -msgstr "Fully Qualified Domain Name missing" - -#, fuzzy +msgstr "" + msgid "Already logged in" -msgstr "Already Logged In" - -#, fuzzy +msgstr "" + msgid "Invalid username" -msgstr "Invalid Username" - -#, fuzzy +msgstr "" + msgid "Invalid friendly name" -msgstr "Invalid Friendly Name" - -#, fuzzy +msgstr "" + msgid "List full" -msgstr "List Full" +msgstr "" msgid "Already there" -msgstr "Already there" +msgstr "" msgid "Not on list" -msgstr "Not on list" +msgstr "" msgid "User is offline" -msgstr "User is offline" +msgstr "" msgid "Already in the mode" -msgstr "Already in the mode" +msgstr "" msgid "Already in opposite list" -msgstr "Already in opposite list" +msgstr "" msgid "Too many groups" -msgstr "Too many groups" +msgstr "" msgid "Invalid group" -msgstr "Invalid group" +msgstr "" msgid "User not in group" -msgstr "User not in group" +msgstr "" msgid "Group name too long" -msgstr "Group name too long" +msgstr "" msgid "Cannot remove group zero" -msgstr "Cannot remove group zero" - -#, fuzzy +msgstr "" + msgid "Tried to add a user to a group that doesn't exist" -msgstr "Tried to add a contact to a group that doesn't exist" +msgstr "" msgid "Switchboard failed" -msgstr "Switchboard failed" - -#, fuzzy +msgstr "" + msgid "Notify transfer failed" -msgstr "Notify Transfer failed" +msgstr "" msgid "Required fields missing" -msgstr "Required fields missing" +msgstr "" msgid "Too many hits to a FND" -msgstr "Too many hits to a FND" +msgstr "" msgid "Not logged in" -msgstr "Not logged in" - -#, fuzzy +msgstr "" + msgid "Service temporarily unavailable" -msgstr "Service Temporarily Unavailable" +msgstr "" msgid "Database server error" -msgstr "Database server error" +msgstr "" msgid "Command disabled" -msgstr "Command disabled" +msgstr "" msgid "File operation error" -msgstr "File operation error" +msgstr "" msgid "Memory allocation error" -msgstr "Memory allocation error" +msgstr "" msgid "Wrong CHL value sent to server" -msgstr "Wrong CHL value sent to server" +msgstr "" msgid "Server busy" -msgstr "Server busy" +msgstr "" msgid "Server unavailable" -msgstr "Server unavailable" - -#, fuzzy +msgstr "" + msgid "Peer notification server down" -msgstr "Peer Notification server down" +msgstr "" msgid "Database connect error" -msgstr "Database connect error" +msgstr "" msgid "Server is going down (abandon ship)" -msgstr "Server is going down (abandon ship)" +msgstr "" msgid "Error creating connection" -msgstr "Error creating connection" +msgstr "" msgid "CVR parameters are either unknown or not allowed" -msgstr "CVR parameters are either unknown or not allowed" +msgstr "" msgid "Unable to write" -msgstr "Unable to write" +msgstr "" msgid "Session overload" -msgstr "Session overload" +msgstr "" msgid "User is too active" -msgstr "User is too active" +msgstr "" msgid "Too many sessions" -msgstr "Too many sessions" +msgstr "" msgid "Passport not verified" -msgstr "Passport not verified" +msgstr "" msgid "Bad friend file" -msgstr "Bad friend file" +msgstr "" msgid "Not expected" -msgstr "Not expected" - -#, fuzzy +msgstr "" + msgid "Friendly name is changing too rapidly" -msgstr "Friendly name changes too rapidly" +msgstr "" msgid "Server too busy" -msgstr "Server too busy" +msgstr "" msgid "Authentication failed" -msgstr "Authentication failed" +msgstr "" msgid "Not allowed when offline" -msgstr "Not allowed when offline" +msgstr "" msgid "Not accepting new users" -msgstr "Not accepting new users" +msgstr "" msgid "Kids Passport without parental consent" -msgstr "Kids Passport without parental consent" +msgstr "" msgid "Passport account not yet verified" -msgstr "Passport account not yet verified" - -#, fuzzy +msgstr "" + msgid "Passport account suspended" -msgstr "Passport account not yet verified" +msgstr "" msgid "Bad ticket" -msgstr "Bad ticket" +msgstr "" #, c-format msgid "Unknown Error Code %d" -msgstr "Unknown Error Code %d" +msgstr "" #, c-format msgid "MSN Error: %s\n" -msgstr "MSN Error: %s\n" +msgstr "" #, c-format msgid "Buddy list synchronization issue in %s (%s)" -msgstr "Buddy list synchronization issue in %s (%s)" +msgstr "" #, c-format msgid "" "%s on the local list is inside the group \"%s\" but not on the server list. " "Do you want this buddy to be added?" msgstr "" -"%s on the local list is inside the group \"%s\" but not on the server list. " -"Do you want this buddy to be added?" #, c-format msgid "" "%s is on the local list but not on the server list. Do you want this buddy " "to be added?" msgstr "" -"%s is on the local list but not on the server list. Do you want this buddy " -"to be added?" - -#, fuzzy + msgid "Other Contacts" -msgstr "Preferred Contact" - -#, fuzzy +msgstr "" + msgid "Non-IM Contacts" -msgstr "Remove Contact" +msgstr "" #, c-format msgid "%s sent a wink. Click here to play it" @@ -5664,47 +5136,41 @@ msgid "Nudge" msgstr "" -#, fuzzy, c-format +#, c-format msgid "%s has nudged you!" -msgstr "%s has gone away." +msgstr "" #, c-format msgid "Nudging %s..." msgstr "" -#, fuzzy msgid "Email Address..." -msgstr "Email Address" +msgstr "" msgid "Your new MSN friendly name is too long." -msgstr "Your new MSN friendly name is too long." - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Set friendly name for %s." -msgstr "Set your friendly name." - -#, fuzzy +msgstr "" + msgid "Set Friendly Name" -msgstr "Set Friendly Name" +msgstr "" msgid "This is the name that other MSN buddies will see you as." -msgstr "This is the name that other MSN buddies will see you as." - -#, fuzzy +msgstr "" + msgid "This Location" -msgstr "Location" - -#, fuzzy +msgstr "" + msgid "This is the name that identifies this location" -msgstr "This is the name that other MSN buddies will see you as." - -#, fuzzy +msgstr "" + msgid "Other Locations" -msgstr "Location" - -#, fuzzy +msgstr "" + msgid "You can sign out from other locations here" -msgstr "You have signed on from another location." +msgstr "" #. TODO: Due to limitations in our current request field API, the #. following string will show up with a trailing colon. This should @@ -5712,9 +5178,8 @@ #. a separate purple_request_field_label_new_without_colon function, #. or by never automatically adding the colon and requiring that #. callers add the colon themselves. -#, fuzzy msgid "You are not signed in from any other locations." -msgstr "You have signed on from another location." +msgstr "" msgid "Allow multiple logins?" msgstr "" @@ -5725,33 +5190,31 @@ msgstr "" msgid "Allow" -msgstr "Allow" +msgstr "" msgid "Disallow" -msgstr "Disallow" +msgstr "" msgid "Set your home phone number." -msgstr "Set your home phone number." +msgstr "" msgid "Set your work phone number." -msgstr "Set your work phone number." +msgstr "" msgid "Set your mobile phone number." -msgstr "Set your mobile phone number." +msgstr "" msgid "Allow MSN Mobile pages?" -msgstr "Allow MSN Mobile pages?" +msgstr "" msgid "" "Do you want to allow or disallow people on your buddy list to send you MSN " "Mobile pages to your cell phone or other mobile device?" msgstr "" -"Do you want to allow or disallow people on your buddy list to send you MSN " -"Mobile pages to your cell phone or other mobile device?" - -#, fuzzy, c-format + +#, c-format msgid "Blocked Text for %s" -msgstr "Buddy Comment for %s" +msgstr "" msgid "No text is blocked for this account." msgstr "" @@ -5765,86 +5228,70 @@ msgstr "" msgid "Send a mobile message." -msgstr "Send a mobile message." +msgstr "" msgid "Page" -msgstr "Page" +msgstr "" msgid "Playing a game" msgstr "" -#, fuzzy msgid "Working" -msgstr "Warn" +msgstr "" msgid "Has you" -msgstr "Has you" - -#, fuzzy +msgstr "" + msgid "Home Phone Number" -msgstr "Set Home Phone Number" - -#, fuzzy +msgstr "" + msgid "Work Phone Number" -msgstr "Set Work Phone Number" - -#, fuzzy +msgstr "" + msgid "Mobile Phone Number" -msgstr "Set Mobile Phone Number" +msgstr "" msgid "Be Right Back" -msgstr "Be Right Back" +msgstr "" msgid "Busy" -msgstr "Busy" - -#, fuzzy +msgstr "" + msgid "On the Phone" -msgstr "On The Phone" - -#, fuzzy +msgstr "" + msgid "Out to Lunch" -msgstr "Out To Lunch" - -#, fuzzy +msgstr "" + msgid "Game Title" -msgstr "Title" - -#, fuzzy +msgstr "" + msgid "Office Title" -msgstr "Title" - -#, fuzzy +msgstr "" + msgid "Set Friendly Name..." -msgstr "Set Friendly Name" - -#, fuzzy +msgstr "" + msgid "View Locations..." -msgstr "Location" - -#, fuzzy +msgstr "" + msgid "Set Home Phone Number..." -msgstr "Set Home Phone Number" - -#, fuzzy +msgstr "" + msgid "Set Work Phone Number..." -msgstr "Set Work Phone Number" - -#, fuzzy +msgstr "" + msgid "Set Mobile Phone Number..." -msgstr "Set Mobile Phone Number" - -#, fuzzy +msgstr "" + msgid "Enable/Disable Mobile Devices..." -msgstr "Enable/Disable Mobile Devices" - -#, fuzzy +msgstr "" + msgid "Allow/Disallow Multiple Logins..." -msgstr "Allow/Disallow Mobile Pages" - -#, fuzzy +msgstr "" + msgid "Allow/Disallow Mobile Pages..." -msgstr "Allow/Disallow Mobile Pages" +msgstr "" msgid "View Blocked Text..." msgstr "" @@ -5853,79 +5300,55 @@ msgstr "" msgid "Send to Mobile" -msgstr "Send to Mobile" - -#, fuzzy +msgstr "" + msgid "SSL support is needed for MSN. Please install a supported SSL library." msgstr "" -"SSL support is needed for MSN. Please install a supported SSL library. See " -"http://Pidgin.sf.net/faq-ssl.php for more information." - -#, fuzzy, c-format + +#, c-format msgid "" "Unable to add the buddy %s because the username is invalid. Usernames must " "be valid email addresses." msgstr "" -"Could not add the buddy %s because the screen name is invalid. Screen names " -"must either start with a letter and contain only letters, numbers and " -"spaces, or contain only numbers." - -#, fuzzy + msgid "Unable to Add" -msgstr "Unable To Add" - -msgid "Authorization Request Message:" -msgstr "Authorization Request Message:" - -msgid "Please authorize me!" -msgstr "Please authorize me!" - -#. * -#. * A wrapper for purple_request_action() that uses @c OK and @c Cancel buttons. -#. -#, fuzzy -msgid "_OK" -msgstr "OK" +msgstr "" msgid "Error retrieving profile" -msgstr "Error retrieving profile" - -#, fuzzy +msgstr "" + msgid "General" -msgstr "Gender" +msgstr "" msgid "Age" -msgstr "Age" +msgstr "" msgid "Occupation" -msgstr "Occupation" +msgstr "" msgid "Location" -msgstr "Location" +msgstr "" msgid "Hobbies and Interests" -msgstr "Hobbies and Interests" +msgstr "" msgid "A Little About Me" -msgstr "A Little About Me" +msgstr "" msgid "Social" msgstr "" msgid "Marital Status" -msgstr "Marital Status" - -#, fuzzy +msgstr "" + msgid "Interests" -msgstr "_Insert" - -#, fuzzy +msgstr "" + msgid "Pets" -msgstr "Ports" - -#, fuzzy +msgstr "" + msgid "Hometown" -msgstr "Host Unknown" +msgstr "" msgid "Places Lived" msgstr "" @@ -5934,51 +5357,43 @@ msgstr "" msgid "Humor" -msgstr "" +msgstr "Humour" msgid "Music" msgstr "" msgid "Favorite Quote" -msgstr "Favuorite Quote" - -#, fuzzy +msgstr "Favourite Quote" + msgid "Contact Info" -msgstr "Account Info" - -#, fuzzy +msgstr "" + msgid "Personal" -msgstr "Personal Title" +msgstr "" msgid "Significant Other" msgstr "" -#, fuzzy msgid "Home Phone" -msgstr "Home Page" - -#, fuzzy +msgstr "" + msgid "Home Phone 2" -msgstr "Set Home Phone Number" +msgstr "" msgid "Home Address" -msgstr "Home Address" - -#, fuzzy +msgstr "" + msgid "Personal Mobile" -msgstr "Personal Title" - -#, fuzzy +msgstr "" + msgid "Home Fax" -msgstr "Home Page" - -#, fuzzy +msgstr "" + msgid "Personal Email" -msgstr "Personal Title" - -#, fuzzy +msgstr "" + msgid "Personal IM" -msgstr "Personal Title" +msgstr "" msgid "Anniversary" msgstr "" @@ -5988,80 +5403,66 @@ msgstr "" msgid "Company" -msgstr "Company" +msgstr "" msgid "Department" -msgstr "Department" - -#, fuzzy +msgstr "" + msgid "Profession" -msgstr "Progress" - -#, fuzzy +msgstr "" + msgid "Work Phone" -msgstr "Phone" - -#, fuzzy +msgstr "" + msgid "Work Phone 2" -msgstr "Set Work Phone Number" +msgstr "" msgid "Work Address" -msgstr "Work Address" - -#, fuzzy +msgstr "" + msgid "Work Mobile" -msgstr "Send to Mobile" - -#, fuzzy +msgstr "" + msgid "Work Pager" -msgstr "Web Page" +msgstr "" msgid "Work Fax" msgstr "" -#, fuzzy msgid "Work Email" -msgstr "Email" +msgstr "" msgid "Work IM" msgstr "" -#, fuzzy msgid "Start Date" -msgstr "Province/Territory" +msgstr "" msgid "Favorite Things" msgstr "Favourite Things" msgid "Last Updated" -msgstr "Last Updated" +msgstr "" msgid "Homepage" -msgstr "Homepage" +msgstr "" msgid "The user has not created a public profile." -msgstr "The user has not created a public profile." +msgstr "" msgid "" "MSN reported not being able to find the user's profile. This either means " "that the user does not exist, or that the user exists but has not created a " "public profile." msgstr "" -"MSN reported not being able to find the user's profile. This either means " -"that the user does not exist, or that the user exists but has not created a " -"public profile." - -#, fuzzy + msgid "" "Could not find any information in the user's profile. The user most likely " "does not exist." msgstr "" -"Pidgin could not find any information in the user's profile. The user most " -"likely does not exist." - -#, fuzzy + msgid "View web profile" -msgstr "Not allowed when offline" +msgstr "" #. *< type #. *< ui_requirement @@ -6072,23 +5473,20 @@ #. *< name #. *< version #. *< summary -#, fuzzy msgid "Windows Live Messenger Protocol Plugin" -msgstr "Novell GroupWise Messenger Protocol Plugin" +msgstr "" msgid "Use HTTP Method" -msgstr "Use HTTP Method" - -#, fuzzy +msgstr "" + msgid "HTTP Method Server" -msgstr "IPC Test Server" +msgstr "" msgid "Show custom smileys" msgstr "" -#, fuzzy msgid "Allow direct connections" -msgstr "Unable to create new connection." +msgstr "" msgid "Allow connecting from multiple locations" msgstr "" @@ -6096,37 +5494,35 @@ msgid "nudge: nudge a user to get their attention" msgstr "" -#, fuzzy msgid "Windows Live ID authentication:Unable to connect" -msgstr "Normal authentication failed!" - -#, fuzzy +msgstr "" + msgid "Windows Live ID authentication:Invalid response" -msgstr "Normal authentication failed!" +msgstr "" msgid "The following users are missing from your addressbook" msgstr "" -#, fuzzy, c-format +#, c-format msgid "Unknown error (%d): %s" -msgstr "Unknown error" - -#, fuzzy +msgstr "" + msgid "Unable to add user" -msgstr "Unable to ban user %s" +msgstr "" #. Unknown error! -#, fuzzy, c-format +#, c-format msgid "Unknown error (%d)" -msgstr "Unknown error" - -#, fuzzy +msgstr "" + msgid "Unable to remove user" -msgstr "Unable to ban user %s" - -#, fuzzy +msgstr "" + msgid "Mobile message was not sent because it was too long." -msgstr "Message could not be sent because the user is offline:" +msgstr "" + +msgid "Mobile message was not sent because an unknown error occurred." +msgstr "" #, c-format msgid "" @@ -6144,97 +5540,73 @@ "After the maintenance has been completed, you will be able to successfully " "sign in." msgstr[0] "" -"The MSN server will shut down for maintenance in %d minute. You will " -"automatically be signed out at that time. Please finish any conversations " -"in progress.\n" -"\n" -"After the maintenance has been completed, you will be able to successfully " -"sign in." -msgstr[1] "" -"The MSN server will shut down for maintenance in %d minutes. You will " -"automatically be signed out at that time. Please finish any conversations " -"in progress.\n" -"\n" -"After the maintenance has been completed, you will be able to successfully " -"sign in." msgid "" "Message was not sent because the system is unavailable. This normally " "happens when the user is blocked or does not exist." msgstr "" -#, fuzzy msgid "Message was not sent because messages are being sent too quickly." -msgstr "Message could not be sent because the user is offline:" - -#, fuzzy +msgstr "" + msgid "Message was not sent because an unknown encoding error occurred." -msgstr "Message may have not been sent because an unknown error occurred:" - -#, fuzzy +msgstr "" + msgid "Message was not sent because an unknown error occurred." -msgstr "Message may have not been sent because an unknown error occurred:" +msgstr "" msgid "Writing error" -msgstr "Writing error" +msgstr "" msgid "Reading error" -msgstr "Reading error" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "" "Connection error from %s server:\n" "%s" msgstr "" -"Connection error from %s server (%s):\n" -"%s" - -#, fuzzy + msgid "Our protocol is not supported by the server" -msgstr "Our protocol is not supported by the server." - -#, fuzzy +msgstr "" + msgid "Error parsing HTTP" -msgstr "Error parsing HTTP." - -#, fuzzy +msgstr "" + msgid "You have signed on from another location" -msgstr "You have signed on from another location." +msgstr "" msgid "The MSN servers are temporarily unavailable. Please wait and try again." msgstr "" -"The MSN servers are temporarily unavailable. Please wait and try again." - -#, fuzzy + msgid "The MSN servers are going down temporarily" -msgstr "The MSN servers are going down temporarily." +msgstr "" #, c-format msgid "Unable to authenticate: %s" -msgstr "Unable to authenticate: %s" +msgstr "" msgid "" "Your MSN buddy list is temporarily unavailable. Please wait and try again." msgstr "" -"Your MSN buddy list is temporarily unavailable. Please wait and try again." msgid "Handshaking" -msgstr "Handshaking" +msgstr "" msgid "Transferring" -msgstr "Transferring" +msgstr "" msgid "Starting authentication" -msgstr "Starting authentication" +msgstr "" msgid "Getting cookie" -msgstr "Getting cookie" +msgstr "" msgid "Sending cookie" -msgstr "Sending cookie" +msgstr "" msgid "Retrieving buddy list" -msgstr "Retrieving buddy list" +msgstr "" #, c-format msgid "%s requests to view your webcam, but this request is not yet supported." @@ -6245,29 +5617,28 @@ msgstr "" msgid "Away From Computer" -msgstr "Away From Computer" +msgstr "" msgid "On The Phone" -msgstr "On The Phone" +msgstr "" msgid "Out To Lunch" -msgstr "Out To Lunch" +msgstr "" msgid "Message may have not been sent because a timeout occurred:" -msgstr "Message may have not been sent because a timeout occurred:" +msgstr "" msgid "Message could not be sent, not allowed while invisible:" -msgstr "Message could not be sent: not allowed while invisible:" +msgstr "" msgid "Message could not be sent because the user is offline:" -msgstr "Message could not be sent because the user is offline:" +msgstr "" msgid "Message could not be sent because a connection error occurred:" -msgstr "Message could not be sent because a connection error occurred:" - -#, fuzzy +msgstr "" + msgid "Message could not be sent because we are sending too quickly:" -msgstr "Message could not be sent because the user is offline:" +msgstr "" msgid "" "Message could not be sent because we were unable to establish a session with " @@ -6277,183 +5648,190 @@ msgid "" "Message could not be sent because an error with the switchboard occurred:" msgstr "" -"Message could not be sent because an error with the switchboard occurred:" msgid "Message may have not been sent because an unknown error occurred:" -msgstr "Message may have not been sent because an unknown error occurred:" - -#, fuzzy +msgstr "" + msgid "Delete Buddy from Address Book?" -msgstr "Add to Address Book" - -#, fuzzy +msgstr "" + msgid "Do you want to delete this buddy from your address book as well?" -msgstr "Do you want to add this buddy to your buddy list?" - -#, fuzzy +msgstr "" + msgid "The username specified is invalid." -msgstr "The SecurID key entered is invalid." - -#, fuzzy -msgid "The PIN you entered is invalid." -msgstr "The SecurID key entered is invalid." - -#, fuzzy -msgid "The PIN you entered has an invalid length [4-10]." -msgstr "The SecurID key entered is invalid." - -msgid "The PIN is invalid. It should only consist of digits [0-9]." -msgstr "" - -#, fuzzy -msgid "The two PINs you entered do not match." -msgstr "New passwords do not match." - -#, fuzzy +msgstr "" + msgid "The Display Name you entered is invalid." -msgstr "The SecurID key entered is invalid." +msgstr "" msgid "" "The birthday you entered is invalid. The correct format is: 'YYYY-MM-DD'." msgstr "" #. show error to user -#, fuzzy msgid "Profile Update Error" -msgstr "Write error" +msgstr "" #. no profile information yet, so we cannot update #. (reference: "libpurple/request.h") msgid "Profile" -msgstr "Profile" +msgstr "" msgid "Your profile information is not yet retrieved. Please try again later." msgstr "" -msgid "Your UID" -msgstr "" - -#. pin -#. pin (required) -#, fuzzy -msgid "PIN" -msgstr "UIN" - -msgid "Verify PIN" -msgstr "" - #. display name #. nick name (required) -#, fuzzy msgid "Display Name" -msgstr "Display" - -#. hidden -msgid "Hide my number" +msgstr "" + +#. about me +msgid "About Me" +msgstr "" + +#. where I live +msgid "Where I Live" msgstr "" #. mobile number -#, fuzzy msgid "Mobile Number" -msgstr "Set Mobile Phone Number" - -#, fuzzy -msgid "Update your Profile" -msgstr "Set Profile" - -msgid "Here you can update your MXit profile" +msgstr "" + +#. is searchable +msgid "Can be searched" +msgstr "" + +#. is suggestable +msgid "Can be suggested" +msgstr "" + +msgid "Update your MXit Profile" +msgstr "" + +msgid "The PIN you entered is invalid." +msgstr "" + +msgid "The PIN you entered has an invalid length [4-10]." +msgstr "" + +msgid "The PIN is invalid. It should only consist of digits [0-9]." +msgstr "" + +msgid "The two PINs you entered do not match." +msgstr "" + +#. show error to user +msgid "PIN Update Error" +msgstr "" + +#. pin +#. pin (required) +msgid "PIN" +msgstr "" + +#. verify pin +msgid "Verify PIN" +msgstr "" + +#. (reference: "libpurple/request.h") +msgid "Change PIN" +msgstr "" + +msgid "Change MXit PIN" msgstr "" msgid "View Splash" msgstr "" -#, fuzzy msgid "There is no splash-screen currently available" -msgstr "Chat is currently unavailable" - -#, fuzzy +msgstr "" + msgid "About" -msgstr "About Pidgin" +msgstr "" + +msgid "Search for user" +msgstr "" + +msgid "Search for a MXit contact" +msgstr "" + +msgid "Type search information" +msgstr "" + +msgid "_Search" +msgstr "" #. display / change profile -#, fuzzy msgid "Change Profile..." -msgstr "Change Password..." +msgstr "" + +#. change PIN +msgid "Change PIN..." +msgstr "" + +#. suggested friends +msgid "Suggested friends..." +msgstr "" + +#. search for contacts +msgid "Search for contacts..." +msgstr "" #. display splash-screen -#, fuzzy msgid "View Splash..." -msgstr "View _Log" +msgstr "" #. display plugin version -#, fuzzy msgid "About..." -msgstr "About Pidgin" +msgstr "" #. the file is too big -#, fuzzy msgid "The file you are trying to send is too large!" -msgstr "The message is too large." - -#, fuzzy +msgstr "" + msgid "" "Unable to connect to the MXit HTTP server. Please check your server settings." msgstr "" -"Unable to connect to server. Please enter the address of the server you wish " -"to connect to." - -#, fuzzy + msgid "Logging In..." -msgstr "Logging" - -#, fuzzy +msgstr "" + msgid "" "Unable to connect to the MXit server. Please check your server settings." msgstr "" -"Unable to connect to server. Please enter the address of the server you wish " -"to connect to." - -#, fuzzy + msgid "Connecting..." -msgstr "Connecting" - -#, fuzzy +msgstr "" + +msgid "The Display Name you entered is too short." +msgstr "" + msgid "The PIN you entered has an invalid length [7-10]." -msgstr "The SecurID key entered is invalid." +msgstr "" #. mxit login name msgid "MXit ID" msgstr "" #. show the form to the user to complete -#, fuzzy msgid "Register New MXit Account" -msgstr "Register New XMPP Account" +msgstr "" msgid "Please fill in the following fields:" msgstr "" #. no reply from the WAP site -#, fuzzy msgid "Error contacting the MXit WAP site. Please try again later." msgstr "" -"Pidgin was unable to connect to the buddy list server. Please try again " -"later." #. wapserver error #. server could not find the user -#, fuzzy msgid "" "MXit is currently unable to process the request. Please try again later." msgstr "" -"Pidgin was unable to connect to the buddy list server. Please try again " -"later." - -#, fuzzy + msgid "Wrong security code entered. Please try again later." msgstr "" -"Pidgin was unable to connect to the buddy list server. Please try again " -"later." msgid "Your session has expired. Please try again later." msgstr "" @@ -6467,190 +5845,186 @@ msgid "The MXit ID you entered is already registered. Please choose another." msgstr "" -#, fuzzy msgid "Internal error. Please try again later." -msgstr "The server is unavailable; try again later" +msgstr "" msgid "You did not enter the security code" msgstr "" -#, fuzzy msgid "Security Code" -msgstr "Security Enabled" +msgstr "" #. ask for input (required) -#, fuzzy msgid "Enter Security Code" -msgstr "Change Password" - -#, fuzzy +msgstr "" + msgid "Your Country" -msgstr "Country" - -#, fuzzy +msgstr "" + msgid "Your Language" -msgstr "Preferred Language" +msgstr "" #. display the form to the user and wait for his/her input -#, fuzzy msgid "MXit Authorization" -msgstr "Request Authorization" +msgstr "" msgid "MXit account validation" msgstr "" -#, fuzzy msgid "Retrieving User Information..." -msgstr "Server Information" - -#, fuzzy +msgstr "" + +msgid "was kicked" +msgstr "" + +msgid "You have been kicked from this MultiMX." +msgstr "" + +msgid "_Room Name:" +msgstr "" + +#. Display system message in chat window +msgid "You have invited" +msgstr "" + msgid "Loading menu..." -msgstr "Logging" - -#, fuzzy +msgstr "" + msgid "Status Message" -msgstr "Send Message" - -#, fuzzy +msgstr "" + msgid "Rejection Message" -msgstr "Send Message" +msgstr "" #. hidden number -#, fuzzy msgid "Hidden Number" -msgstr "Middle Name" - -#, fuzzy +msgstr "" + +msgid "No profile available" +msgstr "" + +msgid "This contact does not have a profile." +msgstr "" + msgid "Your MXit ID..." -msgstr "Yahoo! ID" +msgstr "" + +#. contact is in Deleted, Rejected or None state +msgid "Re-Invite" +msgstr "" #. Configuration options #. WAP server (reference: "libpurple/accountopt.h") -#, fuzzy msgid "WAP Server" -msgstr "Server" - -#, fuzzy +msgstr "" + msgid "Connect via HTTP" -msgstr "Connecting" +msgstr "" msgid "Enable splash-screen popup" msgstr "" -#. you were kicked -#, fuzzy -msgid "You have been kicked from this MultiMX." -msgstr "You have been kicked by %s: (%s)" - -#, fuzzy -msgid "was kicked" -msgstr "Bad ticket" - -#, fuzzy -msgid "_Room Name:" -msgstr "_Room:" - -#. Display system message in chat window -#, fuzzy -msgid "You have invited" -msgstr "You have been kicked by %s: (%s)" - -#, fuzzy msgid "Last Online" -msgstr "Online" +msgstr "" + +msgid "Invite Message" +msgstr "" + +msgid "No results" +msgstr "" + +msgid "No contacts found." +msgstr "" + +#. define columns +msgid "UserId" +msgstr "" + +msgid "Where I live" +msgstr "" + +#, c-format +msgid "You have %i suggested friends." +msgstr "" + +#, c-format +msgid "We found %i contacts that match your search." +msgstr "" #. we must have lost the connection, so terminate it so that we can reconnect -#, fuzzy msgid "We have lost the connection to MXit. Please reconnect." -msgstr "You have been disconnected from chat room %s." +msgstr "" #. packet could not be queued for transmission -#, fuzzy msgid "Message Send Error" -msgstr "XMPP Message Error" - -#, fuzzy +msgstr "" + msgid "Unable to process your request at this time" -msgstr "Unable to ping server" +msgstr "" msgid "Timeout while waiting for a response from the MXit server." msgstr "" -#, fuzzy msgid "Successfully Logged In..." -msgstr "Telephone Number" +msgstr "" #, c-format msgid "" "%s sent you an encrypted message, but it is not supported on this client." msgstr "" -#, fuzzy msgid "Message Error" -msgstr "XMPP Message Error" +msgstr "" msgid "Cannot perform redirect using the specified protocol" msgstr "" -#, fuzzy msgid "An internal MXit server error occurred." -msgstr "An unknown signon error has occurred: %s." - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Login error: %s (%i)" -msgstr "Read error" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Logout error: %s (%i)" -msgstr "Read error" - -#, fuzzy +msgstr "" + msgid "Contact Error" -msgstr "Connection Error" - -#, fuzzy +msgstr "" + msgid "Message Sending Error" -msgstr "XMPP Message Error" - -#, fuzzy +msgstr "" + msgid "Status Error" -msgstr "Stream Error" - -#, fuzzy +msgstr "" + msgid "Mood Error" -msgstr "Unknown Error" - -#, fuzzy +msgstr "" + msgid "Invitation Error" -msgstr "Registration Error" - -#, fuzzy +msgstr "" + msgid "Contact Removal Error" -msgstr "Connection Error" - -#, fuzzy +msgstr "" + msgid "Subscription Error" -msgstr "Subscription" - -#, fuzzy +msgstr "" + msgid "Contact Update Error" -msgstr "Connection Error" - -#, fuzzy +msgstr "" + msgid "File Transfer Error" -msgstr "File Transfers" - -#, fuzzy +msgstr "" + msgid "Cannot create MultiMx room" -msgstr "Cannot change nick" - -#, fuzzy +msgstr "" + msgid "MultiMx Invitation Error" -msgstr "Registration Error" - -#, fuzzy +msgstr "" + msgid "Profile Error" -msgstr "Write error" +msgstr "" #. bad packet msgid "Invalid packet received from MXit." @@ -6680,54 +6054,44 @@ msgstr "" msgid "In Love" -msgstr "In Love" - -#, fuzzy +msgstr "" + msgid "Pending" -msgstr "Send" - -#, fuzzy +msgstr "" + msgid "Invited" -msgstr "Invite" - -#, fuzzy +msgstr "" + msgid "Rejected" -msgstr "Reset" - -#, fuzzy +msgstr "" + msgid "Deleted" -msgstr "Delete" +msgstr "" msgid "MXit Advertising" msgstr "" -#, fuzzy msgid "More Information" -msgstr "Work Information" +msgstr "" #, c-format msgid "No such user: %s" msgstr "" -#, fuzzy msgid "User lookup" -msgstr "User Rooms" - -#, fuzzy +msgstr "" + msgid "Reading challenge" -msgstr "Reading data" - -#, fuzzy +msgstr "" + msgid "Unexpected challenge length from server" -msgstr "Invalid challenge from server" - -#, fuzzy +msgstr "" + msgid "Logging in" -msgstr "Logging" - -#, fuzzy +msgstr "" + msgid "MySpaceIM - No Username Set" -msgstr "No screenname given." +msgstr "" msgid "You appear to have no MySpace username." msgstr "" @@ -6735,16 +6099,14 @@ msgid "Would you like to set one now? (Note: THIS CANNOT BE CHANGED!)" msgstr "" -#, fuzzy msgid "Lost connection with server" -msgstr "You were disconnected from the server." +msgstr "" #. Can't write _()'d strings in array initializers. Workaround. #. khc: then use N_() in the array initializer and use _() when they are #. used -#, fuzzy msgid "New mail messages" -msgstr "New away message" +msgstr "" msgid "New blog comments" msgstr "" @@ -6761,9 +6123,8 @@ msgid "MySpace" msgstr "" -#, fuzzy msgid "IM Friends" -msgstr "_IM windows" +msgstr "" #, c-format msgid "" @@ -6773,11 +6134,9 @@ "%d buddies were added or updated from the server (including buddies already " "on the server-side list)" msgstr[0] "" -msgstr[1] "" - -#, fuzzy + msgid "Add contacts from server" -msgstr "Invalid response from server." +msgstr "" #, c-format msgid "Protocol error, code %d: %s" @@ -6790,39 +6149,32 @@ "cfm?fuseaction=accountSettings.changePassword and try again." msgstr "" -#, fuzzy msgid "Incorrect username or password" -msgstr "Incorrect nickname or password." +msgstr "" msgid "MySpaceIM Error" msgstr "" -#, fuzzy msgid "Invalid input condition" -msgstr "Finalizing connection" - -#, fuzzy +msgstr "" + msgid "Failed to add buddy" -msgstr "Failed to join buddy in chat" - -#, fuzzy +msgstr "" + msgid "'addbuddy' command failed." -msgstr "Import Buddy List from Server" - -#, fuzzy +msgstr "" + msgid "persist command failed" -msgstr "Switchboard failed" - -#, fuzzy +msgstr "" + msgid "Failed to remove buddy" -msgstr "Failed to join buddy in chat" +msgstr "" msgid "'delbuddy' command failed" msgstr "" -#, fuzzy msgid "blocklist command failed" -msgstr "Switchboard failed" +msgstr "" msgid "Missing Cipher" msgstr "" @@ -6838,17 +6190,15 @@ msgid "Add friends from MySpace.com" msgstr "" -#, fuzzy msgid "Importing friends failed" -msgstr "Bad friend file" +msgstr "" #. TODO: find out how msgid "Find people..." msgstr "" -#, fuzzy msgid "Change IM name..." -msgstr "Change Password..." +msgstr "" msgid "myim URL handler" msgstr "" @@ -6862,39 +6212,32 @@ msgid "Show display name in status text" msgstr "" -#, fuzzy msgid "Show headline in status text" -msgstr "Show _aliases in tabs/titles" - -#, fuzzy +msgstr "" + msgid "Send emoticons" -msgstr "Sound Options" +msgstr "" msgid "Screen resolution (dots per inch)" msgstr "" -#, fuzzy msgid "Base font size (points)" -msgstr "Larger font size" - -#, fuzzy +msgstr "" + msgid "User" -msgstr "Users" - -#, fuzzy +msgstr "" + msgid "Headline" -msgstr "Decline" - -#, fuzzy +msgstr "" + msgid "Song" -msgstr "_Sorting:" +msgstr "" msgid "Total Friends" msgstr "" -#, fuzzy msgid "Client Version" -msgstr "Close conversation" +msgstr "" msgid "" "An error occurred while trying to set the username. Please try again, or " @@ -6902,9 +6245,8 @@ "to set your username." msgstr "" -#, fuzzy msgid "MySpaceIM - Username Available" -msgstr "Service Unavailable" +msgstr "" msgid "This username is available. Would you like to set it?" msgstr "" @@ -6915,18 +6257,15 @@ msgid "MySpaceIM - Please Set a Username" msgstr "" -#, fuzzy msgid "This username is unavailable." -msgstr "This theme has no available smileys." - -#, fuzzy +msgstr "" + msgid "Please try another username:" -msgstr "Please enter a new name for the selected group." +msgstr "" #. Protocol won't log in now without a username set.. Disconnect -#, fuzzy msgid "No username set" -msgstr "No screenname given." +msgstr "" msgid "Please enter a username to check its availability:" msgstr "" @@ -6949,13 +6288,12 @@ msgstr "" #. Whack means "to hit or strike someone with a sharp blow" -#, fuzzy msgid "Whack" -msgstr "Back" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "%s has whacked you!" -msgstr "The user has blocked you" +msgstr "" #, c-format msgid "Whacking %s..." @@ -6964,13 +6302,12 @@ #. Torch means "to set on fire." Don't worry, this doesn't #. * make a whole lot of sense in English, either. Feel free #. * to translate it literally. -#, fuzzy msgid "Torch" -msgstr "Topic" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "%s has torched you!" -msgstr "The user has blocked you" +msgstr "" #, c-format msgid "Torching %s..." @@ -6980,9 +6317,9 @@ msgid "Smooch" msgstr "" -#, fuzzy, c-format +#, c-format msgid "%s has smooched you!" -msgstr "The user has blocked you" +msgstr "" #, c-format msgid "Smooching %s..." @@ -6992,39 +6329,37 @@ msgid "Hug" msgstr "" -#, fuzzy, c-format +#, c-format msgid "%s has hugged you!" -msgstr "%s has gone away." +msgstr "" #, c-format msgid "Hugging %s..." msgstr "" #. Slap means "to hit someone with an open/flat hand" -#, fuzzy msgid "Slap" -msgstr "Slovak" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "%s has slapped you!" -msgstr "%s has stopped typing to you (%s)" +msgstr "" #, c-format msgid "Slapping %s..." msgstr "" #. Goose means "to pinch someone on their butt" -#, fuzzy msgid "Goose" -msgstr "Gone" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "%s has goosed you!" -msgstr "%s has gone away." - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Goosing %s..." -msgstr "Looking up %s" +msgstr "" #. A high-five is when two people's hands slap each other #. * in the air above their heads. It is done to celebrate @@ -7032,9 +6367,9 @@ msgid "High-five" msgstr "" -#, fuzzy, c-format +#, c-format msgid "%s has high-fived you!" -msgstr "%s has signed on (%s)" +msgstr "" #, c-format msgid "High-fiving %s..." @@ -7073,189 +6408,177 @@ msgstr "" msgid "Required parameters not passed in" -msgstr "Required parameters not passed in" +msgstr "" msgid "Unable to write to network" -msgstr "Unable to write to network" +msgstr "" msgid "Unable to read from network" -msgstr "Unable to read from network" +msgstr "" msgid "Error communicating with server" -msgstr "Error communicating with server" +msgstr "" msgid "Conference not found" -msgstr "Conference not found" +msgstr "" msgid "Conference does not exist" -msgstr "Conference does not exist" +msgstr "" msgid "A folder with that name already exists" -msgstr "A folder with that name already exists" +msgstr "" msgid "Not supported" -msgstr "Not supported" +msgstr "" msgid "Password has expired" -msgstr "Password has expired" - -#, fuzzy +msgstr "" + msgid "Incorrect password" -msgstr "Incorrect password." +msgstr "" msgid "Account has been disabled" -msgstr "Account has been disabled" +msgstr "" msgid "The server could not access the directory" -msgstr "The server could not access the directory" +msgstr "" msgid "Your system administrator has disabled this operation" -msgstr "Your system administrator has disabled this operation" +msgstr "" msgid "The server is unavailable; try again later" -msgstr "The server is unavailable; try again later" +msgstr "" msgid "Cannot add a contact to the same folder twice" -msgstr "Cannot add a contact to the same folder twice" +msgstr "" msgid "Cannot add yourself" -msgstr "Cannot add yourself" +msgstr "" msgid "Master archive is misconfigured" -msgstr "Master archive is misconfigured" - -#, fuzzy +msgstr "" + msgid "Could not recognize the host of the username you entered" -msgstr "Could not recognize the host of the username you entered" - -#, fuzzy +msgstr "" + msgid "" "Your account has been disabled because too many incorrect passwords were " "entered" msgstr "" -"Your account has been disabled because too many invalid passwords were " -"entered" msgid "You cannot add the same person twice to a conversation" -msgstr "You cannot add the same person twice to a conversation" +msgstr "" msgid "You have reached your limit for the number of contacts allowed" -msgstr "You have reached your limit for the number of contacts allowed" - -#, fuzzy +msgstr "" + msgid "You have entered an incorrect username" -msgstr "You have entered an invalid username" +msgstr "" msgid "An error occurred while updating the directory" -msgstr "An error occurred while updating the directory" +msgstr "" msgid "Incompatible protocol version" -msgstr "Incompatible protocol version" +msgstr "" msgid "The user has blocked you" -msgstr "The user has blocked you" +msgstr "" msgid "" "This evaluation version does not allow more than ten users to log in at one " "time" msgstr "" -"This evaluation version does not allow more than ten users to log in at one " -"time" msgid "The user is either offline or you are blocked" -msgstr "The user is either offline or you are blocked" +msgstr "" #, c-format msgid "Unknown error: 0x%X" -msgstr "Unknown error: 0x%X" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Unable to login: %s" -msgstr "Unable to ban user %s" +msgstr "" #, c-format msgid "Unable to send message. Could not get details for user (%s)." -msgstr "Unable to send message. Could not get details for user (%s)." +msgstr "" #, c-format msgid "Unable to add %s to your buddy list (%s)." -msgstr "Unable to add %s to your buddy list (%s)." +msgstr "" #. TODO: Improve this! message to who or for what conference? #, c-format msgid "Unable to send message (%s)." -msgstr "Unable to send message (%s)." +msgstr "" #, c-format msgid "Unable to invite user (%s)." -msgstr "Unable to invite user (%s)." +msgstr "" #, c-format msgid "Unable to send message to %s. Could not create the conference (%s)." -msgstr "Unable to send message to %s. Could not create the conference (%s)." +msgstr "" #, c-format msgid "Unable to send message. Could not create the conference (%s)." -msgstr "Unable to send message. Could not create the conference (%s)." +msgstr "" #, c-format msgid "" "Unable to move user %s to folder %s in the server side list. Error while " "creating folder (%s)." msgstr "" -"Unable to move user %s to folder %s in the server side list. Error while " -"creating folder (%s)." #, c-format msgid "" "Unable to add %s to your buddy list. Error creating folder in server side " "list (%s)." msgstr "" -"Unable to add %s to your buddy list. Error creating folder in server side " -"list (%s)." #, c-format msgid "Could not get details for user %s (%s)." -msgstr "Could not get details for user %s (%s)." +msgstr "" #, c-format msgid "Unable to add user to privacy list (%s)." -msgstr "Unable to add user to privacy list (%s)." +msgstr "" #, c-format msgid "Unable to add %s to deny list (%s)." -msgstr "Unable to add %s to deny list (%s)." +msgstr "" #, c-format msgid "Unable to add %s to permit list (%s)." -msgstr "Unable to add %s to permit list (%s)." +msgstr "" #, c-format msgid "Unable to remove %s from privacy list (%s)." -msgstr "Unable to remove %s from privacy list (%s)." +msgstr "" #, c-format msgid "Unable to change server side privacy settings (%s)." -msgstr "Unable to change server side privacy settings (%s)." +msgstr "" #, c-format msgid "Unable to create conference (%s)." -msgstr "Unable to create conference (%s)." +msgstr "" msgid "Error communicating with server. Closing connection." -msgstr "Error communicating with server. Closing connection." +msgstr "" msgid "Telephone Number" -msgstr "Telephone Number" +msgstr "" msgid "Personal Title" -msgstr "Personal Title" +msgstr "" msgid "Mailstop" -msgstr "Mailstop" +msgstr "" msgid "User ID" -msgstr "User ID" +msgstr "" #. tag = _("DN"); #. value = nm_user_record_get_dn(user_record); @@ -7264,24 +6587,24 @@ #. } #. msgid "Full name" -msgstr "Full name" +msgstr "" #, c-format msgid "GroupWise Conference %d" -msgstr "GroupWise Conference %d" +msgstr "" msgid "Authenticating..." -msgstr "Authenticating..." +msgstr "" msgid "Waiting for response..." -msgstr "Waiting for response..." +msgstr "" #, c-format msgid "%s has been invited to this conversation." -msgstr "%s has been invited to this conversation." +msgstr "" msgid "Invitation to Conversation" -msgstr "Invitation to Conversation" +msgstr "" #, c-format msgid "" @@ -7289,29 +6612,22 @@ "\n" "Sent: %s" msgstr "" -"Invitation from: %s\n" -"\n" -"Sent: %s" msgid "Would you like to join the conversation?" -msgstr "Would you like to join the conversation?" +msgstr "" #, c-format msgid "" "%s appears to be offline and did not receive the message that you just sent." msgstr "" -"%s appears to be offline and did not receive the message that you just sent." - -#, fuzzy + msgid "" "Unable to connect to server. Please enter the address of the server to which " "you wish to connect." msgstr "" -"Unable to connect to server. Please enter the address of the server you wish " -"to connect to." msgid "This conference has been closed. No more messages can be sent." -msgstr "This conference has been closed. No more messages can be sent." +msgstr "" #. *< type #. *< ui_requirement @@ -7324,37 +6640,41 @@ #. * summary #. * description msgid "Novell GroupWise Messenger Protocol Plugin" -msgstr "Novell GroupWise Messenger Protocol Plugin" +msgstr "" msgid "Server address" -msgstr "Server address" +msgstr "" msgid "Server port" -msgstr "Server port" +msgstr "" msgid "Please authorize me so I can add you to my buddy list." -msgstr "Please authorize me so I can add you to my buddy list." +msgstr "" msgid "No reason given." -msgstr "No reason given." +msgstr "" msgid "Authorization Denied Message:" -msgstr "Authorization Denied Message:" - -#, fuzzy, c-format +msgstr "" + +#. * +#. * A wrapper for purple_request_action() that uses @c OK and @c Cancel buttons. +#. +msgid "_OK" +msgstr "" + +#, c-format msgid "Received unexpected response from %s: %s" -msgstr "Invalid response from server." - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Received unexpected response from %s" -msgstr "Invalid response from server." +msgstr "" msgid "" "You have been connecting and disconnecting too frequently. Wait ten minutes " "and try again. If you continue to try, you will need to wait even longer." msgstr "" -"You have been connecting and disconnecting too frequently. Wait ten minutes " -"and try again. If you continue to try, you will need to wait even longer." msgid "" "You required encryption in your account settings, but one of the servers " @@ -7363,15 +6683,12 @@ #. Note to translators: The first %s is a URL, the second is an #. error message. -#, fuzzy, c-format +#, c-format msgid "Error requesting %s: %s" -msgstr "Error creating connection" - -#, fuzzy +msgstr "" + msgid "The server returned an empty response" msgstr "" -"Unable to connect to server. Please enter the address of the server you wish " -"to connect to." msgid "" "Server requested that you fill out a CAPTCHA in order to sign in, but this " @@ -7388,24 +6705,20 @@ "your AIM/ICQ account.)" msgstr "" -#, fuzzy, c-format +#, c-format msgid "" "(There was an error receiving this message. Either you and %s have " "different encodings selected, or %s has a buggy client.)" msgstr "" -"(There was an error receiving this message. The buddy you are speaking to " -"most likely has a buggy client.)" - -#, fuzzy + msgid "Could not join chat room" -msgstr "Could not connect" - -#, fuzzy +msgstr "" + msgid "Invalid chat room name" -msgstr "Invalid Room Name" +msgstr "" msgid "Invalid error" -msgstr "Invalid error" +msgstr "" msgid "Cannot receive IM due to parental controls" msgstr "" @@ -7413,14 +6726,12 @@ msgid "Cannot send SMS without accepting terms" msgstr "" -#, fuzzy msgid "Cannot send SMS" -msgstr "Cannot send file" +msgstr "" #. SMS_WITHOUT_DISCLAIMER is weird -#, fuzzy msgid "Cannot send SMS to this country" -msgstr "Cannot send a directory." +msgstr "" #. Undocumented msgid "Cannot send SMS to unknown country" @@ -7441,55 +6752,48 @@ msgid "Bot account reached monthly IM limit" msgstr "" -#, fuzzy msgid "Unable to receive offline messages" -msgstr "Unable to send message." - -#, fuzzy +msgstr "" + msgid "Offline message store full" -msgstr "Offline " - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Unable to send message: %s (%s)" -msgstr "Unable to send message (%s)." +msgstr "" #, c-format msgid "Unable to send message: %s" -msgstr "Unable to send message: %s" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Unable to send message to %s: %s (%s)" -msgstr "Unable to send message to %s:" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Unable to send message to %s: %s" -msgstr "Unable to send message to %s:" +msgstr "" msgid "Thinking" msgstr "" -#, fuzzy msgid "Shopping" -msgstr "Buddy stops t_yping" - -#, fuzzy +msgstr "" + msgid "Questioning" -msgstr "Request ambiguous" - -#, fuzzy +msgstr "" + msgid "Eating" -msgstr "Paging" +msgstr "" msgid "Watching a movie" msgstr "" -#, fuzzy msgid "Typing" -msgstr "Ping" - -#, fuzzy +msgstr "" + msgid "At the office" -msgstr "Not In Office" +msgstr "" msgid "Taking a bath" msgstr "" @@ -7500,75 +6804,62 @@ msgid "Having fun" msgstr "" -#, fuzzy msgid "Sleeping" -msgstr "Sleepy" +msgstr "" msgid "Using a PDA" msgstr "" -#, fuzzy msgid "Meeting friends" -msgstr "_IM windows" - -#, fuzzy +msgstr "" + msgid "On the phone" -msgstr "On The Phone" +msgstr "" msgid "Surfing" msgstr "" #. "I am mobile." / "John is mobile." -#, fuzzy msgid "Mobile" -msgstr "Mobile Phone" - -#, fuzzy +msgstr "" + msgid "Searching the web" -msgstr "Warn the user" - -#, fuzzy +msgstr "" + msgid "At a party" -msgstr "Auth port" +msgstr "" msgid "Having Coffee" msgstr "" #. Playing video games -#, fuzzy msgid "Gaming" -msgstr "User Limit" +msgstr "" msgid "Browsing the web" msgstr "" -#, fuzzy msgid "Smoking" -msgstr "_Sorting:" - -#, fuzzy +msgstr "" + msgid "Writing" -msgstr "Warn" +msgstr "" #. Drinking [Alcohol] -#, fuzzy msgid "Drinking" -msgstr "Warn" +msgstr "" msgid "Listening to music" msgstr "" -#, fuzzy msgid "Studying" -msgstr "Send" - -#, fuzzy +msgstr "" + msgid "In the restroom" -msgstr "_Insert" - -#, fuzzy +msgstr "" + msgid "Received invalid data on connection with server" -msgstr "Unable to make SSL connection to server." +msgstr "" #. *< type #. *< ui_requirement @@ -7580,13 +6871,11 @@ #. *< version #. * summary #. * description -#, fuzzy msgid "AIM Protocol Plugin" -msgstr "AIM/ICQ Protocol Plugin" - -#, fuzzy +msgstr "" + msgid "ICQ UIN..." -msgstr "ICQ UIN" +msgstr "" #. *< type #. *< ui_requirement @@ -7598,20 +6887,17 @@ #. *< version #. * summary #. * description -#, fuzzy msgid "ICQ Protocol Plugin" -msgstr "IRC Protocol Plugin" +msgstr "" msgid "Encoding" -msgstr "Encoding" - -#, fuzzy +msgstr "" + msgid "The remote user has closed the connection." -msgstr "The remote user is not present in the network any more" - -#, fuzzy +msgstr "" + msgid "The remote user has declined your request." -msgstr "The user has blocked you" +msgstr "" #, c-format msgid "Lost connection with the remote user:
%s" @@ -7620,13 +6906,11 @@ msgid "Received invalid data on connection with remote user." msgstr "" -#, fuzzy msgid "Unable to establish a connection with the remote user." -msgstr "Unable to make SSL connection to server." - -#, fuzzy +msgstr "" + msgid "Direct IM established" -msgstr "Direct IM with %s established" +msgstr "" #, c-format msgid "" @@ -7639,148 +6923,124 @@ msgstr "" msgid "Free For Chat" -msgstr "Free For Chat" +msgstr "" msgid "Not Available" -msgstr "Not Available" +msgstr "" msgid "Occupied" -msgstr "Occupied" +msgstr "" msgid "Web Aware" -msgstr "Web Aware" +msgstr "" msgid "Invisible" -msgstr "Invisible" - -#, fuzzy +msgstr "" + msgid "Evil" -msgstr "Email" - -#, fuzzy +msgstr "" + msgid "Depression" -msgstr "Progress" - -#, fuzzy +msgstr "" + msgid "At home" -msgstr "About Pidgin" - -#, fuzzy +msgstr "" + msgid "At work" -msgstr "Network" - -#, fuzzy +msgstr "" + msgid "At lunch" -msgstr "Out To Lunch" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Unable to connect to authentication server: %s" -msgstr "Could not connect for transfer." - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Unable to connect to BOS server: %s" -msgstr "Unable to connect to server." - -#, fuzzy +msgstr "" + msgid "Username sent" -msgstr "No screenname given." +msgstr "" msgid "Connection established, cookie sent" -msgstr "Connection established, cookie sent" +msgstr "" #. TODO: Don't call this with ssi msgid "Finalizing connection" -msgstr "Finalizing connection" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "" "Unable to sign on as %s because the username is invalid. Usernames must be " "a valid email address, or start with a letter and contain only letters, " "numbers and spaces, or contain only numbers." msgstr "" -"Unable to login: Could not sign on as %s because the screen name is " -"invalid. Screen names must either start with a letter and contain only " -"letters, numbers and spaces, or contain only numbers." msgid "" "You required encryption in your account settings, but encryption is not " "supported by your system." msgstr "" -#, fuzzy, c-format +#, c-format msgid "You may be disconnected shortly. If so, check %s for updates." msgstr "" -"You may be disconnected shortly. You may want to use TOC until this is " -"fixed. Check %s for updates." - -#, fuzzy + msgid "Unable to get a valid AIM login hash." -msgstr "Pidgin was unable to get a valid AIM login hash." - -#, fuzzy +msgstr "" + msgid "Unable to get a valid login hash." -msgstr "Pidgin was unable to get a valid login hash." +msgstr "" msgid "Received authorization" -msgstr "Received authorization" +msgstr "" #. Unregistered username -#. uid is not exist #. the username does not exist -#, fuzzy msgid "Username does not exist" -msgstr "User does not exist" +msgstr "" #. Suspended account -#, fuzzy msgid "Your account is currently suspended" -msgstr "Your account is currently suspended." +msgstr "" #. service temporarily unavailable msgid "The AOL Instant Messenger service is temporarily unavailable." -msgstr "The AOL Instant Messenger service is temporarily unavailable." +msgstr "" #. username connecting too frequently -#, fuzzy msgid "" "Your username has been connecting and disconnecting too frequently. Wait ten " "minutes and try again. If you continue to try, you will need to wait even " "longer." msgstr "" -"You have been connecting and disconnecting too frequently. Wait ten minutes " -"and try again. If you continue to try, you will need to wait even longer." #. client too old #, c-format msgid "The client version you are using is too old. Please upgrade at %s" -msgstr "The client version you are using is too old. Please upgrade at %s" +msgstr "" #. IP address connecting too frequently -#, fuzzy msgid "" "Your IP address has been connecting and disconnecting too frequently. Wait a " "minute and try again. If you continue to try, you will need to wait even " "longer." msgstr "" -"You have been connecting and disconnecting too frequently. Wait ten minutes " -"and try again. If you continue to try, you will need to wait even longer." - -#, fuzzy + msgid "The SecurID key entered is invalid" -msgstr "The SecurID key entered is invalid." +msgstr "" msgid "Enter SecurID" -msgstr "Enter SecurID" +msgstr "" msgid "Enter the 6 digit number from the digital display." -msgstr "Enter the 6-digit number from the digital display." +msgstr "" msgid "Password sent" -msgstr "Password sent" - -#, fuzzy +msgstr "" + msgid "Unable to initialize connection" -msgstr "Unable to create new connection." +msgstr "" #, c-format msgid "" @@ -7788,17 +7048,14 @@ "following reason:\n" "%s" msgstr "" -"The user %u has denied your request to add them to your buddy list for the " -"following reason:\n" -"%s" msgid "ICQ authorization denied." -msgstr "ICQ authorization denied." +msgstr "" #. Someone has granted you authorization #, c-format msgid "The user %u has granted your request to add them to your buddy list." -msgstr "The user %u has granted your request to add them to your buddy list." +msgstr "" #, c-format msgid "" @@ -7807,10 +7064,6 @@ "From: %s [%s]\n" "%s" msgstr "" -"You have received a special message\n" -"\n" -"From: %s [%s]\n" -"%s" #, c-format msgid "" @@ -7819,10 +7072,6 @@ "From: %s [%s]\n" "%s" msgstr "" -"You have received an ICQ page\n" -"\n" -"From: %s [%s]\n" -"%s" #, c-format msgid "" @@ -7831,37 +7080,29 @@ "Message is:\n" "%s" msgstr "" -"You have received an ICQ email from %s [%s]\n" -"\n" -"Message is:\n" -"%s" #, c-format msgid "ICQ user %u has sent you a buddy: %s (%s)" -msgstr "ICQ user %u has sent you a buddy: %s (%s)" +msgstr "" msgid "Do you want to add this buddy to your buddy list?" -msgstr "Do you want to add this buddy to your buddy list?" - -#, fuzzy +msgstr "" + msgid "_Add" -msgstr "Add" - -#, fuzzy +msgstr "" + msgid "_Decline" -msgstr "Decline" +msgstr "" #, c-format msgid "You missed %hu message from %s because it was invalid." msgid_plural "You missed %hu messages from %s because they were invalid." -msgstr[0] "You missed %hu message from %s because it was invalid." -msgstr[1] "You missed %hu messages from %s because they were invalid." +msgstr[0] "" #, c-format msgid "You missed %hu message from %s because it was too large." msgid_plural "You missed %hu messages from %s because they were too large." -msgstr[0] "You missed %hu message from %s because it was too large." -msgstr[1] "You missed %hu messages from %s because they were too large." +msgstr[0] "" #, c-format msgid "" @@ -7869,136 +7110,119 @@ msgid_plural "" "You missed %hu messages from %s because the rate limit has been exceeded." msgstr[0] "" -"You missed %hu message from %s because the rate limit has been exceeded." -msgstr[1] "" -"You missed %hu messages from %s because the rate limit has been exceeded." - -#, fuzzy, c-format + +#, c-format msgid "" "You missed %hu message from %s because his/her warning level is too high." msgid_plural "" "You missed %hu messages from %s because his/her warning level is too high." -msgstr[0] "You missed %hu message from %s because he/she was too evil." -msgstr[1] "You missed %hu messages from %s because he/she was too evil." - -#, fuzzy, c-format +msgstr[0] "" + +#, c-format msgid "You missed %hu message from %s because your warning level is too high." msgid_plural "" "You missed %hu messages from %s because your warning level is too high." -msgstr[0] "You missed %hu message from %s because you are too evil." -msgstr[1] "You missed %hu messages from %s because you are too evil." +msgstr[0] "" #, c-format msgid "You missed %hu message from %s for an unknown reason." msgid_plural "You missed %hu messages from %s for an unknown reason." -msgstr[0] "You missed %hu message from %s for an unknown reason." -msgstr[1] "You missed %hu messages from %s for an unknown reason." +msgstr[0] "" msgid "Your AIM connection may be lost." -msgstr "Your AIM connection may be lost." +msgstr "" #, c-format msgid "You have been disconnected from chat room %s." -msgstr "You have been disconnected from chat room %s." +msgstr "" + +msgid "The new formatting is invalid." +msgstr "" + +msgid "Username formatting can change only capitalization and whitespace." +msgstr "" msgid "Pop-Up Message" -msgstr "Pop-Up Message" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "The following username is associated with %s" msgid_plural "The following usernames are associated with %s" -msgstr[0] "The following screen names are associated with %s" -msgstr[1] "The following screen names are associated with %s" +msgstr[0] "" #, c-format msgid "No results found for email address %s" -msgstr "No results found for email address %s" +msgstr "" #, c-format msgid "You should receive an email asking to confirm %s." -msgstr "You should receive an email asking to confirm %s." +msgstr "" msgid "Account Confirmation Requested" -msgstr "Account Confirmation Requested" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "" "Error 0x%04x: Unable to format username because the requested name differs " "from the original." msgstr "" -"Error 0x%04x: Unable to format screen name because the requested screen name " -"differs from the original." - -#, fuzzy, c-format + +#, c-format msgid "Error 0x%04x: Unable to format username because it is invalid." msgstr "" -"Error 0x%04x: Unable to format screen name because the requested screen name " -"is too long." - -#, fuzzy, c-format + +#, c-format msgid "" "Error 0x%04x: Unable to format username because the requested name is too " "long." msgstr "" -"Error 0x%04x: Unable to format screen name because the requested screen name " -"is too long." - -#, fuzzy, c-format + +#, c-format msgid "" "Error 0x%04x: Unable to change email address because there is already a " "request pending for this username." msgstr "" -"Error 0x%04x: Unable to change email address because there is already a " -"request pending for this screen name." - -#, fuzzy, c-format + +#, c-format msgid "" "Error 0x%04x: Unable to change email address because the given address has " "too many usernames associated with it." msgstr "" -"Error 0x%04x: Unable to change email address because the given address has " -"too many screen names associated with it." #, c-format msgid "" "Error 0x%04x: Unable to change email address because the given address is " "invalid." msgstr "" -"Error 0x%04x: Unable to change email address because the given address is " -"invalid." #, c-format msgid "Error 0x%04x: Unknown error." -msgstr "Error 0x%04x: Unknown error." +msgstr "" msgid "Error Changing Account Info" -msgstr "Error Changing Account Info" +msgstr "" #, c-format msgid "The email address for %s is %s" -msgstr "The email address for %s is %s" +msgstr "" msgid "Account Info" -msgstr "Account Info" +msgstr "" msgid "" "Your IM Image was not sent. You must be Direct Connected to send IM Images." msgstr "" -"Your IM Image was not sent. You must be Direct Connected to send IM Images." msgid "Unable to set AIM profile." -msgstr "Unable to set AIM profile." +msgstr "" msgid "" "You have probably requested to set your profile before the login procedure " "completed. Your profile remains unset; try setting it again when you are " "fully connected." msgstr "" -"You have probably requested to set your profile before the login procedure " -"completed. Your profile remains unset; try setting it again when you are " -"fully connected." - -#, fuzzy, c-format + +#, c-format msgid "" "The maximum profile length of %d byte has been exceeded. It has been " "truncated for you." @@ -8006,16 +7230,11 @@ "The maximum profile length of %d bytes has been exceeded. It has been " "truncated for you." msgstr[0] "" -"The maximum profile length of %d byte has been exceeded. Pidgin has " -"truncated it for you." -msgstr[1] "" -"The maximum profile length of %d bytes has been exceeded. Pidgin has " -"truncated it for you." msgid "Profile too long." -msgstr "Profile too long." - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "" "The maximum away message length of %d byte has been exceeded. It has been " "truncated for you." @@ -8023,74 +7242,57 @@ "The maximum away message length of %d bytes has been exceeded. It has been " "truncated for you." msgstr[0] "" -"The maximum away message length of %d byte has been exceeded. Pidgin has " -"truncated it for you." -msgstr[1] "" -"The maximum away message length of %d bytes has been exceeded. Pidgin has " -"truncated it for you." msgid "Away message too long." -msgstr "Away message too long." - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "" "Unable to add the buddy %s because the username is invalid. Usernames must " "be a valid email address, or start with a letter and contain only letters, " "numbers and spaces, or contain only numbers." msgstr "" -"Could not add the buddy %s because the screen name is invalid. Screen names " -"must either start with a letter and contain only letters, numbers and " -"spaces, or contain only numbers." - -#, fuzzy + msgid "Unable to Retrieve Buddy List" -msgstr "Unable To Retrieve Buddy List" - -#, fuzzy +msgstr "" + msgid "" "The AIM servers were temporarily unable to send your buddy list. Your buddy " "list is not lost, and will probably become available in a few minutes." msgstr "" -"Pidgin was temporarily unable to retrieve your buddy list from the AIM " -"servers. Your buddy list is not lost, and will probably become available in " -"a few hours." msgid "Orphans" -msgstr "Orphans" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "" "Unable to add the buddy %s because you have too many buddies in your buddy " "list. Please remove one and try again." msgstr "" -"Could not add the buddy %s because you have too many buddies in your buddy " -"list. Please remove one and try again." msgid "(no name)" -msgstr "(no name)" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Unable to add the buddy %s for an unknown reason." -msgstr "Your command failed for an unknown reason." - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "" "The user %s has given you permission to add him or her to your buddy list. " "Do you want to add this user?" msgstr "" -"The user %s has given you permission to add you to their buddy list. Do you " -"want to add them?" msgid "Authorization Given" -msgstr "Authorization Given" +msgstr "" #. Granted #, c-format msgid "The user %s has granted your request to add them to your buddy list." -msgstr "The user %s has granted your request to add them to your buddy list." +msgstr "" msgid "Authorization Granted" -msgstr "Authorization Granted" +msgstr "" #. Denied #, c-format @@ -8099,175 +7301,133 @@ "following reason:\n" "%s" msgstr "" -"The user %s has denied your request to add them to your buddy list for the " -"following reason:\n" -"%s" msgid "Authorization Denied" -msgstr "Authorization Denied" +msgstr "" msgid "_Exchange:" -msgstr "_Exchange:" +msgstr "" msgid "Your IM Image was not sent. You cannot send IM Images in AIM chats." -msgstr "Your IM Image was not sent. You cannot send IM Images in AIM chats." +msgstr "" msgid "iTunes Music Store Link" msgstr "" -#, fuzzy msgid "Lunch" -msgstr "Finch" +msgstr "" #, c-format msgid "Buddy Comment for %s" -msgstr "Buddy Comment for %s" +msgstr "" msgid "Buddy Comment:" -msgstr "Buddy Comment:" +msgstr "" #, c-format msgid "You have selected to open a Direct IM connection with %s." -msgstr "You have selected to open a Direct IM connection with %s." - -#, fuzzy +msgstr "" + msgid "" "Because this reveals your IP address, it may be considered a security risk. " "Do you wish to continue?" msgstr "" -"Because this reveals your IP address, it may be considered a privacy risk. " -"Do you wish to continue?" - -#, fuzzy + msgid "C_onnect" -msgstr "Connect" - -#, fuzzy +msgstr "" + msgid "You closed the connection." -msgstr "Error creating connection" - -#, fuzzy +msgstr "" + msgid "Get AIM Info" -msgstr "Get Info" +msgstr "" #. We only do this if the user is in our buddy list msgid "Edit Buddy Comment" -msgstr "Edit Buddy Comment" - -#, fuzzy +msgstr "" + msgid "Get X-Status Msg" -msgstr "Get Status Msg" - -#, fuzzy +msgstr "" + msgid "End Direct IM Session" -msgstr "Direct IM with %s established" +msgstr "" msgid "Direct IM" -msgstr "Direct IM" +msgstr "" msgid "Re-request Authorization" -msgstr "Re-request Authorization" - -#, fuzzy +msgstr "" + msgid "Require authorization" -msgstr "Request Authorization" +msgstr "" msgid "Web aware (enabling this will cause you to receive SPAM!)" msgstr "" -#, fuzzy msgid "ICQ Privacy Options" -msgstr "Proxy Options" - -msgid "The new formatting is invalid." -msgstr "The new formatting is invalid." - -#, fuzzy -msgid "Username formatting can change only capitalization and whitespace." -msgstr "Screen name formatting can change only capitalization and whitespace." +msgstr "" msgid "Change Address To:" -msgstr "Change Address To:" - -#, fuzzy +msgstr "" + msgid "you are not waiting for authorization" -msgstr "you are not waiting for authorization" +msgstr "" msgid "You are awaiting authorization from the following buddies" -msgstr "You are awaiting authorization from the following buddies" +msgstr "" msgid "" "You can re-request authorization from these buddies by right-clicking on " "them and selecting \"Re-request Authorization.\"" msgstr "" -"You can re-request authorization from these buddies by right-clicking on " -"them and selecting \"Re-request Authorization.\"" msgid "Find Buddy by Email" -msgstr "Find Buddy by Email" +msgstr "" msgid "Search for a buddy by email address" -msgstr "Search for a buddy by email address" +msgstr "" msgid "Type the email address of the buddy you are searching for." -msgstr "Type the email address of the buddy you are searching for." - -#, fuzzy -msgid "_Search" -msgstr "Search" - -#, fuzzy +msgstr "" + msgid "Set User Info (web)..." -msgstr "Set User Info (URL)..." +msgstr "" #. This only happens when connecting with the old-style BUCP login -#, fuzzy msgid "Change Password (web)" -msgstr "Change Password (URL)" - -#, fuzzy +msgstr "" + msgid "Configure IM Forwarding (web)" -msgstr "Configure IM Forwarding (URL)" +msgstr "" #. ICQ actions -#, fuzzy msgid "Set Privacy Options..." -msgstr "Show more options" - -#, fuzzy +msgstr "" + msgid "Show Visible List" -msgstr "Buddy List" - -#, fuzzy +msgstr "" + msgid "Show Invisible List" -msgstr "Invite List" +msgstr "" #. AIM actions msgid "Confirm Account" -msgstr "Confirm Account" - -#, fuzzy +msgstr "" + msgid "Display Currently Registered Email Address" -msgstr "Display Currently Registered Address" - -#, fuzzy +msgstr "" + msgid "Change Currently Registered Email Address..." -msgstr "Change Currently Registered Address..." +msgstr "" msgid "Show Buddies Awaiting Authorization" -msgstr "Show Buddies Awaiting Authorization" - -#, fuzzy +msgstr "" + msgid "Search for Buddy by Email Address..." -msgstr "Search for Buddy by Email..." - -#, fuzzy -msgid "Don't use encryption" -msgstr "Request Authorization" - -#, fuzzy +msgstr "" + msgid "Use clientLogin" -msgstr "User is not logged in" +msgstr "" msgid "" "Always use AIM/ICQ proxy server for\n" @@ -8280,31 +7440,145 @@ #, c-format msgid "Asking %s to connect to us at %s:%hu for Direct IM." -msgstr "Asking %s to connect to us at %s:%hu for Direct IM." - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Attempting to connect to %s:%hu." -msgstr "Attempting to connect to %s at %s:%hu for Direct IM." - -#, fuzzy +msgstr "" + msgid "Attempting to connect via proxy server." -msgstr "Attempting to connect to %s at %s:%hu for Direct IM." +msgstr "" #, c-format msgid "%s has just asked to directly connect to %s" -msgstr "%s has just asked to directly connect to %s" +msgstr "" msgid "" "This requires a direct connection between the two computers and is necessary " "for IM Images. Because your IP address will be revealed, this may be " "considered a privacy risk." msgstr "" -"This requires a direct connection between the two computers and is necessary " -"for IM Images. Because your IP address will be revealed, this may be " -"considered a privacy risk." + +#. Label +msgid "Buddy Icon" +msgstr "" + +msgid "Voice" +msgstr "" + +msgid "AIM Direct IM" +msgstr "" + +msgid "Get File" +msgstr "" + +msgid "Games" +msgstr "" + +msgid "ICQ Xtraz" +msgstr "" + +msgid "Add-Ins" +msgstr "" + +msgid "Send Buddy List" +msgstr "" + +msgid "ICQ Direct Connect" +msgstr "" + +msgid "AP User" +msgstr "" + +msgid "ICQ RTF" +msgstr "" + +msgid "Nihilist" +msgstr "" + +msgid "ICQ Server Relay" +msgstr "" + +msgid "Old ICQ UTF8" +msgstr "" + +msgid "Trillian Encryption" +msgstr "" + +msgid "ICQ UTF8" +msgstr "" + +msgid "Hiptop" +msgstr "" + +msgid "Security Enabled" +msgstr "" + +msgid "Video Chat" +msgstr "" + +msgid "iChat AV" +msgstr "" + +msgid "Live Video" +msgstr "" + +msgid "Camera" +msgstr "" + +msgid "Screen Sharing" +msgstr "" + +msgid "IP Address" +msgstr "" + +msgid "Warning Level" +msgstr "" + +msgid "Buddy Comment" +msgstr "" + +#, c-format +msgid "User information not available: %s" +msgstr "" + +msgid "Mobile Phone" +msgstr "" + +msgid "Personal Web Page" +msgstr "" + +#. aim_userinfo_t +#. use_html_status +msgid "Additional Information" +msgstr "" + +msgid "Zip Code" +msgstr "Postal Code" + +msgid "Work Information" +msgstr "" + +msgid "Division" +msgstr "" + +msgid "Position" +msgstr "" + +msgid "Web Page" +msgstr "" + +msgid "Online Since" +msgstr "" + +msgid "Member Since" +msgstr "" + +msgid "Capabilities" +msgstr "" msgid "Invalid SNAC" -msgstr "Invalid SNAC" +msgstr "" msgid "Server rate limit exceeded" msgstr "" @@ -8313,40 +7587,40 @@ msgstr "" msgid "Service unavailable" -msgstr "Service unavailable" +msgstr "" msgid "Service not defined" -msgstr "Service not defined" +msgstr "" msgid "Obsolete SNAC" -msgstr "Obsolete SNAC" +msgstr "" msgid "Not supported by host" -msgstr "Not supported by host" +msgstr "" msgid "Not supported by client" -msgstr "Not supported by client" +msgstr "" msgid "Refused by client" -msgstr "Refused by client" +msgstr "" msgid "Reply too big" -msgstr "Reply too big" +msgstr "" msgid "Responses lost" -msgstr "Responses lost" +msgstr "" msgid "Request denied" -msgstr "Request denied" +msgstr "" msgid "Busted SNAC payload" -msgstr "Busted SNAC payload" +msgstr "" msgid "Insufficient rights" -msgstr "Insufficient rights" +msgstr "" msgid "In local permit/deny" -msgstr "In local permit/deny" +msgstr "" msgid "Warning level too high (sender)" msgstr "" @@ -8355,1046 +7629,95 @@ msgstr "" msgid "User temporarily unavailable" -msgstr "User temporarily unavailable" +msgstr "" msgid "No match" -msgstr "No match" +msgstr "" msgid "List overflow" -msgstr "List overflow" +msgstr "" msgid "Request ambiguous" -msgstr "Request ambiguous" +msgstr "" msgid "Queue full" -msgstr "Queue full" +msgstr "" msgid "Not while on AOL" -msgstr "Not while on AOL" - -#. Label -msgid "Buddy Icon" -msgstr "Buddy Icon" - -msgid "Voice" -msgstr "Voice" - -msgid "AIM Direct IM" -msgstr "AIM Direct IM" - -msgid "Get File" -msgstr "Get File" - -msgid "Games" -msgstr "Games" - -msgid "ICQ Xtraz" -msgstr "" - -msgid "Add-Ins" -msgstr "Add-Ins" - -msgid "Send Buddy List" -msgstr "Send Buddy List" - -msgid "ICQ Direct Connect" -msgstr "ICQ Direct Connect" - -msgid "AP User" -msgstr "AP User" - -msgid "ICQ RTF" -msgstr "ICQ RTF" - -msgid "Nihilist" -msgstr "Nihilist" - -msgid "ICQ Server Relay" -msgstr "ICQ Server Relay" - -msgid "Old ICQ UTF8" -msgstr "Old ICQ UTF8" - -msgid "Trillian Encryption" -msgstr "Trillian Encryption" - -msgid "ICQ UTF8" -msgstr "ICQ UTF8" - -msgid "Hiptop" -msgstr "Hiptop" - -msgid "Security Enabled" -msgstr "Security Enabled" - -msgid "Video Chat" -msgstr "Video Chat" - -msgid "iChat AV" -msgstr "iChat AV" - -msgid "Live Video" -msgstr "Live Video" - -msgid "Camera" -msgstr "Camera" - -#, fuzzy -msgid "Screen Sharing" -msgstr "Screen Name" - -msgid "IP Address" -msgstr "IP Address" - -msgid "Warning Level" -msgstr "Warning Level" - -msgid "Buddy Comment" -msgstr "Buddy Comment" - -#, c-format -msgid "User information not available: %s" -msgstr "User information not available: %s" - -msgid "Mobile Phone" -msgstr "Mobile Phone" - -msgid "Personal Web Page" -msgstr "Personal Web Page" - -#. aim_userinfo_t -#. use_html_status -msgid "Additional Information" -msgstr "Additional Information" - -msgid "Zip Code" -msgstr "Postal Code" - -msgid "Work Information" -msgstr "Work Information" - -msgid "Division" -msgstr "Division" - -msgid "Position" -msgstr "Position" - -msgid "Web Page" -msgstr "Web Page" - -msgid "Online Since" -msgstr "Online Since" - -msgid "Member Since" -msgstr "Member Since" - -msgid "Capabilities" -msgstr "Capabilities" +msgstr "" #. Translators: This string is a menu option that, if selected, will cause #. you to appear online to the chosen user even when your status is set to #. Invisible. -#, fuzzy msgid "Appear Online" -msgstr "Appear Offline" +msgstr "" #. Translators: This string is a menu option that, if selected, will cause #. you to appear offline to the chosen user when your status is set to #. Invisible (this is the default). -#, fuzzy msgid "Don't Appear Online" -msgstr "Appear Offline" +msgstr "" #. Translators: This string is a menu option that, if selected, will cause #. you to always appear offline to the chosen user (even when your status #. isn't Invisible). msgid "Appear Offline" -msgstr "Appear Offline" +msgstr "" #. Translators: This string is a menu option that, if selected, will cause #. you to appear offline to the chosen user if you are invisible, and #. appear online to the chosen user if you are not invisible (this is the #. default). -#, fuzzy msgid "Don't Appear Offline" -msgstr "Appear Offline" - -#, fuzzy +msgstr "" + msgid "you have no buddies on this list" -msgstr "You have been kicked by %s: (%s)" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "" "You can add a buddy to this list by right-clicking on them and selecting \"%s" "\"" msgstr "" -"You can re-request authorization from these buddies by right-clicking on " -"them and selecting \"Re-request Authorization.\"" - -#, fuzzy + msgid "Visible List" -msgstr "Invisible" +msgstr "" msgid "These buddies will see your status when you switch to \"Invisible\"" msgstr "" -#, fuzzy msgid "Invisible List" -msgstr "Invite List" +msgstr "" msgid "These buddies will always see you as offline" msgstr "" -msgid "Aquarius" -msgstr "" - -#, fuzzy -msgid "Pisces" -msgstr "Pictures" - -#, fuzzy -msgid "Aries" -msgstr "Address" - -#, fuzzy -msgid "Taurus" -msgstr "Turkish" - -#, fuzzy -msgid "Gemini" -msgstr "German" - -#, fuzzy -msgid "Cancer" -msgstr "Cancel" - -msgid "Leo" -msgstr "" - -msgid "Virgo" -msgstr "" - -msgid "Libra" -msgstr "" - -#, fuzzy -msgid "Scorpio" -msgstr "Subscription" - -msgid "Sagittarius" -msgstr "" - -msgid "Capricorn" -msgstr "" - -#, fuzzy -msgid "Rat" -msgstr "Raw" - -msgid "Ox" -msgstr "" - -#, fuzzy -msgid "Tiger" -msgstr "Time" - -msgid "Rabbit" -msgstr "" - -msgid "Dragon" -msgstr "" - -#, fuzzy -msgid "Snake" -msgstr "Save" - -#, fuzzy -msgid "Horse" -msgstr "Ports" - -msgid "Goat" -msgstr "" - -#, fuzzy -msgid "Monkey" -msgstr "None" - -#, fuzzy -msgid "Rooster" -msgstr "Register" - -msgid "Dog" -msgstr "" - -#, fuzzy -msgid "Pig" -msgstr "Ping" - -#, fuzzy -msgid "Other" -msgstr "Opera" - -#, fuzzy -msgid "Visible" -msgstr "Invisible" - -msgid "Friend Only" -msgstr "" - -#, fuzzy -msgid "Private" -msgstr "Privacy" - -msgid "QQ Number" -msgstr "" - -#, fuzzy -msgid "Country/Region" -msgstr "Country" - -msgid "Province/State" -msgstr "" - -#, fuzzy -msgid "Zipcode" -msgstr "Postal Code" - -#, fuzzy -msgid "Phone Number" -msgstr "Telephone Number" - -#, fuzzy -msgid "Authorize adding" -msgstr "Authorize" - -#, fuzzy -msgid "Cellphone Number" -msgstr "Telephone Number" - -#, fuzzy -msgid "Personal Introduction" -msgstr "Personal Information" - -#, fuzzy -msgid "City/Area" -msgstr "City" - -#, fuzzy -msgid "Publish Mobile" -msgstr "Personal Title" - -#, fuzzy -msgid "Publish Contact" -msgstr "Alias Contact" - -#, fuzzy -msgid "College" -msgstr "_Collapse" - -#, fuzzy -msgid "Horoscope" -msgstr "Ports" - -msgid "Zodiac" -msgstr "" - -#, fuzzy -msgid "Blood" -msgstr "Blocked" - -#, fuzzy -msgid "True" -msgstr "Turkish" - -#, fuzzy -msgid "False" -msgstr "Failed" - -#, fuzzy -msgid "Modify Contact" -msgstr "Modify Account" - -#, fuzzy -msgid "Modify Address" -msgstr "Home Address" - -#, fuzzy -msgid "Modify Extended Information" -msgstr "Buddy Information" - -#, fuzzy -msgid "Modify Information" -msgstr "Buddy Information" - -#, fuzzy -msgid "Update" -msgstr "Last Updated" - -#, fuzzy -msgid "Could not change buddy information." -msgstr "Please enter a buddy to pounce." - -msgid "Note" -msgstr "Note" - -#. callback -#, fuzzy -msgid "Buddy Memo" -msgstr "Buddy Icon" - -msgid "Change his/her memo as you like" -msgstr "" - -#, fuzzy -msgid "_Modify" -msgstr "_Modify" - -#, fuzzy -msgid "Memo Modify" -msgstr "_Modify" - -#, fuzzy -msgid "Server says:" -msgstr "Server busy" - -msgid "Your request was accepted." -msgstr "" - -msgid "Your request was rejected." -msgstr "" - -#, fuzzy, c-format -msgid "%u requires verification: %s" -msgstr "Request Authorization" - -#, fuzzy -msgid "Add buddy question" -msgstr "Add buddy to your list?" - -#, fuzzy -msgid "Enter answer here" -msgstr "Cannot send a directory." - -msgid "Send" -msgstr "Send" - -#, fuzzy -msgid "Invalid answer." -msgstr "Invalid password" - -#, fuzzy -msgid "Authorization denied message:" -msgstr "Authorization Denied Message:" - -msgid "Sorry, you're not my style." -msgstr "" - -#, fuzzy, c-format -msgid "%u needs authorization" -msgstr "Starting authentication" - -#, fuzzy -msgid "Add buddy authorize" -msgstr "Add buddy to your list?" - -#, fuzzy -msgid "Enter request here" -msgstr "Enter a Conference Server" - -#, fuzzy -msgid "Would you be my friend?" -msgstr "Would you like to overwrite it?" - -#, fuzzy -msgid "QQ Buddy" -msgstr "Add Buddy" - -#, fuzzy -msgid "Add buddy" -msgstr "Add Buddy" - -#, fuzzy -msgid "Invalid QQ Number" -msgstr "Invalid Room Name" - -#, fuzzy -msgid "Failed sending authorize" -msgstr "Please authorize me!" - -#, fuzzy, c-format -msgid "Failed removing buddy %u" -msgstr "Failed to join buddy in chat" - -#, fuzzy, c-format -msgid "Failed removing me from %d's buddy list" -msgstr "Remove the user from your buddy list" - -#, fuzzy -msgid "No reason given" -msgstr "No reason given." - -#. only need to get value -#, fuzzy, c-format -msgid "You have been added by %s" -msgstr "You have been killed by %s (%s)" - -#, fuzzy -msgid "Would you like to add him?" -msgstr "Would you like to overwrite it?" - -#, fuzzy, c-format -msgid "Rejected by %s" -msgstr "Reset" - -#, fuzzy, c-format -msgid "Message: %s" -msgstr "_Message:" - -msgid "ID: " -msgstr "" - -#, fuzzy -msgid "Group ID" -msgstr "Group:" - -msgid "QQ Qun" -msgstr "" - -#, fuzzy -msgid "Please enter Qun number" -msgstr "Please enter a new name for the selected group." - -msgid "You can only search for permanent Qun\n" -msgstr "" - -#, fuzzy -msgid "(Invalid UTF-8 string)" -msgstr "Invalid proxy settings" - -#, fuzzy -msgid "Not member" -msgstr "Member Since" - -#, fuzzy -msgid "Member" -msgstr "Member Since" - -#, fuzzy -msgid "Requesting" -msgstr "Request ambiguous" - -msgid "Admin" -msgstr "" - -#. XXX: Should this be "Topic"? -#, fuzzy -msgid "Room Title" -msgstr "Room List" - -#, fuzzy -msgid "Notice" -msgstr "Note" - -#, fuzzy -msgid "Detail" -msgstr "Details" - -#, fuzzy -msgid "Creator" -msgstr "Close" - -#, fuzzy -msgid "About me" -msgstr "About Pidgin" - -#, fuzzy -msgid "Category" -msgstr "Read error" - -#, fuzzy -msgid "The Qun does not allow others to join" -msgstr "" -"This evaluation version does not allow more than ten users to log in at one " -"time" - -#, fuzzy -msgid "Join QQ Qun" -msgstr "Join Chat" - -msgid "Input request here" -msgstr "" - -#, fuzzy, c-format -msgid "Successfully joined Qun %s (%u)" -msgstr "Telephone Number" - -msgid "Successfully joined Qun" -msgstr "" - -#, c-format -msgid "Qun %u denied from joining" -msgstr "" - -#, fuzzy -msgid "QQ Qun Operation" -msgstr "Sound Options" - -#, fuzzy -msgid "Failed:" -msgstr "Failed" - -msgid "Join Qun, Unknown Reply" -msgstr "" - -#, fuzzy -msgid "Quit Qun" -msgstr "Join Chat" - -msgid "" -"Note, if you are the creator, \n" -"this operation will eventually remove this Qun." -msgstr "" - -#, fuzzy -msgid "Sorry, you are not our style" -msgstr "Sorry, I ran out for a bit!" - -#, fuzzy -msgid "Successfully changed Qun members" -msgstr "Telephone Number" - -#, fuzzy -msgid "Successfully changed Qun information" -msgstr "Channel Information" - -msgid "You have successfully created a Qun" -msgstr "" - -#, fuzzy -msgid "Would you like to set up detailed information now?" -msgstr "Would you like to join the conversation?" - -#, fuzzy -msgid "Setup" -msgstr "_Set" - -#, c-format -msgid "%u requested to join Qun %u for %s" -msgstr "" - -#, c-format -msgid "%u request to join Qun %u" -msgstr "" - -#, fuzzy, c-format -msgid "Failed to join Qun %u, operated by admin %u" -msgstr "Failed to join buddy in chat" - -#, c-format -msgid "Joining Qun %u is approved by admin %u for %s" -msgstr "" - -#, fuzzy, c-format -msgid "Removed buddy %u." -msgstr "Remove Buddy" - -#, fuzzy, c-format -msgid "New buddy %u joined." -msgstr "Remove Buddy" - -#, fuzzy, c-format -msgid "Unknown-%d" -msgstr "Unknown" - -#, fuzzy -msgid "Level" -msgstr "Never" - -msgid " VIP" -msgstr "" - -msgid " TCP" -msgstr "" - -#, fuzzy -msgid " FromMobile" -msgstr "Mobile Phone" - -#, fuzzy -msgid " BindMobile" -msgstr "Mobile Phone" - -#, fuzzy -msgid " Video" -msgstr "Live Video" - -#, fuzzy -msgid " Zone" -msgstr "None" - -msgid "Flag" -msgstr "" - -msgid "Ver" -msgstr "" - -#, fuzzy -msgid "Invalid name" -msgstr "Invalid Username" - -#, fuzzy -msgid "Select icon..." -msgstr "Select Text Colour" - -#, fuzzy, c-format -msgid "Login time: %d-%d-%d, %d:%d:%d
\n" -msgstr "User: %s
" - -#, fuzzy, c-format -msgid "Total Online Buddies: %d
\n" -msgstr "Alias: %s
" - -#, fuzzy, c-format -msgid "Last Refresh: %d-%d-%d, %d:%d:%d
\n" -msgstr "User: %s
" - -#, fuzzy, c-format -msgid "Server: %s
\n" -msgstr "User: %s
" - -#, fuzzy, c-format -msgid "Client Tag: %s
\n" -msgstr "User: %s
" - -#, fuzzy, c-format -msgid "Connection Mode: %s
\n" -msgstr "Idle for: %s
" - -#, fuzzy, c-format -msgid "My Internet IP: %s:%d
\n" -msgstr "IP Address: %s
" - -#, fuzzy, c-format -msgid "Sent: %lu
\n" -msgstr "Alias: %s
" - -#, fuzzy, c-format -msgid "Resend: %lu
\n" -msgstr "User: %s
" - -#, fuzzy, c-format -msgid "Lost: %lu
\n" -msgstr "%s: %s
" - -#, fuzzy, c-format -msgid "Received: %lu
\n" -msgstr "User: %s
" - -#, fuzzy, c-format -msgid "Received Duplicate: %lu
\n" -msgstr "Alias: %s
" - -#, fuzzy, c-format -msgid "Time: %d-%d-%d, %d:%d:%d
\n" -msgstr "User: %s
" - -#, fuzzy, c-format -msgid "IP: %s
\n" -msgstr "User: %s
" - -#, fuzzy -msgid "Login Information" -msgstr "User Information" - -msgid "

Original Author:
\n" -msgstr "" - -msgid "

Code Contributors:
\n" -msgstr "" - -#, fuzzy -msgid "

Lovely Patch Writers:
\n" -msgstr "User: %s
" - -#, fuzzy -msgid "

Acknowledgement:
\n" -msgstr "Alias: %s
" - -#, fuzzy -msgid "

Scrupulous Testers:
\n" -msgstr "User: %s
" - -msgid "and more, please let me know... thank you!))" -msgstr "" - -msgid "

And, all the boys in the backroom...
\n" -msgstr "" - -msgid "Feel free to join us! :)" -msgstr "" - -#, fuzzy, c-format -msgid "About OpenQ %s" -msgstr "About Pidgin" - -#, fuzzy -msgid "Change Icon" -msgstr "Save Icon" - -msgid "Change Password" -msgstr "Change Password" - -#, fuzzy -msgid "Account Information" -msgstr "User Information" - -msgid "Update all QQ Quns" -msgstr "" - -#, fuzzy -msgid "About OpenQ" -msgstr "About Pidgin" - -#, fuzzy -msgid "Modify Buddy Memo" -msgstr "Home Address" - -#. *< type -#. *< ui_requirement -#. *< flags -#. *< dependencies -#. *< priority -#. *< id -#. *< name -#. *< version -#. * summary -#. * description -#, fuzzy -msgid "QQ Protocol Plugin" -msgstr "IRC Protocol Plugin" - -#, fuzzy -msgid "Auto" -msgstr "Authorize" - -#, fuzzy -msgid "Select Server" -msgstr "Select Text Colour" - -msgid "QQ2005" -msgstr "" - -msgid "QQ2007" -msgstr "" - -msgid "QQ2008" -msgstr "" - -#, fuzzy -msgid "Connect by TCP" -msgstr "Connecting" - -#, fuzzy -msgid "Show server notice" -msgstr "Show fewer options" - -#, fuzzy -msgid "Show server news" -msgstr "Show fewer options" - -msgid "Show chat room when msg comes" -msgstr "" - -#, fuzzy -msgid "Keep alive interval (seconds)" -msgstr "Reading error" - -#, fuzzy -msgid "Update interval (seconds)" -msgstr "Reading error" - -#, fuzzy -msgid "Unable to decrypt server reply" -msgstr "Cannot get server information" - -#, c-format -msgid "Failed requesting token, 0x%02X" -msgstr "" - -#, fuzzy, c-format -msgid "Invalid token len, %d" -msgstr "Invalid authzid" - -#. extend redirect used in QQ2006 -msgid "Redirect_EX is not currently supported" -msgstr "" - -#. need activation -#. need activation -#. need activation -#, fuzzy -msgid "Activation required" -msgstr "Registration Required" - -#, c-format -msgid "Unknown reply code when logging in (0x%02X)" -msgstr "" - -#, fuzzy -msgid "Requesting captcha" -msgstr "Request ambiguous" - -msgid "Checking captcha" -msgstr "" - -#, fuzzy -msgid "Failed captcha verification" -msgstr "Failed Yahoo! Authentication" - -#, fuzzy -msgid "Captcha Image" -msgstr "Save Image" - -#, fuzzy -msgid "Enter code" -msgstr "Change Password" - -msgid "QQ Captcha Verification" -msgstr "" - -#, fuzzy -msgid "Enter the text from the image" -msgstr "Please enter the name of the group to be added." - -#, c-format -msgid "Unknown reply when checking password (0x%02X)" -msgstr "" - -#, c-format -msgid "" -"Unknown reply code when logging in (0x%02X):\n" -"%s" -msgstr "" - -#, fuzzy -msgid "Socket error" -msgstr "Unknown Error" - -#, fuzzy -msgid "Getting server" -msgstr "Set User Info..." - -#, fuzzy -msgid "Requesting token" -msgstr "Request denied" - -#, fuzzy -msgid "Unable to resolve hostname" -msgstr "Unable to ping server" - -#, fuzzy -msgid "Invalid server or port" -msgstr "Invalid username or password" - -#, fuzzy -msgid "Connecting to server" -msgstr "Connecting to SILC Server" - -#, fuzzy -msgid "QQ Error" -msgstr "Read Error" - -#, fuzzy, c-format -msgid "" -"Server News:\n" -"%s\n" -"%s\n" -"%s" -msgstr "ICQ Server Relay" - -#, fuzzy, c-format -msgid "%s:%s" -msgstr "%s on %s (%s)" - -#, fuzzy, c-format -msgid "From %s:" -msgstr "From" - -#, fuzzy, c-format -msgid "" -"Server notice From %s: \n" -"%s" -msgstr "Server Information" - -#, fuzzy -msgid "Unknown SERVER CMD" -msgstr "Unknown reason." - -#, c-format -msgid "" -"Error reply of %s(0x%02X)\n" -"Room %u, reply 0x%02X" -msgstr "" - -#, fuzzy -msgid "QQ Qun Command" -msgstr "Command" - -#, fuzzy -msgid "Unable to decrypt login reply" -msgstr "Cannot get server information" - -#, fuzzy -msgid "Unknown LOGIN CMD" -msgstr "Unknown reason." - -#, fuzzy -msgid "Unknown CLIENT CMD" -msgstr "Unknown reason." - -#, fuzzy, c-format -msgid "%d has declined the file %s" -msgstr "%s has changed the topic to: %s" - -#, fuzzy -msgid "File Send" -msgstr "File Send Failed" - -#, fuzzy, c-format -msgid "%d cancelled the transfer of %s" -msgstr "%s cancelled the transfer of %s" - -#, fuzzy, c-format +#, c-format msgid "Group Title: %s
" -msgstr "User: %s
" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Notes Group ID: %s
" -msgstr "User: %s
" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Info for Group %s" -msgstr "Info for %s" - -#, fuzzy +msgstr "" + msgid "Notes Address Book Information" -msgstr "Work Information" - -#, fuzzy +msgstr "" + msgid "Invite Group to Conference..." -msgstr "Initiate Conference" - -#, fuzzy +msgstr "" + msgid "Get Notes Address Book Info" -msgstr "Add to Address Book" - -#, fuzzy +msgstr "" + msgid "Sending Handshake" -msgstr "Sending cookie" - -#, fuzzy +msgstr "" + msgid "Waiting for Handshake Acknowledgement" -msgstr "Waiting for transfer to begin" +msgstr "" msgid "Handshake Acknowledged, Sending Login" msgstr "" @@ -9402,20 +7725,17 @@ msgid "Waiting for Login Acknowledgement" msgstr "" -#, fuzzy msgid "Login Redirected" -msgstr "Login server" - -#, fuzzy +msgstr "" + msgid "Forcing Login" -msgstr "Logging in" +msgstr "" msgid "Login Acknowledged" msgstr "" -#, fuzzy msgid "Starting Services" -msgstr "Online Services" +msgstr "" #, c-format msgid "" @@ -9429,21 +7749,18 @@ msgid "Announcement from %s" msgstr "" -#, fuzzy msgid "Conference Closed" -msgstr "Connection Closed" - -#, fuzzy +msgstr "" + msgid "Unable to send message: " -msgstr "Unable to send message: %s" +msgstr "" #, c-format msgid "Unable to send message to %s:" -msgstr "Unable to send message to %s:" - -#, fuzzy +msgstr "" + msgid "Place Closed" -msgstr "Cancelled" +msgstr "" msgid "Microphone" msgstr "" @@ -9451,25 +7768,20 @@ msgid "Speakers" msgstr "" -#, fuzzy msgid "Video Camera" -msgstr "Video Chat" - -#, fuzzy +msgstr "" + msgid "File Transfer" -msgstr "File Transfers" - -#, fuzzy +msgstr "" + msgid "Supports" -msgstr "support" - -#, fuzzy +msgstr "" + msgid "External User" -msgstr "Warn User" - -#, fuzzy +msgstr "" + msgid "Create conference with user" -msgstr "Select a conference server to query" +msgstr "" #, c-format msgid "" @@ -9477,25 +7789,20 @@ "sent to %s" msgstr "" -#, fuzzy msgid "New Conference" -msgstr "Initiate Conference" - -#, fuzzy +msgstr "" + msgid "Create" -msgstr "Date" - -#, fuzzy +msgstr "" + msgid "Available Conferences" -msgstr "Initiate Conference" - -#, fuzzy +msgstr "" + msgid "Create New Conference..." -msgstr "Initiate Conference" - -#, fuzzy +msgstr "" + msgid "Invite user to a conference" -msgstr "Initiate Conference" +msgstr "" #, c-format msgid "" @@ -9504,23 +7811,20 @@ "this user to." msgstr "" -#, fuzzy msgid "Invite to Conference" -msgstr "Initiate Conference" - -#, fuzzy +msgstr "" + msgid "Invite to Conference..." -msgstr "Initiate Conference" +msgstr "" msgid "Send TEST Announcement" msgstr "" msgid "Topic:" -msgstr "Topic:" - -#, fuzzy +msgstr "" + msgid "No Sametime Community Server specified" -msgstr "Connecting to SILC Server" +msgstr "" #, c-format msgid "" @@ -9528,28 +7832,24 @@ "Please enter one below to continue logging in." msgstr "" -#, fuzzy msgid "Meanwhile Connection Setup" -msgstr "Remote Connection Failed" - -#, fuzzy +msgstr "" + msgid "No Sametime Community Server Specified" -msgstr "Connecting to SILC Server" +msgstr "" msgid "Connect" -msgstr "Connect" +msgstr "" #, c-format msgid "Unknown (0x%04x)
" msgstr "" -#, fuzzy msgid "Last Known Client" -msgstr "Rate to client" - -#, fuzzy +msgstr "" + msgid "User Name" -msgstr "Username" +msgstr "" msgid "Sametime ID" msgstr "" @@ -9557,21 +7857,17 @@ msgid "An ambiguous user ID was entered" msgstr "" -#, fuzzy, c-format +#, c-format msgid "" "The identifier '%s' may possibly refer to any of the following users. Please " "select the correct user from the list below to add them to your buddy list." msgstr "" -"More than one user was found with the same name. Select the correct user " -"from the list to add to the buddy list." - -#, fuzzy + msgid "Select User" -msgstr "Select Text Colour" - -#, fuzzy +msgstr "" + msgid "Unable to add user: user not found" -msgstr "Unable to add user on %s (%s)" +msgstr "" #, c-format msgid "" @@ -9579,33 +7875,26 @@ "entry has been removed from your buddy list." msgstr "" -#, fuzzy, c-format +#, c-format msgid "" "Error reading file %s: \n" "%s\n" msgstr "" -"Error reading %s: \n" -"%s.\n" - -#, fuzzy + msgid "Remotely Stored Buddy List" -msgstr "Send Buddy List" - -#, fuzzy +msgstr "" + msgid "Buddy List Storage Mode" -msgstr "Buddy List Sorting" - -#, fuzzy +msgstr "" + msgid "Local Buddy List Only" -msgstr "_Dockable Buddy List" - -#, fuzzy +msgstr "" + msgid "Merge List from Server" -msgstr "Delete Buddy List from Server" - -#, fuzzy +msgstr "" + msgid "Merge and Save List to Server" -msgstr "Wrong CHL value sent to server" +msgstr "" msgid "Synchronize List with Server" msgstr "" @@ -9618,17 +7907,15 @@ msgid "Export Sametime List for Account %s" msgstr "" -#, fuzzy msgid "Unable to add group: group exists" -msgstr "Unable to add %s to deny list (%s)." +msgstr "" #, c-format msgid "A group named '%s' already exists in your buddy list." msgstr "" -#, fuzzy msgid "Unable to add group" -msgstr "Unable to rename group" +msgstr "" msgid "Possible Matches" msgstr "" @@ -9643,13 +7930,11 @@ "to your buddy list." msgstr "" -#, fuzzy msgid "Select Notes Address Book" -msgstr "Add to Address Book" - -#, fuzzy +msgstr "" + msgid "Unable to add group: group not found" -msgstr "Unable to read from network" +msgstr "" #, c-format msgid "" @@ -9657,18 +7942,17 @@ "Sametime community." msgstr "" -#, fuzzy msgid "Notes Address Book Group" -msgstr "Add to Address Book" +msgstr "" msgid "" "Enter the name of a Notes Address Book group in the field below to add the " "group and its members to your buddy list." msgstr "" -#, fuzzy, c-format +#, c-format msgid "Search results for '%s'" -msgstr "Search Results" +msgstr "" #, c-format msgid "" @@ -9678,32 +7962,28 @@ msgstr "" msgid "Search Results" -msgstr "Search Results" - -#, fuzzy +msgstr "" + msgid "No matches" -msgstr "No match" +msgstr "" #, c-format msgid "The identifier '%s' did not match any users in your Sametime community." msgstr "" -#, fuzzy msgid "No Matches" -msgstr "No match" - -#, fuzzy +msgstr "" + msgid "Search for a user" -msgstr "_Search for:" +msgstr "" msgid "" "Enter a name or partial ID in the field below to search for matching users " "in your Sametime community." msgstr "" -#, fuzzy msgid "User Search" -msgstr "Search" +msgstr "" msgid "Import Sametime List..." msgstr "" @@ -9711,13 +7991,11 @@ msgid "Export Sametime List..." msgstr "" -#, fuzzy msgid "Add Notes Address Book Group..." -msgstr "Add to Address Book" - -#, fuzzy +msgstr "" + msgid "User Search..." -msgstr "Search" +msgstr "" msgid "Force login (ignore server redirects)" msgstr "" @@ -9728,42 +8006,40 @@ #, c-format msgid "User %s is not present in the network" -msgstr "User %s is not present in the network" +msgstr "" msgid "Key Agreement" -msgstr "Key Agreement" +msgstr "" msgid "Cannot perform the key agreement" -msgstr "Cannot perform the key agreement" +msgstr "" msgid "Error occurred during key agreement" -msgstr "Error occurred during key agreement" +msgstr "" msgid "Key Agreement failed" -msgstr "Key Agreement failed" +msgstr "" msgid "Timeout during key agreement" -msgstr "Timeout during key agreement" +msgstr "" msgid "Key agreement was aborted" -msgstr "Key agreement was aborted" +msgstr "" msgid "Key agreement is already started" -msgstr "Key agreement is already started" +msgstr "" msgid "Key agreement cannot be started with yourself" -msgstr "Key agreement cannot be started with yourself" +msgstr "" msgid "The remote user is not present in the network any more" -msgstr "The remote user is not present in the network any more" +msgstr "" #, c-format msgid "" "Key agreement request received from %s. Would you like to perform the key " "agreement?" msgstr "" -"Key agreement request received from %s. Would you like to perform the key " -"agreement?" #, c-format msgid "" @@ -9771,200 +8047,188 @@ "Remote host: %s\n" "Remote port: %d" msgstr "" -"The remote user is waiting key agreement on:\n" -"Remote host: %s\n" -"Remote port: %d" msgid "Key Agreement Request" -msgstr "Key Agreement Request" +msgstr "" msgid "IM With Password" -msgstr "IM With Password" +msgstr "" msgid "Cannot set IM key" -msgstr "Cannot set IM key" +msgstr "" msgid "Set IM Password" -msgstr "Set IM Password" +msgstr "" msgid "Get Public Key" -msgstr "Get Public Key" +msgstr "" msgid "Cannot fetch the public key" -msgstr "Cannot fetch the public key" +msgstr "" msgid "Show Public Key" -msgstr "Show Public Key" +msgstr "" msgid "Could not load public key" -msgstr "Could not load public key" +msgstr "" msgid "User Information" -msgstr "User Information" +msgstr "" msgid "Cannot get user information" -msgstr "Cannot get user information" +msgstr "" #, c-format msgid "The %s buddy is not trusted" -msgstr "The %s buddy is not trusted" +msgstr "" msgid "" "You cannot receive buddy notifications until you import his/her public key. " "You can use the Get Public Key command to get the public key." msgstr "" -"You cannot receive buddy notifications until you import his/her public key. " -"You can use the Get Public Key command to get the public key." #. Open file selector to select the public key. msgid "Open..." -msgstr "Open..." +msgstr "" #, c-format msgid "The %s buddy is not present in the network" -msgstr "The %s buddy is not present in the network" +msgstr "" msgid "" "To add the buddy you must import his/her public key. Press Import to import " "a public key." msgstr "" -"To add the buddy you must import his/her public key. Press Import to import " -"a public key." - -#, fuzzy + msgid "_Import..." -msgstr "Import..." +msgstr "" msgid "Select correct user" -msgstr "Select correct user" +msgstr "" msgid "" "More than one user was found with the same public key. Select the correct " "user from the list to add to the buddy list." msgstr "" -"More than one user was found with the same public key. Select the correct " -"user from the list to add to the buddy list." msgid "" "More than one user was found with the same name. Select the correct user " "from the list to add to the buddy list." msgstr "" -"More than one user was found with the same name. Select the correct user " -"from the list to add to the buddy list." msgid "Detached" -msgstr "Detached" +msgstr "" msgid "Indisposed" -msgstr "Indisposed" +msgstr "" msgid "Wake Me Up" -msgstr "Wake Me Up" +msgstr "" msgid "Hyper Active" -msgstr "Hyper Active" +msgstr "" msgid "Robot" -msgstr "Robot" +msgstr "" msgid "User Modes" -msgstr "User Modes" +msgstr "" msgid "Preferred Contact" -msgstr "Preferred Contact" +msgstr "" msgid "Preferred Language" -msgstr "Preferred Language" +msgstr "" msgid "Device" -msgstr "Device" +msgstr "" msgid "Timezone" -msgstr "Time Zone" +msgstr "" msgid "Geolocation" -msgstr "Geolocation" +msgstr "" msgid "Reset IM Key" -msgstr "Reset IM Key" +msgstr "" msgid "IM with Key Exchange" -msgstr "IM with Key Exchange" +msgstr "" msgid "IM with Password" -msgstr "IM with Password" +msgstr "" msgid "Get Public Key..." -msgstr "Get Public Key..." +msgstr "" msgid "Kill User" -msgstr "Kill User" +msgstr "" msgid "Draw On Whiteboard" msgstr "" msgid "_Passphrase:" -msgstr "_Passphrase:" +msgstr "" #, c-format msgid "Channel %s does not exist in the network" -msgstr "Channel %s does not exist in the network" +msgstr "" msgid "Channel Information" -msgstr "Channel Information" +msgstr "" msgid "Cannot get channel information" -msgstr "Cannot get channel information" +msgstr "" #, c-format msgid "Channel Name: %s" -msgstr "Channel Name: %s" +msgstr "" #, c-format msgid "
User Count: %d" -msgstr "
User Count: %d" +msgstr "" #, c-format msgid "
Channel Founder: %s" -msgstr "
Channel Founder: %s" +msgstr "" #, c-format msgid "
Channel Cipher: %s" -msgstr "
Channel Cipher: %s" +msgstr "" #. Definition of HMAC: http://en.wikipedia.org/wiki/HMAC #, c-format msgid "
Channel HMAC: %s" -msgstr "
Channel HMAC: %s" +msgstr "" #, c-format msgid "
Channel Topic:
%s" -msgstr "
Channel Topic:
%s" +msgstr "" #, c-format msgid "
Channel Modes: " -msgstr "
Channel Modes: " +msgstr "" #, c-format msgid "
Founder Key Fingerprint:
%s" -msgstr "
Founder Key Fingerprint:
%s" +msgstr "" #, c-format msgid "
Founder Key Babbleprint:
%s" -msgstr "
Founder Key Babbleprint:
%s" +msgstr "" msgid "Add Channel Public Key" -msgstr "Add Channel Public Key" +msgstr "" #. Add new public key msgid "Open Public Key..." -msgstr "Open Public Key..." +msgstr "" msgid "Channel Passphrase" -msgstr "Channel Passphrase" +msgstr "" msgid "Channel Public Keys List" -msgstr "Channel Public Keys List" +msgstr "" #, c-format msgid "" @@ -9974,255 +8238,244 @@ "channel public keys are set then only users whose public keys are listed are " "able to join." msgstr "" -"Channel authentication is used to secure the channel from unauthorized " -"access. The authentication may be based on passphrase and digital " -"signatures. If passphrase is set, it is required to be able to join. If " -"channel public keys are set then only users whose public keys are listed are " -"able to join." msgid "Channel Authentication" -msgstr "Channel Authentication" +msgstr "" msgid "Add / Remove" -msgstr "Add / Remove" +msgstr "" msgid "Group Name" -msgstr "Group Name" +msgstr "" msgid "Passphrase" -msgstr "Passphrase" +msgstr "" #, c-format msgid "Please enter the %s channel private group name and passphrase." -msgstr "Please enter the %s channel private group name and passphrase." +msgstr "" msgid "Add Channel Private Group" -msgstr "Add Channel Private Group" +msgstr "" msgid "User Limit" -msgstr "User Limit" +msgstr "" msgid "Set user limit on channel. Set to zero to reset user limit." -msgstr "Set user limit on channel. Set to zero to reset user limit." +msgstr "" msgid "Invite List" -msgstr "Invite List" +msgstr "" msgid "Ban List" -msgstr "Ban List" +msgstr "" msgid "Add Private Group" -msgstr "Add Private Group" +msgstr "" msgid "Reset Permanent" -msgstr "Reset Permanent" +msgstr "" msgid "Set Permanent" -msgstr "Set Permanent" +msgstr "" msgid "Set User Limit" -msgstr "Set User Limit" +msgstr "" msgid "Reset Topic Restriction" -msgstr "Reset Topic Restriction" +msgstr "" msgid "Set Topic Restriction" -msgstr "Set Topic Restriction" +msgstr "" msgid "Reset Private Channel" -msgstr "Reset Private Channel" +msgstr "" msgid "Set Private Channel" -msgstr "Set Private Channel" +msgstr "" msgid "Reset Secret Channel" -msgstr "Reset Secret Channel" +msgstr "" msgid "Set Secret Channel" -msgstr "Set Secret Channel" +msgstr "" #, c-format msgid "" "You have to join the %s channel before you are able to join the private group" msgstr "" -"You have to join the %s channel before you are able to join the private group" msgid "Join Private Group" -msgstr "Join Private Group" +msgstr "" msgid "Cannot join private group" -msgstr "Cannot join private group" - -#, fuzzy +msgstr "" + msgid "Call Command" -msgstr "Command" +msgstr "" msgid "Cannot call command" -msgstr "Cannot call command" +msgstr "" msgid "Unknown command" -msgstr "Unknown command" +msgstr "" msgid "Secure File Transfer" -msgstr "Secure File Transfer" +msgstr "" msgid "Error during file transfer" -msgstr "Error during file transfer" - -#, fuzzy +msgstr "" + msgid "Remote disconnected" -msgstr "Disconnected." +msgstr "" msgid "Permission denied" -msgstr "Permission denied" +msgstr "" msgid "Key agreement failed" -msgstr "Key agreement failed" - -#, fuzzy +msgstr "" + msgid "Connection timed out" -msgstr "Connection Timeout" - -#, fuzzy +msgstr "" + msgid "Creating connection failed" -msgstr "Connection failed" - -#, fuzzy +msgstr "" + msgid "File transfer session does not exist" -msgstr "File transfer sessions does not exist" +msgstr "" msgid "No file transfer session active" -msgstr "No file transfer session active" +msgstr "" msgid "File transfer already started" -msgstr "File transfer already started" +msgstr "" msgid "Could not perform key agreement for file transfer" -msgstr "Could not perform key agreement for file transfer" +msgstr "" msgid "Could not start the file transfer" -msgstr "Could not start the file transfer" +msgstr "" msgid "Cannot send file" -msgstr "Cannot send file" +msgstr "" msgid "Error occurred" msgstr "" #, c-format msgid "%s has changed the topic of %s to: %s" -msgstr "%s has changed the topic of %s to: %s" +msgstr "" #, c-format msgid "%s set channel %s modes to: %s" -msgstr "%s set channel %s modes to: %s" +msgstr "" #, c-format msgid "%s removed all channel %s modes" -msgstr "%s removed all channel %s modes" +msgstr "" #, c-format msgid "%s set %s's modes to: %s" -msgstr "%s set %s's modes to: %s" +msgstr "" #, c-format msgid "%s removed all %s's modes" -msgstr "%s removed all %s's modes" +msgstr "" #, c-format msgid "You have been kicked off %s by %s (%s)" -msgstr "You have been kicked off %s by %s (%s)" +msgstr "" #, c-format msgid "You have been killed by %s (%s)" -msgstr "You have been killed by %s (%s)" +msgstr "" #, c-format msgid "Killed by %s (%s)" -msgstr "Killed by %s (%s)" +msgstr "" msgid "Server signoff" -msgstr "Server signoff" +msgstr "" msgid "Personal Information" -msgstr "Personal Information" +msgstr "" msgid "Birth Day" -msgstr "Birth Day" +msgstr "" msgid "Job Role" -msgstr "Job Role" +msgstr "" msgid "Organization" -msgstr "Organization" +msgstr "" msgid "Unit" -msgstr "Unit" +msgstr "" + +msgid "Note" +msgstr "" msgid "Join Chat" -msgstr "Join Chat" +msgstr "" #, c-format msgid "You are channel founder on %s" -msgstr "You are channel founder on %s" +msgstr "" #, c-format msgid "Channel founder on %s is %s" -msgstr "Channel founder on %s is %s" - -#, fuzzy +msgstr "" + msgid "Real Name" -msgstr "Real name" +msgstr "" msgid "Status Text" -msgstr "Status Text" +msgstr "" msgid "Public Key Fingerprint" -msgstr "Public Key Fingerprint" +msgstr "" msgid "Public Key Babbleprint" -msgstr "Public Key Babbleprint" - -#, fuzzy +msgstr "" + msgid "_More..." -msgstr "More..." +msgstr "" msgid "Detach From Server" -msgstr "Detach From Server" +msgstr "" msgid "Cannot detach" -msgstr "Cannot detach" +msgstr "" msgid "Cannot set topic" -msgstr "Cannot set topic" +msgstr "" msgid "Failed to change nickname" -msgstr "Failed to change nickname" +msgstr "" msgid "Roomlist" -msgstr "Roomlist" +msgstr "" msgid "Cannot get room list" -msgstr "Cannot get room list" - -#, fuzzy +msgstr "" + msgid "Network is empty" -msgstr "Network Statistics" +msgstr "" msgid "No public key was received" -msgstr "No public key was received" +msgstr "" msgid "Server Information" -msgstr "Server Information" +msgstr "" msgid "Cannot get server information" -msgstr "Cannot get server information" +msgstr "" msgid "Server Statistics" -msgstr "Server Statistics" +msgstr "" msgid "Cannot get server statistics" -msgstr "Cannot get server statistics" +msgstr "" #, c-format msgid "" @@ -10242,67 +8495,49 @@ "Total server operators: %d\n" "Total router operators: %d\n" msgstr "" -"Local server start time: %s\n" -"Local server uptime: %s\n" -"Local server clients: %d\n" -"Local server channels: %d\n" -"Local server operators: %d\n" -"Local router operators: %d\n" -"Local cell clients: %d\n" -"Local cell channels: %d\n" -"Local cell servers: %d\n" -"Total clients: %d\n" -"Total channels: %d\n" -"Total servers: %d\n" -"Total routers: %d\n" -"Total server operators: %d\n" -"Total router operators: %d\n" msgid "Network Statistics" -msgstr "Network Statistics" +msgstr "" msgid "Ping" -msgstr "Ping" +msgstr "" msgid "Ping failed" -msgstr "Ping failed" +msgstr "" msgid "Ping reply received from server" -msgstr "Ping reply received from server" +msgstr "" msgid "Could not kill user" -msgstr "Could not kill user" +msgstr "" msgid "WATCH" msgstr "" -#, fuzzy msgid "Cannot watch user" -msgstr "Cannot add yourself" +msgstr "" msgid "Resuming session" -msgstr "Resuming session" +msgstr "" msgid "Authenticating connection" -msgstr "Authenticating connection" +msgstr "" msgid "Verifying server public key" -msgstr "Verifying server public key" +msgstr "" msgid "Passphrase required" -msgstr "Passphrase required" +msgstr "" #, c-format msgid "" "Received %s's public key. Your local copy does not match this key. Would you " "still like to accept this public key?" msgstr "" -"Received %s's public key. Your local copy does not match this key. Would you " -"still like to accept this public key?" #, c-format msgid "Received %s's public key. Would you like to accept this public key?" -msgstr "Received %s's public key. Would you like to accept this public key?" +msgstr "" #, c-format msgid "" @@ -10311,298 +8546,263 @@ "%s\n" "%s\n" msgstr "" -"Fingerprint and babbleprint for the %s key are:\n" -"\n" -"%s\n" -"%s\n" msgid "Verify Public Key" -msgstr "Verify Public Key" - -#, fuzzy +msgstr "" + msgid "_View..." -msgstr "View..." +msgstr "" msgid "Unsupported public key type" -msgstr "Unsupported public key type" +msgstr "" msgid "Disconnected by server" -msgstr "Disconnected by server" - -#, fuzzy +msgstr "" + msgid "Error connecting to SILC Server" -msgstr "Error during connecting to SILC Server" +msgstr "" msgid "Key Exchange failed" -msgstr "Key Exchange failed" +msgstr "" msgid "" "Resuming detached session failed. Press Reconnect to create new connection." msgstr "" -"Resuming detached session failed. Press Reconnect to create new connection." msgid "Performing key exchange" -msgstr "Performing key exchange" - -#, fuzzy +msgstr "" + msgid "Unable to load SILC key pair" -msgstr "Could not load public key" +msgstr "" #. Progress msgid "Connecting to SILC Server" -msgstr "Connecting to SILC Server" +msgstr "" msgid "Out of memory" -msgstr "Out of memory" - -#, fuzzy +msgstr "" + msgid "Unable to initialize SILC protocol" -msgstr "Cannot initialize SILC Client connection" - -#, fuzzy +msgstr "" + msgid "Error loading SILC key pair" -msgstr "Creating SILC key pair..." - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Download %s: %s" -msgstr "Users on %s: %s" +msgstr "" msgid "Your Current Mood" -msgstr "Your Current Mood" +msgstr "" #, c-format msgid "Normal" -msgstr "Normal" +msgstr "" msgid "" "\n" "Your Preferred Contact Methods" msgstr "" -"\n" -"Your Preferred Contact Methods" msgid "SMS" -msgstr "SMS" +msgstr "" msgid "MMS" -msgstr "MMS" - -#, fuzzy +msgstr "" + msgid "Video conferencing" -msgstr "Video Conferencing" +msgstr "" msgid "Your Current Status" -msgstr "Your Current Status" +msgstr "" msgid "Online Services" -msgstr "Online Services" +msgstr "" msgid "Let others see what services you are using" -msgstr "Let others see what services you are using" +msgstr "" msgid "Let others see what computer you are using" -msgstr "Let others see what computer you are using" +msgstr "" msgid "Your VCard File" -msgstr "Your VCard File" - -#, fuzzy +msgstr "" + msgid "Timezone (UTC)" -msgstr "Time Zone" +msgstr "" msgid "User Online Status Attributes" -msgstr "User Online Status Attributes" +msgstr "" msgid "" "You can let other users see your online status information and your personal " "information. Please fill the information you would like other users to see " "about yourself." msgstr "" -"You can let other users see your online status information and your personal " -"information. Please fill the information you would like other users to see " -"about yourself." msgid "Message of the Day" -msgstr "Message of the Day" +msgstr "" msgid "No Message of the Day available" -msgstr "No Message of the Day available" +msgstr "" msgid "There is no Message of the Day associated with this connection" -msgstr "There is no Message of the Day associated with this connection" - -#, fuzzy +msgstr "" + msgid "Create New SILC Key Pair" -msgstr "Default SILC Key Pair" - -#, fuzzy +msgstr "" + msgid "Passphrases do not match" -msgstr "New passwords do not match." - -#, fuzzy +msgstr "" + msgid "Key Pair Generation failed" -msgstr "Key agreement failed" - -#, fuzzy +msgstr "" + msgid "Key length" -msgstr "Key length: \t%d bits\n" - -#, fuzzy +msgstr "" + msgid "Public key file" -msgstr "Public key file" - -#, fuzzy +msgstr "" + msgid "Private key file" -msgstr "Private key file" - -#, fuzzy +msgstr "" + msgid "Passphrase (retype)" -msgstr "Password sent" - -#, fuzzy +msgstr "" + msgid "Generate Key Pair" -msgstr "Default SILC Key Pair" +msgstr "" msgid "Online Status" -msgstr "Online Status" +msgstr "" msgid "View Message of the Day" -msgstr "View Message of the Day" - -#, fuzzy +msgstr "" + msgid "Create SILC Key Pair..." -msgstr "Creating SILC key pair..." +msgstr "" #, c-format msgid "User %s is not present in the network" -msgstr "User %s is not present in the network" +msgstr "" msgid "Topic too long" -msgstr "Topic too long" +msgstr "" msgid "You must specify a nick" -msgstr "You must specify a nick" +msgstr "" #, c-format msgid "channel %s not found" -msgstr "channel %s not found" +msgstr "" #, c-format msgid "channel modes for %s: %s" -msgstr "channel modes for %s: %s" +msgstr "" #, c-format msgid "no channel modes are set on %s" -msgstr "no channel modes are set on %s" +msgstr "" #, c-format msgid "Failed to set cmodes for %s" -msgstr "Failed to set cmodes for %s" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Unknown command: %s, (may be a client bug)" -msgstr "Unknown command: %s, (may be a Pidgin bug)" +msgstr "" msgid "part [channel]: Leave the chat" -msgstr "part [channel]: Leave the chat" +msgstr "" msgid "leave [channel]: Leave the chat" -msgstr "leave [channel]: Leave the chat" +msgstr "" msgid "topic [<new topic>]: View or change the topic" -msgstr "topic [<new topic>]: View or change the topic" +msgstr "" msgid "join <channel> [<password>]: Join a chat on this network" -msgstr "join <channel> [<password>]: Join a chat on this network" +msgstr "" msgid "list: List channels on this network" -msgstr "list: List channels on this network" +msgstr "" msgid "whois <nick>: View nick's information" -msgstr "whois <nick>: View nick's information" +msgstr "" msgid "msg <nick> <message>: Send a private message to a user" -msgstr "msg <nick> <message>: Send a private message to a user" +msgstr "" msgid "query <nick> [<message>]: Send a private message to a user" msgstr "" -"query <nick> [<message>]: Send a private message to a user" msgid "motd: View the server's Message Of The Day" -msgstr "motd: View the server's Message Of The Day" +msgstr "" msgid "detach: Detach this session" -msgstr "detach: Detach this session" +msgstr "" msgid "quit [message]: Disconnect from the server, with an optional message" -msgstr "quit [message]: Disconnect from the server, with an optional message" +msgstr "" msgid "call <command>: Call any silc client command" -msgstr "call <command>: Call any silc client command" +msgstr "" msgid "kill <nick> [-pubkey|<reason>]: Kill nick" -msgstr "kill <nick> [-pubkey|<reason>]: Kill nick" +msgstr "" msgid "nick <newnick>: Change your nickname" -msgstr "nick <newnick>: Change your nickname" +msgstr "" msgid "whowas <nick>: View nick's information" -msgstr "whowas <nick>: View nick's information" +msgstr "" msgid "" "cmode <channel> [+|-<modes>] [arguments]: Change or display " "channel modes" msgstr "" -"cmode <channel> [+|-<modes>] [arguments]: Change or display " -"channel modes" msgid "" "cumode <channel> +|-<modes> <nick>: Change nick's modes " "on channel" msgstr "" -"cumode <channel> +|-<modes> <nick>: Change nick's modes " -"on channel" msgid "umode <usermodes>: Set your modes in the network" -msgstr "umode <usermodes>: Set your modes in the network" +msgstr "" msgid "oper <nick> [-pubkey]: Get server operator privileges" -msgstr "oper <nick> [-pubkey]: Get server operator privileges" +msgstr "" msgid "" "invite <channel> [-|+]<nick>: invite nick or add/remove from " "channel invite list" msgstr "" -"invite <channel> [-|+]<nick>: invite nick or add/remove from " -"channel invite list" msgid "kick <channel> <nick> [comment]: Kick client from channel" -msgstr "kick <channel> <nick> [comment]: Kick client from channel" +msgstr "" msgid "info [server]: View server administrative details" -msgstr "info [server]: View server administrative details" +msgstr "" msgid "ban [<channel> +|-<nick>]: Ban client from channel" -msgstr "ban [<channel> +|-<nick>]: Ban client from channel" +msgstr "" msgid "getkey <nick|server>: Retrieve client's or server's public key" -msgstr "getkey <nick|server>: Retrieve client's or server's public key" +msgstr "" msgid "stats: View server and network statistics" -msgstr "stats: View server and network statistics" +msgstr "" msgid "ping: Send PING to the connected server" -msgstr "ping: Send PING to the connected server" +msgstr "" msgid "users <channel>: List users in channel" -msgstr "users <channel>: List users in channel" +msgstr "" msgid "" "names [-count|-ops|-halfops|-voices|-normal] <channel(s)>: List " "specific users in channel(s)" msgstr "" -"names [-count|-ops|-halfops|-voices|-normal] <channel(s)>: List " -"specific users in channel(s)" #. *< type #. *< ui_requirement @@ -10614,22 +8814,20 @@ #. *< version #. * summary msgid "SILC Protocol Plugin" -msgstr "SILC Protocol Plugin" +msgstr "" #. * description msgid "Secure Internet Live Conferencing (SILC) Protocol" -msgstr "Secure Internet Live Conferencing (SILC) Protocol" +msgstr "" msgid "Network" -msgstr "Network" - -#, fuzzy +msgstr "" + msgid "Public Key file" -msgstr "Public key file" - -#, fuzzy +msgstr "" + msgid "Private Key file" -msgstr "Private key file" +msgstr "" msgid "Cipher" msgstr "" @@ -10641,67 +8839,64 @@ msgstr "" msgid "Public key authentication" -msgstr "Public key authentication" +msgstr "" msgid "Block IMs without Key Exchange" -msgstr "Block IMs without Key Exchange" +msgstr "" msgid "Block messages to whiteboard" msgstr "" -#, fuzzy msgid "Automatically open whiteboard" -msgstr "_Automatically expand contacts" - -#, fuzzy +msgstr "" + msgid "Digitally sign and verify all messages" -msgstr "Digitally sign all IM messages" +msgstr "" msgid "Creating SILC key pair..." -msgstr "Creating SILC key pair..." - -#, fuzzy +msgstr "" + msgid "Unable to create SILC key pair" -msgstr "Creating SILC key pair..." +msgstr "" #. Hint for translators: Please check the tabulator width here and in #. the next strings (short strings: 2 tabs, longer strings 1 tab, #. sum: 3 tabs or 24 characters) #, c-format msgid "Real Name: \t%s\n" -msgstr "Real Name: \t%s\n" +msgstr "" #, c-format msgid "User Name: \t%s\n" -msgstr "User Name: \t%s\n" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Email: \t\t%s\n" -msgstr "EMail: \t\t%s\n" +msgstr "" #, c-format msgid "Host Name: \t%s\n" -msgstr "Host Name: \t%s\n" +msgstr "" #, c-format msgid "Organization: \t%s\n" -msgstr "Organization: \t%s\n" +msgstr "" #, c-format msgid "Country: \t%s\n" -msgstr "Country: \t%s\n" +msgstr "" #, c-format msgid "Algorithm: \t%s\n" -msgstr "Algorithm: \t%s\n" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Key Length: \t%d bits\n" -msgstr "Key length: \t%d bits\n" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Version: \t%s\n" -msgstr "Organization: \t%s\n" +msgstr "" #, c-format msgid "" @@ -10709,35 +8904,30 @@ "%s\n" "\n" msgstr "" -"Public Key Fingerprint:\n" -"%s\n" -"\n" #, c-format msgid "" "Public Key Babbleprint:\n" "%s" msgstr "" -"Public Key Babbleprint:\n" -"%s" msgid "Public Key Information" -msgstr "Public Key Information" +msgstr "" msgid "Paging" -msgstr "Paging" +msgstr "" msgid "Video Conferencing" -msgstr "Video Conferencing" +msgstr "" msgid "Computer" -msgstr "Computer" +msgstr "" msgid "PDA" -msgstr "PDA" +msgstr "" msgid "Terminal" -msgstr "Terminal" +msgstr "" #, c-format msgid "%s sent message to whiteboard. Would you like to open the whiteboard?" @@ -10753,82 +8943,78 @@ msgstr "" msgid "No server statistics available" -msgstr "No server statistics available" +msgstr "" msgid "Error during connecting to SILC Server" -msgstr "Error during connecting to SILC Server" +msgstr "" #, c-format msgid "Failure: Version mismatch, upgrade your client" -msgstr "Failure: Version mismatch; upgrade your client" +msgstr "" #, c-format msgid "Failure: Remote does not trust/support your public key" -msgstr "Failure: Remote does not trust/support your public key" +msgstr "" #, c-format msgid "Failure: Remote does not support proposed KE group" -msgstr "Failure: Remote does not support proposed KE group" +msgstr "" #, c-format msgid "Failure: Remote does not support proposed cipher" -msgstr "Failure: Remote does not support proposed cipher" +msgstr "" #, c-format msgid "Failure: Remote does not support proposed PKCS" -msgstr "Failure: Remote does not support proposed PKCS" +msgstr "" #, c-format msgid "Failure: Remote does not support proposed hash function" -msgstr "Failure: Remote does not support proposed hash function" +msgstr "" #, c-format msgid "Failure: Remote does not support proposed HMAC" -msgstr "Failure: Remote does not support proposed HMAC" +msgstr "" #, c-format msgid "Failure: Incorrect signature" -msgstr "Failure: Incorrect signature" +msgstr "" #, c-format msgid "Failure: Invalid cookie" -msgstr "Failure: Invalid cookie" +msgstr "" #, c-format msgid "Failure: Authentication failed" -msgstr "Failure: Authentication failed" - -#, fuzzy +msgstr "" + msgid "Unable to initialize SILC Client connection" -msgstr "Cannot initialize SILC Client connection" - -#, fuzzy +msgstr "" + msgid "John Noname" -msgstr "Last name:" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Unable to load SILC key pair: %s" -msgstr "Could not load public key" - -#, fuzzy +msgstr "" + msgid "Unable to create connection" -msgstr "Unable to create new connection." - -#, fuzzy +msgstr "" + msgid "Unknown server response" -msgstr "Unknown error." - -#, fuzzy +msgstr "" + msgid "Unable to create listen socket" -msgstr "Unable to create socket" - -#, fuzzy +msgstr "" + +msgid "Unable to resolve hostname" +msgstr "" + msgid "SIP usernames may not contain whitespaces or @ symbols" -msgstr "IRC nicks may not contain whitespace" - -#, fuzzy +msgstr "" + msgid "SIP connect server not specified" -msgstr "Show fewer options" +msgstr "" #. *< type #. *< ui_requirement @@ -10838,52 +9024,42 @@ #. *< id #. *< name #. *< version -#, fuzzy msgid "SIP/SIMPLE Protocol Plugin" -msgstr "SILC Protocol Plugin" +msgstr "" #. * summary -#, fuzzy msgid "The SIP/SIMPLE Protocol Plugin" -msgstr "SILC Protocol Plugin" +msgstr "" msgid "Publish status (note: everyone may watch you)" msgstr "" -#, fuzzy msgid "Use UDP" -msgstr "User ID" - -#, fuzzy +msgstr "" + msgid "Use proxy" -msgstr "No Proxy" - -#, fuzzy +msgstr "" + msgid "Proxy" -msgstr "No Proxy" - -#, fuzzy +msgstr "" + msgid "Auth User" -msgstr "AP User" - -#, fuzzy +msgstr "" + msgid "Auth Domain" -msgstr "Automatic" - -#, fuzzy +msgstr "" + msgid "join <room>: Join a chat room on the Yahoo network" -msgstr "join: <room> [server]: Join a chat on this server." - -#, fuzzy +msgstr "" + msgid "list: List rooms on the Yahoo network" -msgstr "list: List channels on this network" +msgstr "" msgid "doodle: Request user to start a Doodle session" msgstr "" -#, fuzzy msgid "Yahoo ID..." -msgstr "Yahoo! ID" +msgstr "" #. *< type #. *< ui_requirement @@ -10895,23 +9071,20 @@ #. *< version #. * summary #. * description -#, fuzzy msgid "Yahoo! Protocol Plugin" -msgstr "Yahoo Protocol Plugin" +msgstr "" msgid "Pager port" -msgstr "Pager port" - -#, fuzzy +msgstr "" + msgid "File transfer server" -msgstr "File transfer host" +msgstr "" msgid "File transfer port" -msgstr "File transfer port" - -#, fuzzy +msgstr "" + msgid "Chat room locale" -msgstr "Chat Room List Url" +msgstr "" msgid "Ignore conference and chatroom invitations" msgstr "" @@ -10919,13 +9092,11 @@ msgid "Use account proxy for HTTP and HTTPS connections" msgstr "" -#, fuzzy msgid "Chat room list URL" -msgstr "Chat Room List Url" - -#, fuzzy +msgstr "" + msgid "Yahoo JAPAN ID..." -msgstr "Yahoo! ID" +msgstr "" #. *< type #. *< ui_requirement @@ -10937,9 +9108,8 @@ #. *< version #. * summary #. * description -#, fuzzy msgid "Yahoo! JAPAN Protocol Plugin" -msgstr "Yahoo Protocol Plugin" +msgstr "" #, c-format msgid "%s has sent you a webcam invite, which is not yet supported." @@ -10949,91 +9119,80 @@ msgstr "" msgid "Your Yahoo! message did not get sent." -msgstr "Your Yahoo! message did not get sent." +msgstr "" #, c-format msgid "Yahoo! system message for %s:" -msgstr "Yahoo! system message for %s:" +msgstr "" + +msgid "Authorization denied message:" +msgstr "" #, c-format msgid "" "%s has (retroactively) denied your request to add them to your list for the " "following reason: %s." msgstr "" -"%s has (retroactively) denied your request to add them to your list for the " -"following reason: %s." #, c-format msgid "%s has (retroactively) denied your request to add them to your list." -msgstr "%s has (retroactively) denied your request to add them to your list." +msgstr "" msgid "Add buddy rejected" -msgstr "Add buddy rejected" +msgstr "" #. Some error in the received stream -#, fuzzy msgid "Received invalid data" -msgstr "Unable to make SSL connection to server." +msgstr "" #. security lock from too many failed login attempts -#, fuzzy msgid "" "Account locked: Too many failed login attempts. Logging into the Yahoo! " "website may fix this." -msgstr "Unknown error number %d. Logging into the Yahoo! website may fix this." +msgstr "" #. indicates a lock of some description -#, fuzzy msgid "" "Account locked: Unknown reason. Logging into the Yahoo! website may fix " "this." -msgstr "Unknown error number %d. Logging into the Yahoo! website may fix this." +msgstr "" #. indicates a lock due to logging in too frequently -#, fuzzy msgid "" "Account locked: You have been logging in too frequently. Wait a few minutes " "before trying to connect again. Logging into the Yahoo! website may help." -msgstr "Unknown error number %d. Logging into the Yahoo! website may fix this." +msgstr "" #. username or password missing -#, fuzzy msgid "Username or password missing" -msgstr "Incorrect nickname or password." - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "" "The Yahoo server has requested the use of an unrecognized authentication " "method. You will probably not be able to successfully sign on to Yahoo. " "Check %s for updates." msgstr "" -"The Yahoo server has requested the use of an unrecognized authentication " -"method. This version of Pidgin will likely not be able to successfully sign " -"on to Yahoo. Check %s for updates." msgid "Failed Yahoo! Authentication" -msgstr "Failed Yahoo! Authentication" +msgstr "" #, c-format msgid "" "You have tried to ignore %s, but the user is on your buddy list. Clicking " "\"Yes\" will remove and ignore the buddy." msgstr "" -"You have tried to ignore %s, but the user is on your buddy list. Clicking " -"\"Yes\" will remove and ignore the buddy." msgid "Ignore buddy?" -msgstr "Ignore buddy?" - -#, fuzzy +msgstr "" + msgid "Invalid username or password" -msgstr "Incorrect nickname or password." - -#, fuzzy +msgstr "" + msgid "" "Your account has been locked due to too many failed login attempts. Please " "try logging into the Yahoo! website." -msgstr "Unknown error number %d. Logging into the Yahoo! website may fix this." +msgstr "" #, c-format msgid "Unknown error 52. Reconnecting should fix this." @@ -11046,85 +9205,73 @@ #, c-format msgid "Unknown error number %d. Logging into the Yahoo! website may fix this." -msgstr "Unknown error number %d. Logging into the Yahoo! website may fix this." - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Unable to add buddy %s to group %s to the server list on account %s." -msgstr "Could not add buddy %s to group %s to the server list on account %s." - -#, fuzzy +msgstr "" + msgid "Unable to add buddy to server list" -msgstr "Could not add buddy to server list" +msgstr "" #, c-format msgid "[ Audible %s/%s/%s.swf ] %s" msgstr "" -#, fuzzy msgid "Received unexpected HTTP response from server" -msgstr "Invalid response from server." - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Lost connection with %s: %s" -msgstr "Conversations with %s" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Unable to establish a connection with %s: %s" -msgstr "Unable to make SSL connection to server." - -#, fuzzy +msgstr "" + msgid "Unable to connect: The server returned an empty response." msgstr "" -"Unable to connect to server. Please enter the address of the server you wish " -"to connect to." msgid "" "Unable to connect: The server's response did not contain the necessary " "information" msgstr "" -#, fuzzy msgid "Not at Home" -msgstr "Not At Home" - -#, fuzzy +msgstr "" + msgid "Not at Desk" -msgstr "Not At Desk" - -#, fuzzy +msgstr "" + msgid "Not in Office" -msgstr "Not In Office" +msgstr "" msgid "On Vacation" -msgstr "On Vacation" +msgstr "" msgid "Stepped Out" -msgstr "Stepped Out" +msgstr "" msgid "Not on server list" -msgstr "Not on server list" - -#, fuzzy +msgstr "" + msgid "Appear Permanently Offline" -msgstr "Appear Offline" - -#, fuzzy +msgstr "" + msgid "Presence" -msgstr "Preferences" - -#, fuzzy +msgstr "" + msgid "Don't Appear Permanently Offline" -msgstr "Appear Offline" +msgstr "" msgid "Join in Chat" -msgstr "Join in Chat" +msgstr "" msgid "Initiate Conference" -msgstr "Initiate Conference" - -#, fuzzy +msgstr "" + msgid "Presence Settings" -msgstr "Use Environmental Settings" +msgstr "" msgid "Start Doodling" msgstr "" @@ -11133,14 +9280,13 @@ msgstr "" msgid "Join whom in chat?" -msgstr "Join whom in chat?" +msgstr "" msgid "Activate ID..." -msgstr "Activate ID..." - -#, fuzzy +msgstr "" + msgid "Join User in Chat..." -msgstr "Join user in chat..." +msgstr "" msgid "Open Inbox" msgstr "" @@ -11161,112 +9307,94 @@ msgstr "" msgid "Unable to connect." -msgstr "Unable to connect." +msgstr "" msgid "Unable to establish file descriptor." -msgstr "Unable to establish file descriptor." - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "%s is trying to send you a group of %d files.\n" -msgstr "Offering to send %s to %s" - -#, fuzzy +msgstr "" + msgid "Write Error" -msgstr "Write error" +msgstr "" msgid "Yahoo! Japan Profile" -msgstr "Yahoo! Japan Profile" +msgstr "" msgid "Yahoo! Profile" -msgstr "Yahoo! Profile" +msgstr "" msgid "" "Sorry, profiles marked as containing adult content are not supported at this " "time." msgstr "" -"Sorry, profiles marked as containing adult content are not supported at this " -"time." - -#, fuzzy + msgid "" "If you wish to view this profile, you will need to visit this link in your " "web browser:" msgstr "" -"If you wish to view this profile, you will need to visit this link in your " -"web browser" msgid "Yahoo! ID" -msgstr "Yahoo! ID" +msgstr "" msgid "Hobbies" -msgstr "Hobbies" +msgstr "" msgid "Latest News" -msgstr "Latest News" +msgstr "" msgid "Home Page" -msgstr "Home Page" +msgstr "" msgid "Cool Link 1" -msgstr "Cool Link 1" +msgstr "" msgid "Cool Link 2" -msgstr "Cool Link 2" +msgstr "" msgid "Cool Link 3" -msgstr "Cool Link 3" - -#, fuzzy +msgstr "" + msgid "Last Update" -msgstr "Last Updated" - -#, fuzzy +msgstr "" + msgid "" "This profile is in a language or format that is not supported at this time." msgstr "" -"Sorry, this profile seems to be in a language that is not supported at this " -"time." msgid "" "Could not retrieve the user's profile. This most likely is a temporary " "server-side problem. Please try again later." msgstr "" -"Could not retrieve the user's profile. This most likely is a temporary " -"server-side problem. Please try again later." msgid "" "Could not retrieve the user's profile. This most likely means that the user " "does not exist; however, Yahoo! sometimes does fail to find a user's " "profile. If you know that the user exists, please try again later." msgstr "" -"Could not retrieve the user's profile. This most likely means that the user " -"does not exist; however, Yahoo! sometimes does fail to find a user's " -"profile. If you know that the user exists, please try again later." msgid "The user's profile is empty." -msgstr "The user's profile is empty." - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "%s has declined to join." -msgstr "%s has signed on (%s)" +msgstr "" msgid "Failed to join chat" -msgstr "Failed to join chat" +msgstr "" #. -6 -#, fuzzy msgid "Unknown room" -msgstr "Unknown Error" +msgstr "" #. -15 -#, fuzzy msgid "Maybe the room is full" -msgstr "Maybe the room is full?" +msgstr "" #. -35 -#, fuzzy msgid "Not available" -msgstr "Not Available" +msgstr "" msgid "" "Unknown error. You may need to logout and wait five minutes before being " @@ -11275,124 +9403,112 @@ #, c-format msgid "You are now chatting in %s." -msgstr "You are now chatting in %s." +msgstr "" msgid "Failed to join buddy in chat" -msgstr "Failed to join buddy in chat" +msgstr "" msgid "Maybe they're not in a chat?" -msgstr "Maybe they're not in a chat?" +msgstr "" msgid "Fetching the room list failed." -msgstr "Fetching the room list failed." +msgstr "" msgid "Voices" -msgstr "Voices" +msgstr "" msgid "Webcams" -msgstr "Webcams" +msgstr "" msgid "Connection problem" -msgstr "Connection problem" +msgstr "" msgid "Unable to fetch room list." -msgstr "Unable to fetch room list." +msgstr "" msgid "User Rooms" -msgstr "User Rooms" - -#, fuzzy +msgstr "" + msgid "Connection problem with the YCHT server" -msgstr "Connection problem with the YCHT server." +msgstr "" msgid "" "(There was an error converting this message.\t Check the 'Encoding' option " "in the Account Editor)" msgstr "" -"(There was an error converting this message.\t Check the 'Encoding' option " -"in the Account Editor)" - -#, fuzzy, c-format + +#, c-format msgid "Unable to send to chat %s,%s,%s" -msgstr "Unable send to chat %s,%s,%s" - -#, fuzzy +msgstr "" + msgid "Hidden or not logged-in" -msgstr "
Hidden or not logged-in" +msgstr "" #, c-format msgid "
At %s since %s" -msgstr "
At %s since %s" +msgstr "" msgid "Anyone" -msgstr "Anyone" +msgstr "" msgid "_Class:" -msgstr "_Class:" +msgstr "" msgid "_Instance:" -msgstr "_Instance:" +msgstr "" msgid "_Recipient:" -msgstr "_Recipient:" +msgstr "" #, c-format msgid "Attempt to subscribe to %s,%s,%s failed" -msgstr "Attempt to subscribe to %s,%s,%s failed" +msgstr "" msgid "zlocate <nick>: Locate user" -msgstr "zlocate <nick>: Locate user" +msgstr "" msgid "zl <nick>: Locate user" -msgstr "zl <nick>: Locate user" +msgstr "" msgid "instance <instance>: Set the instance to be used on this class" -msgstr "instance <instance>: Set the instance to be used on this class" +msgstr "" msgid "inst <instance>: Set the instance to be used on this class" -msgstr "inst <instance>: Set the instance to be used on this class" - -#, fuzzy +msgstr "" + msgid "topic <instance>: Set the instance to be used on this class" -msgstr "inst <instance>: Set the instance to be used on this class" +msgstr "" msgid "sub <class> <instance> <recipient>: Join a new chat" -msgstr "sub <class> <instance> <recipient>: Join a new chat" +msgstr "" msgid "" "zi <instance>: Send a message to <message,instance,*>" msgstr "" -"zi <instance>: Send a message to <message,instance,*>" msgid "" "zci <class> <instance>: Send a message to <class," "instance,*>" msgstr "" -"zci <class> <instance>: Send a message to <class," -"instance,*>" msgid "" "zcir <class> <instance> <recipient>: Send a message to <" "class,instance,recipient>" msgstr "" -"zcir <class> <instance> <recipient>: Send a message to <" -"class,instance,recipient>" msgid "" "zir <instance> <recipient>: Send a message to <MESSAGE," "instance,recipient>" msgstr "" -"zir <instance> <recipient>: Send a message to <MESSAGE," -"instance,recipient>" msgid "zc <class>: Send a message to <class,PERSONAL,*>" -msgstr "zc <class>: Send a message to <class,PERSONAL,*>" +msgstr "" msgid "Resubscribe" -msgstr "Resubscribe" +msgstr "" msgid "Retrieve subscriptions from server" -msgstr "Retrieve subscriptions from server" +msgstr "" #. *< type #. *< ui_requirement @@ -11405,75 +9521,68 @@ #. * summary #. * description msgid "Zephyr Protocol Plugin" -msgstr "Zephyr Protocol Plugin" - -#, fuzzy +msgstr "" + msgid "Use tzc" -msgstr "Unit" - -#, fuzzy +msgstr "" + msgid "tzc command" -msgstr "No such command." +msgstr "" msgid "Export to .anyone" -msgstr "Export to .anyone" +msgstr "" msgid "Export to .zephyr.subs" -msgstr "Export to .zephyr.subs" - -#, fuzzy +msgstr "" + msgid "Import from .anyone" -msgstr "Export to .anyone" - -#, fuzzy +msgstr "" + msgid "Import from .zephyr.subs" -msgstr "Export to .zephyr.subs" - -#, fuzzy +msgstr "" + msgid "Realm" -msgstr "Realname" +msgstr "" msgid "Exposure" -msgstr "Exposure" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Unable to create socket: %s" -msgstr "Unable to create socket" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Unable to parse response from HTTP proxy: %s" -msgstr "Unable to send message: %s" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "HTTP proxy connection error %d" -msgstr "Proxy connection error %d" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Access denied: HTTP proxy server forbids port %d tunneling" -msgstr "Access denied: proxy server forbids port %d tunnelling." - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Error resolving %s" -msgstr "Error joining chat %s" +msgstr "" #, c-format msgid "Requesting %s's attention..." msgstr "" -#, fuzzy, c-format +#, c-format msgid "%s has requested your attention!" -msgstr "%s requested your information" +msgstr "" #. * #. * A wrapper for purple_request_action() that uses @c Yes and @c No buttons. #. -#, fuzzy msgid "_Yes" -msgstr "Yes" - -#, fuzzy +msgstr "" + msgid "_No" -msgstr "No" +msgstr "" #. * #. * A wrapper for purple_request_action() that uses Accept and Cancel buttons. @@ -11482,9 +9591,8 @@ #. * A wrapper for purple_request_action_with_icon() that uses Accept and Cancel #. * buttons. #. -#, fuzzy msgid "_Accept" -msgstr "Accept" +msgstr "" #. * #. * The default message to use when the user becomes auto-away. @@ -11492,101 +9600,91 @@ msgid "I'm not here right now" msgstr "" -#, fuzzy msgid "saved statuses" -msgstr "Server Statistics" +msgstr "" #, c-format msgid "%s is now known as %s.\n" -msgstr "%s is now known as %s.\n" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "" "%s has invited %s to the chat room %s:\n" "%s" -msgstr "%s has invited %s to the chat room %s\n" +msgstr "" #, c-format msgid "%s has invited %s to the chat room %s\n" -msgstr "%s has invited %s to the chat room %s\n" +msgstr "" msgid "Accept chat invitation?" -msgstr "Accept chat invitation?" +msgstr "" #. Shortcut -#, fuzzy msgid "Shortcut" -msgstr "Shortcuts" +msgstr "" msgid "The text-shortcut for the smiley" msgstr "" #. Stored Image -#, fuzzy msgid "Stored Image" -msgstr "Save Image" +msgstr "" msgid "Stored Image. (that'll have to do for now)" msgstr "" -#, fuzzy msgid "SSL Connection Failed" -msgstr "Connection Failed" +msgstr "" msgid "SSL Handshake Failed" -msgstr "SSL Handshake Failed" - -#, fuzzy +msgstr "" + msgid "SSL peer presented an invalid certificate" -msgstr "You have entered an invalid username" - -#, fuzzy +msgstr "" + msgid "Unknown SSL error" -msgstr "Unknown error" - -#, fuzzy +msgstr "" + msgid "Unset" -msgstr "Unit" - -#, fuzzy +msgstr "" + msgid "Do not disturb" -msgstr "Do Not Disturb" - -#, fuzzy +msgstr "" + msgid "Extended away" -msgstr "Extended Away" - -#, fuzzy +msgstr "" + msgid "Feeling" -msgstr "Remaining" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "%s (%s) changed status from %s to %s" -msgstr "%s has changed the topic to: %s" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "%s (%s) is now %s" -msgstr "%s is now known as %s" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "%s (%s) is no longer %s" -msgstr "%s is no longer away." +msgstr "" #, c-format msgid "%s became idle" -msgstr "%s became idle" +msgstr "" #, c-format msgid "%s became unidle" -msgstr "%s became unidle" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "+++ %s became idle" -msgstr "%s became idle" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "+++ %s became unidle" -msgstr "%s became unidle" +msgstr "" #. #. * This string determines how some dates are displayed. The default @@ -11599,60 +9697,52 @@ msgstr "" msgid "Calculating..." -msgstr "Calculating..." +msgstr "" msgid "Unknown." -msgstr "Unknown." - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "%d second" msgid_plural "%d seconds" -msgstr[0] "second" -msgstr[1] "seconds" - -#, fuzzy, c-format +msgstr[0] "" + +#, c-format msgid "%d day" msgid_plural "%d days" -msgstr[0] "day" -msgstr[1] "days" +msgstr[0] "" #, c-format msgid "%s, %d hour" msgid_plural "%s, %d hours" msgstr[0] "" -msgstr[1] "" - -#, fuzzy, c-format + +#, c-format msgid "%d hour" msgid_plural "%d hours" -msgstr[0] "hour" -msgstr[1] "hours" - -#, fuzzy, c-format +msgstr[0] "" + +#, c-format msgid "%s, %d minute" msgid_plural "%s, %d minutes" -msgstr[0] "minute" -msgstr[1] "minutes" - -#, fuzzy, c-format +msgstr[0] "" + +#, c-format msgid "%d minute" msgid_plural "%d minutes" -msgstr[0] "minute" -msgstr[1] "minutes" +msgstr[0] "" #, c-format msgid "Could not open %s: Redirected too many times" msgstr "" -#, fuzzy, c-format +#, c-format msgid "Unable to connect to %s" -msgstr "Unable to connect to server." - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Error reading from %s: response too long (%d bytes limit)" msgstr "" -"Error reading %s: \n" -"%s.\n" #, c-format msgid "" @@ -11660,136 +9750,119 @@ "server may be trying something malicious." msgstr "" -#, fuzzy, c-format +#, c-format msgid "Error reading from %s: %s" msgstr "" -"Error reading %s: \n" -"%s.\n" - -#, fuzzy, c-format + +#, c-format msgid "Error writing to %s: %s" msgstr "" -"Error writing %s: \n" -"%s.\n" - -#, fuzzy, c-format + +#, c-format msgid "Unable to connect to %s: %s" -msgstr "Unable to connect to server." +msgstr "" #, c-format msgid " - %s" msgstr "" -#, fuzzy, c-format +#, c-format msgid " (%s)" -msgstr "%s on %s (%s)" +msgstr "" #. 10053 msgid "Connection interrupted by other software on your computer." msgstr "" #. 10054 -#, fuzzy msgid "Remote host closed connection." -msgstr "The remote user is not present in the network any more" +msgstr "" #. 10060 -#, fuzzy msgid "Connection timed out." -msgstr "Connection Timeout" +msgstr "" #. 10061 -#, fuzzy msgid "Connection refused." -msgstr "Connection Closed" +msgstr "" #. 10048 -#, fuzzy msgid "Address already in use." -msgstr "That file already exists" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Error Reading %s" msgstr "" -"Error reading %s: \n" -"%s.\n" - -#, fuzzy, c-format + +#, c-format msgid "" "An error was encountered reading your %s. The file has not been loaded, and " "the old file has been renamed to %s~." msgstr "" -"An error was encountered parsing your buddy list. It has not been loaded, " -"and the old file has moved to blist.xml~." msgid "" "Chat over IM. Supports AIM, Google Talk, Jabber/XMPP, MSN, Yahoo and more" msgstr "" -#, fuzzy msgid "Internet Messenger" -msgstr "Instant Messagers" - -#, fuzzy +msgstr "" + msgid "Pidgin Internet Messenger" -msgstr "Instant Messagers" +msgstr "" #. Build the login options frame. msgid "Login Options" -msgstr "Login Options" - -#, fuzzy +msgstr "" + msgid "Pro_tocol:" -msgstr "Protocol:" +msgstr "" msgid "_Username:" -msgstr "_Username:" - -#, fuzzy +msgstr "" + msgid "Remember pass_word" -msgstr "Remember password" +msgstr "" #. Build the user options frame. msgid "User Options" -msgstr "User Options" - -#, fuzzy +msgstr "" + msgid "_Local alias:" -msgstr "Local Users" - -#, fuzzy +msgstr "" + msgid "New _mail notifications" -msgstr "New mail notifications" +msgstr "" #. Buddy icon msgid "Use this buddy _icon for this account:" msgstr "" -#, fuzzy msgid "Ad_vanced" -msgstr "_Cancel" - -#, fuzzy +msgstr "" + msgid "Use GNOME Proxy Settings" -msgstr "Use Global Proxy Settings" +msgstr "" msgid "Use Global Proxy Settings" -msgstr "Use Global Proxy Settings" +msgstr "" msgid "No Proxy" -msgstr "No Proxy" - -msgid "HTTP" -msgstr "HTTP" +msgstr "" msgid "SOCKS 4" -msgstr "SOCKS 4" +msgstr "" msgid "SOCKS 5" -msgstr "SOCKS 5" +msgstr "" + +msgid "Tor/Privacy (SOCKS5)" +msgstr "" + +msgid "HTTP" +msgstr "" msgid "Use Environmental Settings" -msgstr "Use Environmental Settings" +msgstr "" #. This is an easter egg. #. It means one of two things, both intended as humourus: @@ -11797,51 +9870,53 @@ #. look at butterflies. #. B)You are looking really closely at something that shouldn't matter. msgid "If you look real closely" -msgstr "If you look real closely" +msgstr "" #. This is an easter egg. See the comment on the previous line in the source. msgid "you can see the butterflies mating" -msgstr "you can see the butterflies mating" +msgstr "" msgid "Proxy _type:" -msgstr "Proxy _type:" +msgstr "" msgid "_Host:" -msgstr "_Host:" +msgstr "" msgid "_Port:" -msgstr "_Port:" +msgstr "" msgid "Pa_ssword:" -msgstr "Pa_ssword:" - -#, fuzzy +msgstr "" + +msgid "Use _silence suppression" +msgstr "" + +msgid "_Voice and Video" +msgstr "" + msgid "Unable to save new account" -msgstr "Unable to create new connection." +msgstr "" msgid "An account already exists with the specified criteria." msgstr "" msgid "Add Account" -msgstr "Add Account" - -#, fuzzy +msgstr "" + msgid "_Basic" -msgstr "Back" +msgstr "" msgid "Create _this new account on the server" msgstr "" -#, fuzzy msgid "P_roxy" -msgstr "No Proxy" - -#, fuzzy +msgstr "" + msgid "Enabled" -msgstr "Failed" +msgstr "" msgid "Protocol" -msgstr "Protocol" +msgstr "" #, c-format msgid "" @@ -11856,60 +9931,61 @@ "Accounts->Manage Accounts in the Buddy List window" msgstr "" -#, fuzzy, c-format +#, c-format +msgid "" +"%s%s%s%s wants to add you (%s) to his or her buddy " +"list%s%s" +msgstr "" + +#, c-format msgid "%s%s%s%s wants to add you (%s) to his or her buddy list%s%s" -msgstr "The user %s wants to add %s to his or her buddy list." +msgstr "" + +msgid "Send Instant Message" +msgstr "" #. Buddy List -#, fuzzy msgid "Background Color" -msgstr "Background colour" - -#, fuzzy +msgstr "Background Colour" + msgid "The background color for the buddy list" -msgstr "Do you want to add this buddy to your buddy list?" - -#, fuzzy +msgstr "The background colour for the buddy list" + msgid "Layout" -msgstr "Logged out" - -#, fuzzy +msgstr "" + msgid "The layout of icons, name, and status of the buddy list" -msgstr "The user %s wants to add you to their buddy list." +msgstr "" #. Group #. Note to translators: These two strings refer to the background color #. of a buddy list group when in its expanded state -#, fuzzy msgid "Expanded Background Color" -msgstr "Background colour" +msgstr "Expanded Background Colour" msgid "The background color of an expanded group" -msgstr "" +msgstr "The background colour of an expanded group" #. Note to translators: These two strings refer to the font and color #. of a buddy list group when in its expanded state -#, fuzzy msgid "Expanded Text" -msgstr "_Expand" +msgstr "" msgid "The text information for when a group is expanded" msgstr "" #. Note to translators: These two strings refer to the background color #. of a buddy list group when in its collapsed state -#, fuzzy msgid "Collapsed Background Color" -msgstr "Select Background Colour" +msgstr "Collapsed Background Colour" msgid "The background color of a collapsed group" -msgstr "" +msgstr "The background colour of a collapsed group" #. Note to translators: These two strings refer to the font and color #. of a buddy list group when in its collapsed state -#, fuzzy msgid "Collapsed Text" -msgstr "_Collapse" +msgstr "" msgid "The text information for when a group is collapsed" msgstr "" @@ -11917,92 +9993,78 @@ #. Buddy #. Note to translators: These two strings refer to the background color #. of a buddy list contact or chat room -#, fuzzy msgid "Contact/Chat Background Color" -msgstr "Select Background Colour" +msgstr "Contact/Chat Background Colour" msgid "The background color of a contact or chat" -msgstr "" +msgstr "The background colour of a contact or chat" #. Note to translators: These two strings refer to the font and color #. of a buddy list contact when in its expanded state -#, fuzzy msgid "Contact Text" -msgstr "Shortcuts" +msgstr "" msgid "The text information for when a contact is expanded" msgstr "" #. Note to translators: These two strings refer to the font and color #. of a buddy list buddy when it is online -#, fuzzy msgid "Online Text" -msgstr "Online" - -#, fuzzy +msgstr "" + msgid "The text information for when a buddy is online" -msgstr "Get information on the selected buddy" +msgstr "" #. Note to translators: These two strings refer to the font and color #. of a buddy list buddy when it is away -#, fuzzy msgid "Away Text" -msgstr "Away" - -#, fuzzy +msgstr "" + msgid "The text information for when a buddy is away" -msgstr "Get information on the selected buddy" +msgstr "" #. Note to translators: These two strings refer to the font and color #. of a buddy list buddy when it is offline -#, fuzzy msgid "Offline Text" -msgstr "Offline" - -#, fuzzy +msgstr "" + msgid "The text information for when a buddy is offline" -msgstr "Get information on the selected buddy" +msgstr "" #. Note to translators: These two strings refer to the font and color #. of a buddy list buddy when it is idle -#, fuzzy msgid "Idle Text" -msgstr "Mood" - -#, fuzzy +msgstr "" + msgid "The text information for when a buddy is idle" -msgstr "Get information on the selected buddy" +msgstr "" #. Note to translators: These two strings refer to the font and color #. of a buddy list buddy when they have sent you a new message msgid "Message Text" -msgstr "Message Text" +msgstr "" msgid "The text information for when a buddy has an unread message" msgstr "" #. Note to translators: These two strings refer to the font and color #. of a buddy list buddy when they have sent you a new message -#, fuzzy msgid "Message (Nick Said) Text" -msgstr "Message Text" - -#, fuzzy +msgstr "" + msgid "" "The text information for when a chat has an unread message that mentions " "your nickname" -msgstr "Get information on the selected buddy" - -#, fuzzy +msgstr "" + msgid "The text information for a buddy's status" -msgstr "Change user information for %s" +msgstr "" #, c-format msgid "You have %d contact named %s. Would you like to merge them?" msgid_plural "" "You currently have %d contacts named %s. Would you like to merge them?" msgstr[0] "" -msgstr[1] "" msgid "" "Merging these contacts will cause them to share a single entry on the buddy " @@ -12013,318 +10075,265 @@ msgid "Please update the necessary fields." msgstr "" -#, fuzzy msgid "A_ccount" -msgstr "Account:" +msgstr "" msgid "" "Please enter the appropriate information about the chat you would like to " "join.\n" msgstr "" -"Please enter the appropriate information about the chat you would like to " -"join.\n" - -#, fuzzy + msgid "Room _List" -msgstr "Room List" - -#, fuzzy +msgstr "" + msgid "_Block" -msgstr "Block" - -#, fuzzy +msgstr "" + msgid "Un_block" -msgstr "Block" +msgstr "" msgid "Move to" msgstr "" msgid "Get _Info" -msgstr "Get _Info" +msgstr "" msgid "I_M" -msgstr "I_M" - -#, fuzzy +msgstr "" + msgid "_Audio Call" -msgstr "Add Chat" +msgstr "" msgid "Audio/_Video Call" msgstr "" -#, fuzzy msgid "_Video Call" -msgstr "Video Chat" - -#, fuzzy +msgstr "" + msgid "_Send File..." -msgstr "_Send File" - -#, fuzzy +msgstr "" + msgid "Add Buddy _Pounce..." -msgstr "Add Buddy _Pounce" +msgstr "" msgid "View _Log" -msgstr "View _Log" - -#, fuzzy +msgstr "" + msgid "Hide When Offline" -msgstr "Not allowed when offline" - -#, fuzzy +msgstr "" + msgid "Show When Offline" -msgstr "Not allowed when offline" +msgstr "" msgid "_Alias..." -msgstr "_Alias..." +msgstr "" msgid "_Remove" -msgstr "_Remove" - -#, fuzzy +msgstr "" + msgid "Set Custom Icon" -msgstr "Custom" - -#, fuzzy +msgstr "" + msgid "Remove Custom Icon" -msgstr "Remove Contact" - -#, fuzzy +msgstr "" + msgid "Add _Buddy..." -msgstr "Add Buddy" - -#, fuzzy +msgstr "" + msgid "Add C_hat..." -msgstr "Add Chat" +msgstr "" msgid "_Delete Group" -msgstr "_Delete Group" +msgstr "" msgid "_Rename" -msgstr "_Rename" +msgstr "" #. join button msgid "_Join" -msgstr "_Join" +msgstr "" msgid "Auto-Join" -msgstr "Auto-Join" - -#, fuzzy +msgstr "" + msgid "Persistent" -msgstr "Permit" - -#, fuzzy +msgstr "" + msgid "_Edit Settings..." -msgstr "Use Environmental Settings" +msgstr "" msgid "_Collapse" -msgstr "_Collapse" +msgstr "" msgid "_Expand" -msgstr "_Expand" - -#, fuzzy +msgstr "" + msgid "/Tools/Mute Sounds" -msgstr "Mute Sounds" +msgstr "" msgid "" "You are not currently signed on with an account that can add that buddy." msgstr "" -"You are not currently signed on with an account that can add that buddy." #. I don't believe this can happen currently, I think #. * everything that calls this function checks for one of the #. * above node types first. -#, fuzzy msgid "Unknown node type" -msgstr "Unknown Error Code %d" - -#, fuzzy +msgstr "" + msgid "Please select your mood from the list" -msgstr "Please enter a new name for the selected group." - -#, fuzzy +msgstr "" + msgid "Message (optional)" -msgstr "Message Notification" - -#, fuzzy +msgstr "" + msgid "Edit User Mood" -msgstr "User Modes" +msgstr "" #. NOTE: Do not set any accelerator to Control+O. It is mapped by #. gtk_blist_key_press_cb to "Get User Info" on the selected buddy. #. Buddies menu msgid "/_Buddies" -msgstr "/_Buddies" +msgstr "" msgid "/Buddies/New Instant _Message..." -msgstr "/Buddies/New Instant _Message..." +msgstr "" msgid "/Buddies/Join a _Chat..." -msgstr "/Buddies/Join a _Chat..." +msgstr "" msgid "/Buddies/Get User _Info..." -msgstr "/Buddies/Get User _Info..." +msgstr "" msgid "/Buddies/View User _Log..." -msgstr "/Buddies/View User _Log..." - -#, fuzzy +msgstr "" + msgid "/Buddies/Sh_ow" -msgstr "/Buddies/_Signoff" - -#, fuzzy +msgstr "" + msgid "/Buddies/Show/_Offline Buddies" -msgstr "/Buddies/Show _Offline Buddies" - -#, fuzzy +msgstr "" + msgid "/Buddies/Show/_Empty Groups" -msgstr "/Buddies/Show _Empty Groups" - -#, fuzzy +msgstr "" + msgid "/Buddies/Show/Buddy _Details" -msgstr "/Buddies/Show Offline Buddies" - -#, fuzzy +msgstr "" + msgid "/Buddies/Show/Idle _Times" -msgstr "/Buddies/Show Offline Buddies" - -#, fuzzy +msgstr "" + msgid "/Buddies/Show/_Protocol Icons" -msgstr "/Buddies/Show _Empty Groups" - -#, fuzzy +msgstr "" + msgid "/Buddies/_Sort Buddies" -msgstr "/Buddies/Show Offline Buddies" +msgstr "" msgid "/Buddies/_Add Buddy..." -msgstr "/Buddies/_Add Buddy..." +msgstr "" msgid "/Buddies/Add C_hat..." -msgstr "/Buddies/Add C_hat..." +msgstr "" msgid "/Buddies/Add _Group..." -msgstr "/Buddies/Add _Group..." +msgstr "" msgid "/Buddies/_Quit" -msgstr "/Buddies/_Quit" +msgstr "" #. Accounts menu -#, fuzzy msgid "/_Accounts" -msgstr "Accounts" - -#, fuzzy +msgstr "" + msgid "/Accounts/Manage Accounts" -msgstr "Accounts" +msgstr "" #. Tools msgid "/_Tools" -msgstr "/_Tools" - -#, fuzzy +msgstr "" + msgid "/Tools/Buddy _Pounces" -msgstr "/Tools/Buddy _Pounce" - -#, fuzzy +msgstr "" + msgid "/Tools/_Certificates" -msgstr "/Tools/Pr_eferences" - -#, fuzzy +msgstr "" + msgid "/Tools/Custom Smile_ys" -msgstr "/Tools/_Away" - -#, fuzzy +msgstr "" + msgid "/Tools/Plu_gins" -msgstr "/Tools/Plugin Actions" +msgstr "" msgid "/Tools/Pr_eferences" -msgstr "/Tools/Pr_eferences" +msgstr "" msgid "/Tools/Pr_ivacy" -msgstr "/Tools/Pr_ivacy" - -#, fuzzy +msgstr "" + msgid "/Tools/Set _Mood" -msgstr "/Tools/View System _Log" +msgstr "" msgid "/Tools/_File Transfers" -msgstr "/Tools/_File Transfers" +msgstr "" msgid "/Tools/R_oom List" -msgstr "/Tools/R_oom List" - -#, fuzzy +msgstr "" + msgid "/Tools/System _Log" -msgstr "/Tools/View System _Log" - -#, fuzzy +msgstr "" + msgid "/Tools/Mute _Sounds" -msgstr "Mute Sounds" +msgstr "" #. Help msgid "/_Help" -msgstr "/_Help" +msgstr "" msgid "/Help/Online _Help" -msgstr "/Help/Online _Help" - -#, fuzzy +msgstr "" + msgid "/Help/_Build Information" -msgstr "Buddy Information" +msgstr "" msgid "/Help/_Debug Window" -msgstr "/Help/_Debug Window" - -#, fuzzy +msgstr "" + msgid "/Help/De_veloper Information" -msgstr "Server Information" - -#, fuzzy +msgstr "" + msgid "/Help/_Translator Information" -msgstr "Personal Information" +msgstr "" msgid "/Help/_About" -msgstr "/Help/_About" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Account: %s" msgstr "" -"\n" -"Account: %s" - -#, fuzzy, c-format + +#, c-format msgid "" "\n" "Occupants: %d" msgstr "" -"\n" -"Account: %s" - -#, fuzzy, c-format + +#, c-format msgid "" "\n" "Topic: %s" msgstr "" -"\n" -"%s: %s" - -#, fuzzy + msgid "(no topic set)" -msgstr "No topic is set" - -#, fuzzy +msgstr "" + msgid "Buddy Alias" -msgstr "Buddy List" - -#, fuzzy +msgstr "" + msgid "Logged In" -msgstr "Logged out" - -#, fuzzy +msgstr "" + msgid "Last Seen" -msgstr "Last name:" +msgstr "" msgid "Spooky" msgstr "" @@ -12335,114 +10344,96 @@ msgid "Rockin'" msgstr "" -#, fuzzy msgid "Total Buddies" -msgstr "Buddies" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Idle %dd %dh %02dm" -msgstr "Idle (%dh%02dm) " - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Idle %dh %02dm" -msgstr "Idle (%dh%02dm) " - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Idle %dm" -msgstr "Idle (%dm) " - -#, fuzzy +msgstr "" + msgid "/Buddies/New Instant Message..." -msgstr "/Buddies/New Instant _Message..." +msgstr "" msgid "/Buddies/Join a Chat..." -msgstr "/Buddies/Join a Chat..." - -#, fuzzy +msgstr "" + msgid "/Buddies/Get User Info..." -msgstr "/Buddies/Get User _Info..." - -#, fuzzy +msgstr "" + msgid "/Buddies/Add Buddy..." -msgstr "/Buddies/_Add Buddy..." - -#, fuzzy +msgstr "" + msgid "/Buddies/Add Chat..." -msgstr "/Buddies/Add C_hat..." - -#, fuzzy +msgstr "" + msgid "/Buddies/Add Group..." -msgstr "/Buddies/Add _Group..." +msgstr "" msgid "/Tools/Privacy" -msgstr "/Tools/Privacy" +msgstr "" msgid "/Tools/Room List" -msgstr "/Tools/Room List" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "%d unread message from %s\n" msgid_plural "%d unread messages from %s\n" -msgstr[0] "Message from %s" -msgstr[1] "Message from %s" - -#, fuzzy +msgstr[0] "" + msgid "Manually" -msgstr "Manual" +msgstr "" msgid "By status" -msgstr "By status" +msgstr "" msgid "By recent log activity" msgstr "" -#, fuzzy, c-format +#, c-format msgid "%s disconnected" -msgstr "Disconnected." - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "%s disabled" -msgstr "Command disabled" - -#, fuzzy +msgstr "" + msgid "Reconnect" -msgstr "_Reconnect" - -#, fuzzy +msgstr "" + msgid "Re-enable" -msgstr "_Rename" +msgstr "" msgid "SSL FAQs" msgstr "" -#, fuzzy msgid "Welcome back!" -msgstr "%s came back" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "%d account was disabled because you signed on from another location:" msgid_plural "" "%d accounts were disabled because you signed on from another location:" -msgstr[0] "You have signed on from another location." -msgstr[1] "You have signed on from another location." - -#, fuzzy +msgstr[0] "" + msgid "Username:" msgstr "" -"\n" -"Warned:" - -#, fuzzy + msgid "Password:" -msgstr "_Password:" - -#, fuzzy +msgstr "" + msgid "_Login" -msgstr "Login" - -#, fuzzy +msgstr "" + msgid "/Accounts" -msgstr "Accounts" +msgstr "" #. Translators: Please maintain the use of -> and <- to refer to menu heirarchy #, c-format @@ -12457,65 +10448,54 @@ #. set the Show Offline Buddies option. must be done #. * after the treeview or faceprint gets mad. -Robot101 #. -#, fuzzy msgid "/Buddies/Show/Offline Buddies" -msgstr "/Buddies/Show Offline Buddies" - -#, fuzzy +msgstr "" + msgid "/Buddies/Show/Empty Groups" -msgstr "/Buddies/Show Empty Groups" - -#, fuzzy +msgstr "" + msgid "/Buddies/Show/Buddy Details" -msgstr "/Buddies/Show Offline Buddies" - -#, fuzzy +msgstr "" + msgid "/Buddies/Show/Idle Times" -msgstr "/Buddies/Show Offline Buddies" - -#, fuzzy +msgstr "" + msgid "/Buddies/Show/Protocol Icons" -msgstr "/Buddies/Show Empty Groups" - -#, fuzzy +msgstr "" + msgid "Add a buddy.\n" -msgstr "Add a _Buddy" - -#, fuzzy +msgstr "" + msgid "Buddy's _username:" -msgstr "_Buddy name:" - -#, fuzzy +msgstr "" + msgid "(Optional) A_lias:" -msgstr "Optional information:" - -#, fuzzy +msgstr "" + +msgid "(Optional) _Invite message:" +msgstr "" + msgid "Add buddy to _group:" -msgstr "Add buddy to your list?" +msgstr "" msgid "This protocol does not support chat rooms." -msgstr "This protocol does not support chat rooms." +msgstr "" msgid "" "You are not currently signed on with any protocols that have the ability to " "chat." msgstr "" -"You are not currently signed on with any protocols that have the ability to " -"chat." msgid "" "Please enter an alias, and the appropriate information about the chat you " "would like to add to your buddy list.\n" msgstr "" -"Please enter an alias, and the appropriate information about the chat you " -"would like to add to your buddy list.\n" - -#, fuzzy + msgid "A_lias:" -msgstr "Alias:" +msgstr "" msgid "_Group:" -msgstr "_Group:" +msgstr "" msgid "Auto_join when account connects." msgstr "" @@ -12524,11 +10504,10 @@ msgstr "" msgid "Please enter the name of the group to be added." -msgstr "Please enter the name of the group to be added." - -#, fuzzy +msgstr "" + msgid "Enable Account" -msgstr "Account" +msgstr "" msgid "/Accounts/Enable Account" msgstr "" @@ -12536,355 +10515,310 @@ msgid "/Accounts/" msgstr "" -#, fuzzy msgid "_Edit Account" -msgstr "_Account" - -#, fuzzy +msgstr "" + msgid "Set _Mood..." -msgstr "Save File..." +msgstr "" msgid "No actions available" -msgstr "No actions available" - -#, fuzzy +msgstr "" + msgid "_Disable" -msgstr "Visible" - -#, fuzzy +msgstr "" + msgid "/Tools" -msgstr "/_Tools" - -#, fuzzy +msgstr "" + msgid "/Buddies/Sort Buddies" -msgstr "/Buddies/Show Offline Buddies" +msgstr "" msgid "Type the host name for this certificate." msgstr "" #. Widget creation function -#, fuzzy msgid "SSL Servers" -msgstr "Server" - -#, fuzzy +msgstr "" + msgid "Unknown command." -msgstr "Unknown command" - -#, fuzzy +msgstr "" + msgid "That buddy is not on the same protocol as this chat." -msgstr "That buddy is not on the same protocol as this chat" +msgstr "" msgid "" "You are not currently signed on with an account that can invite that buddy." msgstr "" -"You are not currently signed on with an account that can invite that buddy." msgid "Invite Buddy Into Chat Room" -msgstr "Invite Buddy Into Chat Room" +msgstr "" msgid "_Buddy:" -msgstr "_Buddy:" +msgstr "" msgid "_Message:" -msgstr "_Message:" +msgstr "" #, c-format msgid "

Conversation with %s

\n" -msgstr "

Conversation with %s

\n" +msgstr "" msgid "Save Conversation" -msgstr "Save Conversation" +msgstr "" msgid "Un-Ignore" -msgstr "Un-Ignore" +msgstr "" msgid "Ignore" -msgstr "Ignore" - -#, fuzzy +msgstr "" + msgid "Get Away Message" -msgstr "New Away Message" - -#, fuzzy +msgstr "" + msgid "Last Said" -msgstr "Last name:" +msgstr "" msgid "Unable to save icon file to disk." -msgstr "Unable to save icon file to disk." +msgstr "" msgid "Save Icon" -msgstr "Save Icon" +msgstr "" msgid "Animate" -msgstr "Animate" +msgstr "" msgid "Hide Icon" -msgstr "Hide Icon" +msgstr "" msgid "Save Icon As..." -msgstr "Save Icon As..." - -#, fuzzy +msgstr "" + msgid "Set Custom Icon..." -msgstr "Custom" - -#, fuzzy +msgstr "" + msgid "Change Size" -msgstr "Change Address To:" +msgstr "" msgid "Show All" msgstr "" #. Conversation menu msgid "/_Conversation" -msgstr "/_Conversation" +msgstr "" msgid "/Conversation/New Instant _Message..." -msgstr "/Conversation/New Instant _Message..." - -#, fuzzy +msgstr "" + msgid "/Conversation/Join a _Chat..." -msgstr "/Conversation/In_vite..." +msgstr "" msgid "/Conversation/_Find..." -msgstr "/Conversation/_Find..." +msgstr "" msgid "/Conversation/View _Log" -msgstr "/Conversation/View _Log" +msgstr "" msgid "/Conversation/_Save As..." -msgstr "/Conversation/_Save As..." - -#, fuzzy +msgstr "" + msgid "/Conversation/Clea_r Scrollback" -msgstr "/Conversation/Clear" - -#, fuzzy +msgstr "" + msgid "/Conversation/M_edia" -msgstr "/Conversation/_Close" - -#, fuzzy +msgstr "" + msgid "/Conversation/Media/_Audio Call" -msgstr "/Conversation/_Close" - -#, fuzzy +msgstr "" + msgid "/Conversation/Media/_Video Call" -msgstr "/Conversation/_Close" - -#, fuzzy +msgstr "" + msgid "/Conversation/Media/Audio\\/Video _Call" -msgstr "/Conversation/View _Log" +msgstr "" msgid "/Conversation/Se_nd File..." -msgstr "/Conversation/Se_nd File..." - -#, fuzzy +msgstr "" + msgid "/Conversation/Get _Attention" -msgstr "/Conversation/Get Info" +msgstr "" msgid "/Conversation/Add Buddy _Pounce..." -msgstr "/Conversation/Add Buddy _Pounce..." +msgstr "" msgid "/Conversation/_Get Info" -msgstr "/Conversation/_Get Info" +msgstr "" msgid "/Conversation/In_vite..." -msgstr "/Conversation/In_vite..." - -#, fuzzy +msgstr "" + msgid "/Conversation/M_ore" -msgstr "/Conversation/_Close" - -#, fuzzy +msgstr "" + msgid "/Conversation/Al_ias..." -msgstr "/Conversation/Alias..." +msgstr "" msgid "/Conversation/_Block..." -msgstr "/Conversation/_Block..." - -#, fuzzy +msgstr "" + msgid "/Conversation/_Unblock..." -msgstr "/Conversation/_Block..." +msgstr "" msgid "/Conversation/_Add..." -msgstr "/Conversation/_Add..." +msgstr "" msgid "/Conversation/_Remove..." -msgstr "/Conversation/_Remove..." +msgstr "" msgid "/Conversation/Insert Lin_k..." -msgstr "/Conversation/Insert Lin_k..." +msgstr "" msgid "/Conversation/Insert Imag_e..." -msgstr "/Conversation/Insert Imag_e..." +msgstr "" msgid "/Conversation/_Close" -msgstr "/Conversation/_Close" +msgstr "" #. Options msgid "/_Options" -msgstr "/_Options" +msgstr "" msgid "/Options/Enable _Logging" -msgstr "/Options/Enable _Logging" +msgstr "" msgid "/Options/Enable _Sounds" -msgstr "/Options/Enable _Sounds" - -#, fuzzy +msgstr "" + msgid "/Options/Show Formatting _Toolbars" -msgstr "/Options/Show Formatting _Toolbar" - -#, fuzzy +msgstr "" + msgid "/Options/Show Ti_mestamps" -msgstr "/Options/Show Timestamps" - -#, fuzzy +msgstr "" + msgid "/Conversation/More" -msgstr "/Conversation/_Close" - -#, fuzzy +msgstr "" + msgid "/Options" -msgstr "/_Options" +msgstr "" #. The menubar has been deactivated. Make sure the 'More' submenu is regenerated next time #. * the 'Conversation' menu pops up. #. Make sure the 'Conversation -> More' menuitems are regenerated whenever #. * the 'Conversation' menu pops up because the entries can change after the #. * conversation is created. -#, fuzzy msgid "/Conversation" -msgstr "/_Conversation" +msgstr "" msgid "/Conversation/View Log" -msgstr "/Conversation/View Log" - -#, fuzzy +msgstr "" + msgid "/Conversation/Media/Audio Call" -msgstr "/Conversation/_Close" - -#, fuzzy +msgstr "" + msgid "/Conversation/Media/Video Call" -msgstr "/Conversation/View Log" - -#, fuzzy +msgstr "" + msgid "/Conversation/Media/Audio\\/Video Call" -msgstr "/Conversation/_Close" +msgstr "" msgid "/Conversation/Send File..." -msgstr "/Conversation/Send File..." - -#, fuzzy +msgstr "" + msgid "/Conversation/Get Attention" -msgstr "/Conversation/Get Info" +msgstr "" msgid "/Conversation/Add Buddy Pounce..." -msgstr "/Conversation/Add Buddy Pounce..." +msgstr "" msgid "/Conversation/Get Info" -msgstr "/Conversation/Get Info" +msgstr "" msgid "/Conversation/Invite..." -msgstr "/Conversation/Invite..." +msgstr "" msgid "/Conversation/Alias..." -msgstr "/Conversation/Alias..." +msgstr "" msgid "/Conversation/Block..." -msgstr "/Conversation/Block..." - -#, fuzzy +msgstr "" + msgid "/Conversation/Unblock..." -msgstr "/Conversation/Block..." +msgstr "" msgid "/Conversation/Add..." -msgstr "/Conversation/Add..." +msgstr "" msgid "/Conversation/Remove..." -msgstr "/Conversation/Remove..." +msgstr "" msgid "/Conversation/Insert Link..." -msgstr "/Conversation/Insert Link..." +msgstr "" msgid "/Conversation/Insert Image..." -msgstr "/Conversation/Insert Image..." +msgstr "" msgid "/Options/Enable Logging" -msgstr "/Options/Enable Logging" +msgstr "" msgid "/Options/Enable Sounds" -msgstr "/Options/Enable Sounds" - -#, fuzzy +msgstr "" + msgid "/Options/Show Formatting Toolbars" -msgstr "/Options/Show Formatting Toolbar" +msgstr "" msgid "/Options/Show Timestamps" -msgstr "/Options/Show Timestamps" +msgstr "" msgid "User is typing..." -msgstr "User is typing..." - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "" "\n" "%s has stopped typing" -msgstr "%s has stopped typing to you (%s)" +msgstr "" #. Build the Send To menu -#, fuzzy msgid "S_end To" -msgstr "_Send As" - -#, fuzzy +msgstr "" + msgid "_Send" -msgstr "Send" +msgstr "" #. Setup the label telling how many people are in the room. msgid "0 people in room" -msgstr "0 people in room" +msgstr "" msgid "Close Find bar" msgstr "" -#, fuzzy msgid "Find:" -msgstr "Find" +msgstr "" #, c-format msgid "%d person in room" msgid_plural "%d people in room" -msgstr[0] "%d person in room" -msgstr[1] "%d people in room" - -#, fuzzy +msgstr[0] "" + msgid "Stopped Typing" -msgstr "Ping" - -#, fuzzy +msgstr "" + msgid "Nick Said" -msgstr "Nick" - -#, fuzzy +msgstr "" + msgid "Unread Messages" -msgstr "Send Message" - -#, fuzzy +msgstr "" + msgid "New Event" -msgstr "Event" - -#, fuzzy +msgstr "" + msgid "clear: Clears all conversation scrollbacks." -msgstr "%s has closed the conversation window." - -#, fuzzy +msgstr "" + msgid "Confirm close" -msgstr "Confirm Account" - -#, fuzzy +msgstr "" + msgid "You have unread messages. Are you sure you want to close the window?" -msgstr "Are you sure you want to delete %s?" +msgstr "" msgid "Close other tabs" msgstr "" @@ -12899,35 +10833,34 @@ msgstr "" msgid "Close conversation" -msgstr "Close conversation" +msgstr "" msgid "Last created window" -msgstr "Last created window" +msgstr "" msgid "Separate IM and Chat windows" -msgstr "Separate IM and Chat windows" +msgstr "" msgid "New window" -msgstr "New window" +msgstr "" msgid "By group" -msgstr "By group" +msgstr "" msgid "By account" -msgstr "By account" +msgstr "" msgid "Find" -msgstr "Find" +msgstr "" msgid "_Search for:" -msgstr "_Search for:" +msgstr "" msgid "Save Debug Log" -msgstr "Save Debug Log" - -#, fuzzy +msgstr "" + msgid "Invert" -msgstr "_Insert" +msgstr "" msgid "Highlight matches" msgstr "" @@ -12941,13 +10874,11 @@ msgid "_Both Icon & Text" msgstr "" -#, fuzzy msgid "Filter" -msgstr "Failed" - -#, fuzzy +msgstr "" + msgid "Right click for more options." -msgstr "Show more options" +msgstr "" msgid "Level " msgstr "" @@ -12955,31 +10886,23 @@ msgid "Select the debug filter level." msgstr "" -#, fuzzy msgid "All" -msgstr "Allow" +msgstr "" msgid "Misc" msgstr "" -#, fuzzy msgid "Warning" -msgstr "Warn" - -#, fuzzy +msgstr "" + msgid "Error " -msgstr "Error" - -#, fuzzy +msgstr "" + msgid "Fatal Error" -msgstr "Internal Error" - -msgid "bug master" -msgstr "" - -#, fuzzy +msgstr "" + msgid "artist" -msgstr "Address" +msgstr "" #. feel free to not translate this msgid "Ka-Hing Cheung" @@ -12989,39 +10912,35 @@ msgstr "" msgid "support" -msgstr "support" - -#, fuzzy +msgstr "" + msgid "webmaster" -msgstr "developer & webmaster" +msgstr "" msgid "win32 port" -msgstr "win32 port" +msgstr "" msgid "maintainer" -msgstr "maintainer" - -#, fuzzy +msgstr "" + msgid "libfaim maintainer" -msgstr "former libfaim maintainer" +msgstr "" #. If "lazy bum" translates literally into a serious insult, use something else or omit it. msgid "hacker and designated driver [lazy bum]" -msgstr "hacker and designated driver [lazy bum]" - -#, fuzzy +msgstr "" + msgid "support/QA" -msgstr "support" - -#, fuzzy +msgstr "" + msgid "XMPP" -msgstr "XMPP ID" +msgstr "" msgid "original author" -msgstr "original author" +msgstr "" msgid "lead developer" -msgstr "lead developer" +msgstr "" msgid "Senior Contributor/QA" msgstr "" @@ -13029,19 +10948,17 @@ msgid "Afrikaans" msgstr "" -#, fuzzy msgid "Arabic" -msgstr "Amharic" - -#, fuzzy +msgstr "" + msgid "Assamese" -msgstr "Ashamed" +msgstr "" msgid "Belarusian Latin" msgstr "" msgid "Bulgarian" -msgstr "Bulgarian" +msgstr "" msgid "Bengali" msgstr "" @@ -13049,24 +10966,23 @@ msgid "Bengali-India" msgstr "" -#, fuzzy msgid "Bosnian" -msgstr "Romanian" +msgstr "" msgid "Catalan" -msgstr "Catalan" +msgstr "" msgid "Valencian-Catalan" msgstr "" msgid "Czech" -msgstr "Czech" +msgstr "" msgid "Danish" -msgstr "Danish" +msgstr "" msgid "German" -msgstr "German" +msgstr "" msgid "Dzongkha" msgstr "" @@ -13075,44 +10991,40 @@ msgstr "" msgid "Australian English" -msgstr "Australian English" +msgstr "" msgid "British English" -msgstr "British English" +msgstr "" msgid "Canadian English" -msgstr "Canadian English" +msgstr "" msgid "Esperanto" msgstr "" msgid "Spanish" -msgstr "Spanish" - -#, fuzzy +msgstr "" + msgid "Estonian" -msgstr "Romanian" +msgstr "" msgid "Basque" msgstr "" -#, fuzzy msgid "Persian" -msgstr "Serbian" +msgstr "" msgid "Finnish" -msgstr "Finnish" +msgstr "" msgid "French" -msgstr "French" - -#, fuzzy +msgstr "" + msgid "Irish" -msgstr "Turkish" - -#, fuzzy +msgstr "" + msgid "Galician" -msgstr "Italian" +msgstr "" msgid "Gujarati" msgstr "" @@ -13121,148 +11033,133 @@ msgstr "" msgid "Hebrew" -msgstr "Hebrew" +msgstr "" msgid "Hindi" -msgstr "Hindi" +msgstr "" msgid "Hungarian" -msgstr "Hungarian" - -#, fuzzy +msgstr "" + msgid "Armenian" -msgstr "Romanian" - -#, fuzzy +msgstr "" + msgid "Indonesian" -msgstr "Macedonian" +msgstr "" msgid "Italian" -msgstr "Italian" +msgstr "" msgid "Japanese" -msgstr "Japanese" - -#, fuzzy +msgstr "" + msgid "Georgian" -msgstr "German" - -#, fuzzy +msgstr "" + msgid "Ubuntu Georgian Translators" -msgstr "Current Translators" - -#, fuzzy +msgstr "" + msgid "Khmer" -msgstr "Opera" - -#, fuzzy +msgstr "" + msgid "Kannada" -msgstr "Banned" +msgstr "" msgid "Kannada Translation team" msgstr "" msgid "Korean" -msgstr "Korean" - -#, fuzzy +msgstr "" + msgid "Kurdish" -msgstr "Turkish" +msgstr "" msgid "Lao" msgstr "" -#, fuzzy msgid "Maithili" -msgstr "Nihilist" +msgstr "" + +msgid "Meadow Mari" +msgstr "" msgid "Macedonian" -msgstr "Macedonian" - -#, fuzzy +msgstr "" + msgid "Malayalam" -msgstr "Male" - -#, fuzzy +msgstr "" + msgid "Mongolian" -msgstr "Macedonian" - -#, fuzzy +msgstr "" + msgid "Marathi" -msgstr "Address" - -#, fuzzy +msgstr "" + msgid "Malay" -msgstr "Male" - -#, fuzzy +msgstr "" + msgid "Bokmål Norwegian" -msgstr "Norwegian" +msgstr "" msgid "Nepali" msgstr "" -#, fuzzy msgid "Dutch, Flemish" -msgstr "Dutch; Flemish" - -#, fuzzy +msgstr "" + msgid "Norwegian Nynorsk" -msgstr "Norwegian" +msgstr "" msgid "Occitan" msgstr "" -#, fuzzy msgid "Oriya" -msgstr "Opera" +msgstr "" msgid "Punjabi" msgstr "" msgid "Polish" -msgstr "Polish" +msgstr "" msgid "Portuguese" -msgstr "Portuguese" +msgstr "" msgid "Portuguese-Brazil" -msgstr "Portuguese-Brazil" - -#, fuzzy +msgstr "" + msgid "Pashto" -msgstr "Photo" +msgstr "" msgid "Romanian" -msgstr "Romanian" +msgstr "" msgid "Russian" -msgstr "Russian" +msgstr "" msgid "Slovak" -msgstr "Slovak" +msgstr "" msgid "Slovenian" -msgstr "Slovenian" +msgstr "" msgid "Albanian" -msgstr "Albanian" +msgstr "" msgid "Serbian" -msgstr "Serbian" +msgstr "" msgid "Sinhala" msgstr "" msgid "Swedish" -msgstr "Swedish" +msgstr "" msgid "Swahili" msgstr "" -#, fuzzy msgid "Tamil" -msgstr "Terminal" +msgstr "" msgid "Telugu" msgstr "" @@ -13271,35 +11168,34 @@ msgstr "" msgid "Turkish" -msgstr "Turkish" - -#, fuzzy +msgstr "" + msgid "Ukranian" -msgstr "Ukrainian" +msgstr "" msgid "Urdu" msgstr "" msgid "Vietnamese" -msgstr "Vietnamese" +msgstr "" msgid "T.M.Thanh and the Gnome-Vi Team" -msgstr "T.M.Thanh and the Gnome-Vi Team" +msgstr "" msgid "Simplified Chinese" -msgstr "Simplified Chinese" +msgstr "" msgid "Hong Kong Chinese" msgstr "" msgid "Traditional Chinese" -msgstr "Traditional Chinese" +msgstr "" msgid "Amharic" -msgstr "Amharic" +msgstr "" msgid "Lithuanian" -msgstr "Lithuanian" +msgstr "" #, c-format msgid "" @@ -13330,88 +11226,81 @@ "
" msgstr "" -#, fuzzy, c-format +#, c-format msgid "About %s" -msgstr "About Pidgin" - -#, fuzzy +msgstr "" + msgid "Build Information" -msgstr "Buddy Information" +msgstr "" #. End of not to be translated section -#, fuzzy, c-format +#, c-format msgid "%s Build Information" -msgstr "Buddy Information" - -#, fuzzy +msgstr "" + msgid "Current Developers" -msgstr "Retired Developers" +msgstr "" msgid "Crazy Patch Writers" -msgstr "Crazy Patch Writers" +msgstr "" msgid "Retired Developers" -msgstr "Retired Developers" - -#, fuzzy +msgstr "" + msgid "Retired Crazy Patch Writers" -msgstr "Crazy Patch Writers" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "%s Developer Information" -msgstr "Server Information" +msgstr "" msgid "Current Translators" -msgstr "Current Translators" +msgstr "" msgid "Past Translators" -msgstr "Past Translators" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "%s Translator Information" -msgstr "Work Information" - -#, fuzzy +msgstr "" + msgid "_Name" -msgstr "Name" +msgstr "" msgid "_Account" -msgstr "_Account" +msgstr "" msgid "Get User Info" -msgstr "Get User Info" - -#, fuzzy +msgstr "" + msgid "" "Please enter the username or alias of the person whose info you would like " "to view." msgstr "" -"Please enter the screen name of the person whose info you would like to view." - -#, fuzzy + msgid "View User Log" -msgstr "Get User Log" +msgstr "" msgid "Alias Contact" -msgstr "Alias Contact" +msgstr "" msgid "Enter an alias for this contact." -msgstr "Enter an alias for this contact." +msgstr "" #, c-format msgid "Enter an alias for %s." -msgstr "Enter an alias for %s." +msgstr "" msgid "Alias Buddy" -msgstr "Alias Buddy" +msgstr "" msgid "Alias Chat" -msgstr "Alias Chat" +msgstr "" msgid "Enter an alias for this chat." -msgstr "Enter an alias for this chat." - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "" "You are about to remove the contact containing %s and %d other buddy from " "your buddy list. Do you want to continue?" @@ -13419,190 +11308,156 @@ "You are about to remove the contact containing %s and %d other buddies from " "your buddy list. Do you want to continue?" msgstr[0] "" -"You are about to remove the contact containing %s and %d other buddies from " -"your buddy list. Do you want to continue?" -msgstr[1] "" -"You are about to remove the contact containing %s and %d other buddies from " -"your buddy list. Do you want to continue?" msgid "Remove Contact" -msgstr "Remove Contact" - -#, fuzzy +msgstr "" + msgid "_Remove Contact" -msgstr "Remove Contact" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "" "You are about to merge the group called %s into the group called %s. Do you " "want to continue?" msgstr "" -"You are about to remove the group %s and all its members from your buddy " -"list. Do you want to continue?" - -#, fuzzy + msgid "Merge Groups" -msgstr "Remove Group" - -#, fuzzy +msgstr "" + msgid "_Merge Groups" -msgstr "_Delete Group" +msgstr "" #, c-format msgid "" "You are about to remove the group %s and all its members from your buddy " "list. Do you want to continue?" msgstr "" -"You are about to remove the group %s and all its members from your buddy " -"list. Do you want to continue?" msgid "Remove Group" -msgstr "Remove Group" - -#, fuzzy +msgstr "" + msgid "_Remove Group" -msgstr "Remove Group" +msgstr "" #, c-format msgid "" "You are about to remove %s from your buddy list. Do you want to continue?" msgstr "" -"You are about to remove %s from your buddy list. Do you want to continue?" msgid "Remove Buddy" -msgstr "Remove Buddy" +msgstr "" msgid "_Remove Buddy" -msgstr "_Remove Buddy" +msgstr "" #, c-format msgid "" "You are about to remove the chat %s from your buddy list. Do you want to " "continue?" msgstr "" -"You are about to remove the chat %s from your buddy list. Do you want to " -"continue?" msgid "Remove Chat" -msgstr "Remove Chat" - -#, fuzzy +msgstr "" + msgid "_Remove Chat" -msgstr "Remove Chat" - -#, fuzzy +msgstr "" + msgid "Right-click for more unread messages...\n" -msgstr "Show more options" - -#, fuzzy +msgstr "" + msgid "_Change Status" -msgstr "Change Address To:" - -#, fuzzy +msgstr "" + msgid "Show Buddy _List" -msgstr "Buddy List" - -#, fuzzy +msgstr "" + msgid "_Unread Messages" -msgstr "Send Message" - -#, fuzzy +msgstr "" + msgid "New _Message..." -msgstr "New Message..." - -#, fuzzy +msgstr "" + msgid "_Accounts" -msgstr "Accounts" - -#, fuzzy +msgstr "" + msgid "Plu_gins" -msgstr "Plugins" - -#, fuzzy +msgstr "" + msgid "Pr_eferences" -msgstr "Preferences" - -#, fuzzy +msgstr "" + msgid "Mute _Sounds" -msgstr "Mute Sounds" - -#, fuzzy +msgstr "" + msgid "_Blink on New Message" -msgstr "New Message..." - -#, fuzzy +msgstr "" + msgid "_Quit" -msgstr "Quit" - -#, fuzzy +msgstr "" + msgid "Not started" -msgstr "Not supported" +msgstr "" msgid "Receiving As:" -msgstr "Receiving As:" +msgstr "" msgid "Receiving From:" -msgstr "Receiving From:" +msgstr "" msgid "Sending To:" -msgstr "Sending To:" +msgstr "" msgid "Sending As:" -msgstr "Sending As:" +msgstr "" msgid "There is no application configured to open this type of file." -msgstr "There is no application configured to open this type of file." +msgstr "" msgid "An error occurred while opening the file." -msgstr "An error occurred while opening the file." - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Error launching %s: %s" -msgstr "Error launching %s: %s" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Error running %s" -msgstr "Error joining chat %s" +msgstr "" #, c-format msgid "Process returned error code %d" msgstr "" msgid "Filename:" -msgstr "Filename:" - -#, fuzzy +msgstr "" + msgid "Local File:" -msgstr "Local Users" +msgstr "" msgid "Speed:" -msgstr "Speed:" +msgstr "" msgid "Time Elapsed:" -msgstr "Time Elapsed:" +msgstr "" msgid "Time Remaining:" -msgstr "Time Remaining:" +msgstr "" msgid "Close this window when all transfers _finish" msgstr "" -#, fuzzy msgid "C_lear finished transfers" -msgstr "_Clear finished transfers" +msgstr "" #. "Download Details" arrow -#, fuzzy msgid "File transfer _details" -msgstr "Hide transfer details" - -#, fuzzy +msgstr "" + msgid "Paste as Plain _Text" -msgstr "Pa_ste As Text" - -#, fuzzy +msgstr "" + msgid "_Reset formatting" -msgstr "_Clear Formatting" +msgstr "" msgid "Disable _smileys in selected text" msgstr "" @@ -13613,78 +11468,69 @@ msgid "Color to draw hyperlinks." msgstr "Colour to draw hyperlinks." -#, fuzzy msgid "Hyperlink visited color" -msgstr "Hyperlink colour" - -#, fuzzy +msgstr "Hyperlink visited colour" + msgid "Color to draw hyperlink after it has been visited (or activated)." -msgstr "Colour to draw hyperlinks." - -#, fuzzy +msgstr "Colour to draw hyperlink after it has been visited (or activated)." + msgid "Hyperlink prelight color" -msgstr "Hyperlink colour" - -#, fuzzy +msgstr "Hyperlink prelight colour" + msgid "Color to draw hyperlinks when mouse is over them." -msgstr "Colour to draw hyperlinks." - -#, fuzzy +msgstr "Colour to draw hyperlinks when mouse is over them." + msgid "Sent Message Name Color" -msgstr "Send Message" +msgstr "Sent Message Name Colour" msgid "Color to draw the name of a message you sent." -msgstr "" - -#, fuzzy +msgstr "Colour to draw the name of a message you sent." + msgid "Received Message Name Color" -msgstr "Send Message" +msgstr "Received Message Name Colour" msgid "Color to draw the name of a message you received." -msgstr "" +msgstr "Colour to draw the name of a message you received." msgid "\"Attention\" Name Color" -msgstr "" +msgstr "\"Attention\" Name Colour" msgid "Color to draw the name of a message you received containing your name." msgstr "" +"Colour to draw the name of a message you received containing your name." msgid "Action Message Name Color" -msgstr "" +msgstr "Action Message Name Colour" msgid "Color to draw the name of an action message." -msgstr "" +msgstr "Colour to draw the name of an action message." msgid "Action Message Name Color for Whispered Message" -msgstr "" +msgstr "Action Message Name Colour for Whispered Message" msgid "Color to draw the name of a whispered action message." -msgstr "" +msgstr "Colour to draw the name of a whispered action message." msgid "Whisper Message Name Color" -msgstr "" +msgstr "Whisper Message Name Colour" msgid "Color to draw the name of a whispered message." -msgstr "" - -#, fuzzy +msgstr "Colour to draw the name of a whispered message." + msgid "Typing notification color" -msgstr "Notification Removal" - -#, fuzzy +msgstr "Typing notification colour" + msgid "The color to use for the typing notification" -msgstr "New mail notifications" - -#, fuzzy +msgstr "The colour to use for the typing notification" + msgid "Typing notification font" -msgstr "_Popup notification" +msgstr "" msgid "The font to use for the typing notification" msgstr "" -#, fuzzy msgid "Enable typing notification" -msgstr "New mail notifications" +msgstr "" msgid "" "Unrecognized file type\n" @@ -13692,27 +11538,24 @@ "Defaulting to PNG." msgstr "" -#, fuzzy, c-format +#, c-format msgid "" "Error saving image\n" "\n" "%s" msgstr "" -"You have mail!\n" -"\n" -"%s" msgid "Save Image" -msgstr "Save Image" +msgstr "" msgid "_Save Image..." -msgstr "_Save Image..." +msgstr "" msgid "_Add Custom Smiley..." msgstr "" msgid "Select Font" -msgstr "Select Font" +msgstr "" msgid "Select Text Color" msgstr "Select Text Colour" @@ -13721,33 +11564,31 @@ msgstr "Select Background Colour" msgid "_URL" -msgstr "_URL" +msgstr "" msgid "_Description" -msgstr "_Description" +msgstr "" msgid "" "Please enter the URL and description of the link that you want to insert. " "The description is optional." msgstr "" -"Please enter the URL and description of the link that you want to insert. " -"The description is optional." msgid "Please enter the URL of the link that you want to insert." -msgstr "Please enter the URL of the link that you want to insert." +msgstr "" msgid "Insert Link" -msgstr "Insert Link" +msgstr "" msgid "_Insert" -msgstr "_Insert" +msgstr "" #, c-format msgid "Failed to store image: %s\n" -msgstr "Failed to store image: %s\n" +msgstr "" msgid "Insert Image" -msgstr "Insert Image" +msgstr "" #, c-format msgid "" @@ -13756,89 +11597,76 @@ msgstr "" msgid "Smile!" -msgstr "Smile!" +msgstr "" msgid "_Manage custom smileys" msgstr "" msgid "This theme has no available smileys." -msgstr "This theme has no available smileys." - -#, fuzzy +msgstr "" + msgid "_Font" -msgstr "_Account" - -#, fuzzy +msgstr "" + msgid "Group Items" -msgstr "Group Name" +msgstr "" msgid "Ungroup Items" msgstr "" msgid "Bold" -msgstr "Bold" +msgstr "" msgid "Italic" -msgstr "Italic" +msgstr "" msgid "Underline" -msgstr "Underline" +msgstr "" msgid "Strikethrough" msgstr "" -#, fuzzy msgid "Increase Font Size" -msgstr "Ignore font si_zes" +msgstr "" msgid "Decrease Font Size" msgstr "" msgid "Font Face" -msgstr "Font Face" - -#, fuzzy +msgstr "" + msgid "Foreground Color" -msgstr "Foreground font colour" - -#, fuzzy +msgstr "Foreground Colour" + msgid "Reset Formatting" -msgstr "Default Formatting" - -#, fuzzy +msgstr "" + msgid "Insert IM Image" -msgstr "Insert Image" - -#, fuzzy +msgstr "" + msgid "Insert Smiley" -msgstr "Insert smiley" - -#, fuzzy +msgstr "" + msgid "Send Attention" -msgstr "_Send As" - -#, fuzzy +msgstr "" + msgid "_Bold" -msgstr "_Password:" - -#, fuzzy +msgstr "" + msgid "_Italic" -msgstr " (ircop)" - -#, fuzzy +msgstr "" + msgid "_Underline" -msgstr "Underline" +msgstr "" msgid "Strikethrough" msgstr "" -#, fuzzy msgid "_Larger" -msgstr "Pidgin v%s" - -#, fuzzy +msgstr "" + msgid "_Normal" -msgstr "Normal" +msgstr "" msgid "_Smaller" msgstr "" @@ -13846,39 +11674,32 @@ #. If we want to show the formatting for the following items, we would #. * need to update them when formatting changes. The above items don't need #. * no updating nor nothin' -#, fuzzy msgid "_Font face" -msgstr "Font Face" - -#, fuzzy +msgstr "" + msgid "Foreground _color" -msgstr "Foreground font colour" - -#, fuzzy +msgstr "Foreground _colour" + msgid "Bac_kground color" -msgstr "Background colour" - -#, fuzzy +msgstr "Bac_kground colour" + msgid "_Image" -msgstr "Save Image" - -#, fuzzy +msgstr "" + msgid "_Link" -msgstr "_Join" +msgstr "" msgid "_Horizontal rule" msgstr "" -#, fuzzy msgid "_Smile!" -msgstr "Smile!" +msgstr "" msgid "_Attention!" msgstr "" -#, fuzzy msgid "Log Deletion Failed" -msgstr "Connection Failed" +msgstr "" msgid "Check permissions and try again." msgstr "" @@ -13895,41 +11716,33 @@ "%s which started at %s?" msgstr "" -#, fuzzy, c-format +#, c-format msgid "" "Are you sure you want to permanently delete the system log which started at " "%s?" -msgstr "Are you sure you want to remove the away message \"%s\"?" - -#, fuzzy +msgstr "" + msgid "Delete Log?" -msgstr "Delete" - -#, fuzzy +msgstr "" + msgid "Delete Log..." -msgstr "Delete" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Conversation in %s on %s" msgstr "" -"You have mail!\n" -"\n" -"%s" - -#, fuzzy, c-format + +#, c-format msgid "Conversation with %s on %s" msgstr "" -"You have mail!\n" -"\n" -"%s" #. Steal the "HELP" response and use it to trigger browsing to the logs folder msgid "_Browse logs folder" msgstr "" -#, fuzzy, c-format +#, c-format msgid "%s %s. Try `%s -h' for more information.\n" -msgstr "Pidgin %s. Try `%s -h' for more information.\n" +msgstr "" #, c-format msgid "" @@ -14011,64 +11824,57 @@ msgstr "" msgid "_Pause" -msgstr "_Pause" +msgstr "" #, c-format msgid "%s has %d new message." msgid_plural "%s has %d new messages." -msgstr[0] "%s has %d new message." -msgstr[1] "%s has %d new messages." +msgstr[0] "" #, c-format msgid "%d new email." msgid_plural "%d new emails." msgstr[0] "" -msgstr[1] "" - -#, fuzzy, c-format + +#, c-format msgid "The browser command \"%s\" is invalid." -msgstr "The browser command %s is invalid." +msgstr "" msgid "Unable to open URL" -msgstr "Unable to open URL" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Error launching \"%s\": %s" -msgstr "Error launching %s: %s" +msgstr "" msgid "" "The 'Manual' browser command has been chosen, but no command has been set." msgstr "" -"The 'Manual' browser command has been chosen, but no command has been set." - -#, fuzzy + msgid "No message" -msgstr "(1 message)" - -#, fuzzy +msgstr "" + msgid "Open All Messages" -msgstr "Send Message" - -#, fuzzy +msgstr "" + msgid "You have mail!" msgstr "" -"You have mail!\n" -"\n" -"%s" - -#, fuzzy + msgid "New Pounces" -msgstr "New Buddy Pounce" - +msgstr "" + +#. Translators: Make sure you translate "Dismiss" differently than +#. "close"! This string is used in the "You have pounced" dialog +#. that appears when one of your Buddy Pounces is triggered. In +#. this context "Dismiss" means "I acknowledge that I've seen that +#. this pounce was triggered--remove it from this list." Translating +#. it as "Remove" is acceptable if you can't think of a more precise +#. word. msgid "Dismiss" msgstr "" -#, fuzzy msgid "You have pounced!" msgstr "" -"You have mail!\n" -"\n" -"%s" msgid "The following plugins will be unloaded." msgstr "" @@ -14076,13 +11882,11 @@ msgid "Multiple plugins will be unloaded." msgstr "" -#, fuzzy msgid "Unload Plugins" -msgstr "Plugins" - -#, fuzzy +msgstr "" + msgid "Could not unload plugin" -msgstr "Could not load public key" +msgstr "" msgid "" "The plugin could not be unloaded now, but will be disabled at the next " @@ -14095,115 +11899,93 @@ "Check the plugin website for an update." msgstr "" -#, fuzzy msgid "Author" -msgstr "Authorize" - -#, fuzzy +msgstr "" + msgid "Written by:" -msgstr "Sending To:" - -#, fuzzy +msgstr "" + msgid "Web site:" -msgstr "%s: " - -#, fuzzy +msgstr "" + msgid "Filename:" msgstr "" -"\n" -"Warned:" - -#, fuzzy + msgid "Configure Pl_ugin" -msgstr "Configure Room" +msgstr "" msgid "Plugin Details" msgstr "" msgid "Select a file" -msgstr "Select a file" - -#, fuzzy +msgstr "" + msgid "Modify Buddy Pounce" -msgstr "Edit Buddy Pounce" +msgstr "" #. Create the "Pounce on Whom" frame. -#, fuzzy msgid "Pounce on Whom" -msgstr "Pounce Who" +msgstr "" msgid "_Account:" -msgstr "_Account:" +msgstr "" msgid "_Buddy name:" -msgstr "_Buddy name:" - -#, fuzzy +msgstr "" + msgid "Si_gns on" -msgstr "Si_gn on" - -#, fuzzy +msgstr "" + msgid "Signs o_ff" -msgstr "Sign _off" - -#, fuzzy +msgstr "" + msgid "Goes a_way" -msgstr "Buddy Goes _Away" - -#, fuzzy +msgstr "" + msgid "Ret_urns from away" -msgstr "_Return from away" - -#, fuzzy +msgstr "" + msgid "Becomes _idle" -msgstr "%s became idle" - -#, fuzzy +msgstr "" + msgid "Is no longer i_dle" -msgstr "%s is no longer idle." - -#, fuzzy +msgstr "" + msgid "Starts _typing" -msgstr "Buddy starts _typing" +msgstr "" msgid "P_auses while typing" msgstr "" -#, fuzzy msgid "Stops t_yping" -msgstr "Buddy stops t_yping" - -#, fuzzy +msgstr "" + msgid "Sends a _message" -msgstr "Send a _message" - -#, fuzzy +msgstr "" + msgid "Ope_n an IM window" -msgstr "Op_en an IM window" - -#, fuzzy +msgstr "" + msgid "_Pop up a notification" -msgstr "_Popup notification" +msgstr "" msgid "Send a _message" -msgstr "Send a _message" +msgstr "" msgid "E_xecute a command" -msgstr "E_xecute a command" +msgstr "" msgid "P_lay a sound" -msgstr "P_lay a sound" - -#, fuzzy +msgstr "" + msgid "Brows_e..." -msgstr "B_rowse..." - -#, fuzzy +msgstr "" + msgid "Br_owse..." -msgstr "B_rowse..." +msgstr "" msgid "Pre_view" -msgstr "Pre_view" +msgstr "" msgid "P_ounce only when my status is not Available" msgstr "" @@ -14211,53 +11993,41 @@ msgid "_Recurring" msgstr "" -#, fuzzy msgid "Pounce Target" -msgstr "Pounce When" - -#, fuzzy +msgstr "" + msgid "Started typing" -msgstr "Buddy starts _typing" - -#, fuzzy +msgstr "" + msgid "Paused while typing" -msgstr "User is typing..." - -#, fuzzy +msgstr "" + msgid "Signed on" -msgstr "Si_gn on" - -#, fuzzy +msgstr "" + msgid "Returned from being idle" -msgstr "Retur_n from idle" - -#, fuzzy +msgstr "" + msgid "Returned from being away" -msgstr "_Return from away" - -#, fuzzy +msgstr "" + msgid "Stopped typing" -msgstr "Ping" - -#, fuzzy +msgstr "" + msgid "Signed off" -msgstr "Sign _off" - -#, fuzzy +msgstr "" + msgid "Became idle" -msgstr "%s became idle" - -#, fuzzy +msgstr "" + msgid "Went away" -msgstr "When away" - -#, fuzzy +msgstr "" + msgid "Sent a message" -msgstr "Send a _message" - -#, fuzzy +msgstr "" + msgid "Unknown.... Please report this!" -msgstr "Unknown pounce event. Please report this!" +msgstr "" msgid "(Custom)" msgstr "" @@ -14268,9 +12038,8 @@ msgid "The default Pidgin sound theme" msgstr "" -#, fuzzy msgid "The default Pidgin buddy list theme" -msgstr "Buddy List" +msgstr "" msgid "The default Pidgin status icon theme" msgstr "" @@ -14278,102 +12047,86 @@ msgid "Theme failed to unpack." msgstr "" -#, fuzzy msgid "Theme failed to load." -msgstr "Failed to store image: %s\n" +msgstr "" msgid "Theme failed to copy." msgstr "" -#, fuzzy msgid "Theme Selections" -msgstr "Browser Selection" +msgstr "" #. Instructions -#, fuzzy msgid "" "Select a theme that you would like to use from the lists below.\n" "New themes can be installed by dragging and dropping them onto the theme " "list." msgstr "" -"Select a smiley theme that you would like to use from the list below. New " -"themes can be installed by dragging and dropping them onto the theme list." - -#, fuzzy + msgid "Buddy List Theme:" -msgstr "Buddy List" - -#, fuzzy +msgstr "" + msgid "Status Icon Theme:" -msgstr "Status: %s" +msgstr "" msgid "Sound Theme:" msgstr "" -#, fuzzy msgid "Smiley Theme:" -msgstr "Smiley Themes" - -#, fuzzy +msgstr "" + msgid "Keyboard Shortcuts" -msgstr "Shortcuts" - -#, fuzzy +msgstr "" + msgid "Cl_ose conversations with the Escape key" -msgstr "Conversations with %s" +msgstr "" #. System Tray msgid "System Tray Icon" -msgstr "System Tray Icon" - -#, fuzzy +msgstr "" + msgid "_Show system tray icon:" -msgstr "System Tray Icon" - -#, fuzzy +msgstr "" + msgid "On unread messages" -msgstr "Send a _message" - -#, fuzzy +msgstr "" + msgid "Conversation Window" -msgstr "IM Conversation Windows" - -#, fuzzy +msgstr "" + msgid "_Hide new IM conversations:" -msgstr "Close conversation" +msgstr "" msgid "When away" -msgstr "When away" - -#, fuzzy +msgstr "" + msgid "Minimi_ze new conversation windows" -msgstr "IM Conversation Windows" +msgstr "" #. All the tab options! msgid "Tabs" msgstr "" msgid "Show IMs and chats in _tabbed windows" -msgstr "Show IMs and chats in _tabbed windows" +msgstr "" msgid "Show close b_utton on tabs" -msgstr "Show close b_utton on tabs" - -#, fuzzy +msgstr "" + msgid "_Placement:" -msgstr "ExtPlacement" +msgstr "" msgid "Top" -msgstr "Top" +msgstr "" msgid "Bottom" -msgstr "Bottom" +msgstr "" msgid "Left" -msgstr "Left" +msgstr "" msgid "Right" -msgstr "Right" +msgstr "" msgid "Left Vertical" msgstr "" @@ -14381,165 +12134,143 @@ msgid "Right Vertical" msgstr "" -#, fuzzy msgid "N_ew conversations:" -msgstr "Close conversation" - -#, fuzzy +msgstr "" + msgid "Show _formatting on incoming messages" -msgstr "Show _formatting toolbar" +msgstr "" msgid "Close IMs immediately when the tab is closed" msgstr "" -#, fuzzy msgid "Show _detailed information" -msgstr "Profile Information" +msgstr "" msgid "Enable buddy ic_on animation" -msgstr "Enable buddy ic_on animation" +msgstr "" msgid "_Notify buddies that you are typing to them" -msgstr "_Notify buddies that you are typing to them" - -#, fuzzy +msgstr "" + msgid "Highlight _misspelled words" -msgstr "_Highlight misspelled words" +msgstr "" msgid "Use smooth-scrolling" msgstr "" -#, fuzzy msgid "F_lash window when IMs are received" -msgstr "_Flash Window when messages are received" +msgstr "" msgid "Minimum input area height in lines:" msgstr "" -#, fuzzy msgid "Font" -msgstr "Font Face" +msgstr "" msgid "Use font from _theme" msgstr "" -#, fuzzy msgid "Conversation _font:" -msgstr "Conversations" +msgstr "" msgid "Default Formatting" -msgstr "Default Formatting" - -#, fuzzy +msgstr "" + msgid "" "This is how your outgoing message text will appear when you use protocols " "that support formatting." msgstr "" -"This is how your outgoing message text will appear when you use protocols " -"that support formatting. :)" msgid "Cannot start proxy configuration program." msgstr "" -#, fuzzy msgid "Cannot start browser configuration program." -msgstr "Cannot get user information" - -#, fuzzy +msgstr "" + msgid "Disabled" -msgstr "Visible" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Use _automatically detected IP address: %s" -msgstr "_Autodetect IP Address" - -#, fuzzy +msgstr "" + msgid "ST_UN server:" -msgstr "_Server:" +msgstr "" msgid "Example: stunserver.org" msgstr "" msgid "Public _IP:" -msgstr "Public _IP:" +msgstr "" msgid "Ports" -msgstr "Ports" +msgstr "" msgid "_Enable automatic router port forwarding" msgstr "" -#, fuzzy msgid "_Manually specify range of ports to listen on:" -msgstr "_Manually specify range of ports to listen on" - -#, fuzzy +msgstr "" + msgid "_Start:" -msgstr "Status:" - -#, fuzzy +msgstr "" + msgid "_End:" -msgstr "_Expand" +msgstr "" #. TURN server msgid "Relay Server (TURN)" msgstr "" -#, fuzzy msgid "_TURN server:" -msgstr "_Server:" - -#, fuzzy +msgstr "" + msgid "_UDP Port:" -msgstr "_Port:" - -#, fuzzy +msgstr "" + msgid "Use_rname:" -msgstr "_Username:" - -#, fuzzy +msgstr "" + msgid "Pass_word:" -msgstr "Password:" +msgstr "" msgid "Seamonkey" msgstr "" msgid "Opera" -msgstr "Opera" +msgstr "" msgid "Netscape" -msgstr "Netscape" +msgstr "" msgid "Mozilla" -msgstr "Mozilla" +msgstr "" msgid "Konqueror" -msgstr "Konqueror" +msgstr "" msgid "Google Chrome" msgstr "" #. Do not move the line below. Code below expects gnome-open to be in #. * this list immediately after xdg-open! -#, fuzzy msgid "Desktop Default" -msgstr "Accept Defaults" - -#, fuzzy +msgstr "" + msgid "GNOME Default" -msgstr "Gnome Default" +msgstr "" msgid "Galeon" -msgstr "Galeon" +msgstr "" msgid "Firefox" -msgstr "Firefox" +msgstr "" msgid "Firebird" -msgstr "Firebird" +msgstr "" msgid "Epiphany" -msgstr "Epiphany" +msgstr "" #. Translators: please do not translate "chromium-browser" here! msgid "Chromium (chromium-browser)" @@ -14550,10 +12281,10 @@ msgstr "" msgid "Manual" -msgstr "Manual" +msgstr "" msgid "Browser Selection" -msgstr "Browser Selection" +msgstr "" msgid "Browser preferences are configured in GNOME preferences" msgstr "" @@ -14561,35 +12292,32 @@ msgid "Browser configuration program was not found." msgstr "" -#, fuzzy msgid "Configure _Browser" -msgstr "Configure Room" +msgstr "" msgid "_Browser:" -msgstr "_Browser:" +msgstr "" msgid "_Open link in:" -msgstr "_Open link in:" +msgstr "" msgid "Browser default" -msgstr "Browser default" +msgstr "" msgid "Existing window" -msgstr "Existing window" +msgstr "" msgid "New tab" -msgstr "New tab" +msgstr "" #, c-format msgid "" "_Manual:\n" "(%s for URL)" msgstr "" -"_Manual:\n" -"(%s for URL)" msgid "Proxy Server" -msgstr "Proxy Server" +msgstr "" msgid "Proxy preferences are configured in GNOME preferences" msgstr "" @@ -14597,135 +12325,118 @@ msgid "Proxy configuration program was not found." msgstr "" -#, fuzzy msgid "Configure _Proxy" -msgstr "Configure Room" +msgstr "" #. This is a global option that affects SOCKS4 usage even with #. * account-specific proxy settings msgid "Use remote _DNS with SOCKS4 proxies" msgstr "" -#, fuzzy msgid "Proxy t_ype:" -msgstr "Proxy _type:" +msgstr "" msgid "No proxy" -msgstr "No proxy" - -#, fuzzy +msgstr "" + msgid "P_ort:" -msgstr "_Port:" - -#, fuzzy +msgstr "" + msgid "User_name:" -msgstr "_Username:" - -#, fuzzy +msgstr "" + msgid "Log _format:" -msgstr "Log _Format:" - -#, fuzzy +msgstr "" + msgid "Log all _instant messages" -msgstr "_Log all instant messages" +msgstr "" msgid "Log all c_hats" -msgstr "Log all c_hats" +msgstr "" msgid "Log all _status changes to system log" msgstr "" msgid "Sound Selection" -msgstr "Sound Selection" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Quietest" -msgstr "Quit" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Quieter" -msgstr "Quit" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Quiet" -msgstr "Quit" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Loud" -msgstr "Load" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Louder" -msgstr "hour" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Loudest" -msgstr "Sounds" +msgstr "" msgid "_Method:" -msgstr "_Method:" +msgstr "" msgid "Console beep" -msgstr "Console beep" - -#, fuzzy +msgstr "" + msgid "No sounds" -msgstr "Sounds" +msgstr "" #, c-format msgid "" "Sound c_ommand:\n" "(%s for filename)" msgstr "" -"Sound c_ommand:\n" -"(%s for filename)" - -#, fuzzy + msgid "M_ute sounds" -msgstr "Mute Sounds" +msgstr "" msgid "Sounds when conversation has _focus" -msgstr "Sounds when conversation has _focus" - -#, fuzzy +msgstr "" + msgid "_Enable sounds:" -msgstr "Failed" +msgstr "" msgid "V_olume:" msgstr "" msgid "Play" -msgstr "Play" - -#, fuzzy +msgstr "" + msgid "_Browse..." -msgstr "B_rowse..." - -#, fuzzy +msgstr "" + msgid "_Reset" -msgstr "Reset" - -#, fuzzy +msgstr "" + msgid "_Report idle time:" -msgstr "Show idle _times" +msgstr "" msgid "Based on keyboard or mouse use" msgstr "" -#, fuzzy msgid "_Minutes before becoming idle:" -msgstr "_Minutes before setting away:" - -#, fuzzy +msgstr "" + msgid "Change to this status when _idle:" -msgstr "Set away _when idle" +msgstr "" msgid "_Auto-reply:" -msgstr "_Auto-reply:" - -#, fuzzy +msgstr "" + msgid "When both away and idle" -msgstr "When away and idle" +msgstr "" #. Signon status stuff msgid "Status at Startup" @@ -14738,94 +12449,90 @@ msgstr "" msgid "Interface" -msgstr "Interface" +msgstr "" msgid "Browser" -msgstr "Browser" - -#, fuzzy +msgstr "" + msgid "Status / Idle" -msgstr "Away / Idle" - -#, fuzzy +msgstr "" + msgid "Themes" -msgstr "Smiley Themes" +msgstr "" msgid "Allow all users to contact me" -msgstr "Allow all users to contact me" +msgstr "" msgid "Allow only the users on my buddy list" -msgstr "Allow only the users on my buddy list" +msgstr "" msgid "Allow only the users below" -msgstr "Allow only the users below" +msgstr "" msgid "Block all users" -msgstr "Block all users" +msgstr "" msgid "Block only the users below" -msgstr "Block only the users below" +msgstr "" msgid "Privacy" -msgstr "Privacy" +msgstr "" msgid "Changes to privacy settings take effect immediately." -msgstr "Changes to privacy settings take effect immediately." +msgstr "" msgid "Set privacy for:" -msgstr "Set privacy for:" +msgstr "" #. Remove All button -#, fuzzy msgid "Remove Al_l" -msgstr "Remove" +msgstr "" msgid "Permit User" -msgstr "Permit User" +msgstr "" msgid "Type a user you permit to contact you." -msgstr "Type a user you permit to contact you." +msgstr "" msgid "Please enter the name of the user you wish to be able to contact you." -msgstr "Please enter the name of the user you wish to be able to contact you." - -#, fuzzy +msgstr "" + msgid "_Permit" -msgstr "Permit" +msgstr "" #, c-format msgid "Allow %s to contact you?" -msgstr "Allow %s to contact you?" +msgstr "" #, c-format msgid "Are you sure you wish to allow %s to contact you?" -msgstr "Are you sure you wish to allow %s to contact you?" +msgstr "" msgid "Block User" -msgstr "Block User" +msgstr "" msgid "Type a user to block." -msgstr "Type a user to block." +msgstr "" msgid "Please enter the name of the user you wish to block." -msgstr "Please enter the name of the user you wish to block." +msgstr "" #, c-format msgid "Block %s?" -msgstr "Block %s?" +msgstr "" #, c-format msgid "Are you sure you want to block %s?" -msgstr "Are you sure you want to block %s?" +msgstr "" msgid "Apply" -msgstr "Apply" +msgstr "" msgid "That file already exists" -msgstr "That file already exists" +msgstr "" msgid "Would you like to overwrite it?" -msgstr "Would you like to overwrite it?" +msgstr "" msgid "Overwrite" msgstr "" @@ -14833,42 +12540,35 @@ msgid "Choose New Name" msgstr "" -#, fuzzy msgid "Select Folder..." -msgstr "Select Text Colour" +msgstr "" #. list button msgid "_Get List" -msgstr "_Get List" +msgstr "" #. add button -#, fuzzy msgid "_Add Chat" -msgstr "Add Chat" - -#, fuzzy +msgstr "" + msgid "Are you sure you want to delete the selected saved statuses?" -msgstr "Are you sure you want to delete %s?" +msgstr "" #. Use button -#, fuzzy msgid "_Use" -msgstr "_Use" +msgstr "" msgid "Title already in use. You must choose a unique title." msgstr "" -#, fuzzy msgid "Different" -msgstr "Department" - -#, fuzzy +msgstr "" + msgid "_Title:" -msgstr "Title" - -#, fuzzy +msgstr "" + msgid "_Status:" -msgstr "Status:" +msgstr "" #. Different status message expander msgid "Use a _different status for some accounts" @@ -14876,56 +12576,47 @@ #. Save & Use button msgid "Sa_ve & Use" -msgstr "Sa_ve & Use" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Status for %s" -msgstr "Status: %s" +msgstr "" #, c-format msgid "" "A custom smiley for '%s' already exists. Please use a different shortcut." msgstr "" -#, fuzzy msgid "Custom Smiley" -msgstr "Insert smiley" - -#, fuzzy +msgstr "" + msgid "Duplicate Shortcut" -msgstr "Public key file" - -#, fuzzy +msgstr "" + msgid "Edit Smiley" -msgstr "Insert smiley" - -#, fuzzy +msgstr "" + msgid "Add Smiley" -msgstr "Smile!" - -#, fuzzy +msgstr "" + msgid "_Image:" -msgstr "Save Image" +msgstr "" #. Shortcut text -#, fuzzy msgid "S_hortcut text:" -msgstr "Shortcuts" - -#, fuzzy +msgstr "" + msgid "Smiley" -msgstr "Smile!" - -#, fuzzy +msgstr "" + msgid "Shortcut Text" -msgstr "Shortcuts" +msgstr "" msgid "Custom Smiley Manager" msgstr "" -#, fuzzy msgid "Select Buddy Icon" -msgstr "Select Buddy" +msgstr "" msgid "Click to change your buddyicon for this account." msgstr "" @@ -14933,21 +12624,17 @@ msgid "Click to change your buddyicon for all accounts." msgstr "" -#, fuzzy msgid "Waiting for network connection" -msgstr "Waiting for transfer to begin" - -#, fuzzy +msgstr "" + msgid "New status..." -msgstr "New Message..." - -#, fuzzy +msgstr "" + msgid "Saved statuses..." -msgstr "Server Statistics" - -#, fuzzy +msgstr "" + msgid "Status Selector" -msgstr "Status Text" +msgstr "" msgid "Google Talk" msgstr "" @@ -14955,17 +12642,16 @@ msgid "Facebook (XMPP)" msgstr "" -#, fuzzy, c-format +#, c-format msgid "The following error has occurred loading %s: %s" -msgstr "An unknown signon error has occurred: %s." - -#, fuzzy +msgstr "" + msgid "Failed to load image" -msgstr "Failed to store image: %s\n" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Cannot send folder %s." -msgstr "Cannot send file" +msgstr "" #, c-format msgid "" @@ -14973,36 +12659,30 @@ "individually." msgstr "" -#, fuzzy msgid "You have dragged an image" -msgstr "You have entered an invalid username" +msgstr "" msgid "" "You can send this image as a file transfer, embed it into this message, or " "use it as the buddy icon for this user." msgstr "" -#, fuzzy msgid "Set as buddy icon" -msgstr "Show buddy _icons" - -#, fuzzy +msgstr "" + msgid "Send image file" -msgstr "Send message" - -#, fuzzy +msgstr "" + msgid "Insert in message" -msgstr "Insert image" - -#, fuzzy +msgstr "" + msgid "Would you like to set it as the buddy icon for this user?" -msgstr "Would you like to join the conversation?" - -#, fuzzy +msgstr "" + msgid "" "You can send this image as a file transfer, or use it as the buddy icon for " "this user." -msgstr "Would you like to join the conversation?" +msgstr "" msgid "" "You can insert this image into this message, or use it as the buddy icon for " @@ -15017,9 +12697,8 @@ #. * nothing else? Probably not. I'll just give an error and #. * return. #. The original patch sent the icon used by the launcher. That's probably wrong -#, fuzzy msgid "Cannot send launcher" -msgstr "Cannot send file" +msgstr "" msgid "" "You dragged a desktop launcher. Most likely you wanted to send the target of " @@ -15032,98 +12711,78 @@ "File size: %s\n" "Image size: %dx%d" msgstr "" -"File: %s\n" -"File size: %s\n" -"Image size: %dx%d" #, c-format msgid "The file '%s' is too large for %s. Please try a smaller image.\n" msgstr "" -#, fuzzy msgid "Icon Error" -msgstr "Unknown Error" - -#, fuzzy +msgstr "" + msgid "Could not set icon" -msgstr "Could not send" - -#, fuzzy +msgstr "" + msgid "_Open Link" -msgstr "_Open link in:" +msgstr "" msgid "_Copy Link Location" -msgstr "_Copy Link Location" +msgstr "" msgid "_Copy Email Address" -msgstr "_Copy Email Address" - -#, fuzzy +msgstr "" + msgid "_Open File" -msgstr "Open File..." - -#, fuzzy +msgstr "" + msgid "Open _Containing Directory" -msgstr "_Search for:" - -#, fuzzy +msgstr "" + msgid "Save File" -msgstr "Save File..." - -#, fuzzy +msgstr "" + msgid "_Play Sound" -msgstr "P_lay a sound" - -#, fuzzy +msgstr "" + msgid "_Save File" -msgstr "Save File..." - -#, fuzzy +msgstr "" + msgid "Do you really want to clear?" -msgstr "Are you sure you want to delete %s?" - -#, fuzzy +msgstr "" + msgid "Select color" -msgstr "Select Text Colour" +msgstr "Select colour" #. Translators may want to transliterate the name. #. It is not to be translated. -#, fuzzy msgid "Pidgin" -msgstr "Paging" +msgstr "" msgid "_Alias" -msgstr "_Alias" - -#, fuzzy +msgstr "" + msgid "Close _tabs" -msgstr "Close" - -#, fuzzy +msgstr "" + msgid "_Get Info" -msgstr "Get Info" +msgstr "" msgid "_Invite" -msgstr "_Invite" - -#, fuzzy +msgstr "" + msgid "_Modify..." -msgstr "_Modify" - -#, fuzzy +msgstr "" + msgid "_Add..." -msgstr "Add" +msgstr "" msgid "_Open Mail" -msgstr "_Open Mail" - -#, fuzzy +msgstr "" + msgid "_Edit" -msgstr "_Edit" - -#, fuzzy +msgstr "" + msgid "Pidgin Tooltip" -msgstr "Paging" +msgstr "" msgid "Pidgin smileys" msgstr "" @@ -15131,32 +12790,27 @@ msgid "Selecting this disables graphical emoticons." msgstr "" -#, fuzzy msgid "none" -msgstr "Anyone" - -#, fuzzy +msgstr "" + msgid "Small" -msgstr "Email" +msgstr "" msgid "Smaller versions of the default smileys" msgstr "" -#, fuzzy msgid "Response Probability:" -msgstr "Responses lost" - -#, fuzzy +msgstr "" + msgid "Statistics Configuration" -msgstr "Tray Icon Configuration" +msgstr "" #. msg_difference spinner msgid "Maximum response timeout:" msgstr "" -#, fuzzy msgid "minutes" -msgstr "minutes." +msgstr "" #. last_seen spinner msgid "Maximum last-seen difference:" @@ -15184,29 +12838,24 @@ msgid "Displays statistical information about your buddies' availability" msgstr "" -#, fuzzy msgid "Buddy is idle" -msgstr "Buddy is idle:" - -#, fuzzy +msgstr "" + msgid "Buddy is away" -msgstr "Buddy is away:" - -#, fuzzy +msgstr "" + msgid "Buddy is \"extended\" away" -msgstr "Buddy is away:" +msgstr "" #. Not used yet. -#, fuzzy msgid "Buddy is mobile" -msgstr "Buddy is idle:" - -#, fuzzy +msgstr "" + msgid "Buddy is offline" -msgstr "Buddy is offline:" +msgstr "" msgid "Point values to use when..." -msgstr "Point values to use when..." +msgstr "" msgid "" "The buddy with the largest score is the buddy who will have priority " @@ -15216,9 +12865,8 @@ msgid "Use last buddy when scores are equal" msgstr "" -#, fuzzy msgid "Point values to use for account..." -msgstr "Point values to use for Account..." +msgstr "" #. *< type #. *< ui_requirement @@ -15227,7 +12875,7 @@ #. *< priority #. *< id msgid "Contact Priority" -msgstr "Contact Priority" +msgstr "" #. *< name #. *< version @@ -15235,124 +12883,99 @@ msgid "" "Allows for controlling the values associated with different buddy states." msgstr "" -"Allows for controlling the values associated with different buddy states." #. *< description msgid "" "Allows for changing the point values of idle/away/offline states for buddies " "in contact priority computations." msgstr "" -"Allows for changing the point values of idle/away/offline states for buddies " -"in contact priority computations." - -#, fuzzy + msgid "Conversation Colors" -msgstr "/Conversation/_Close" - -#, fuzzy +msgstr "Conversation Colours" + msgid "Customize colors in the conversation window" -msgstr "IM Conversation Windows" - -#, fuzzy +msgstr "Customize colours in the conversation window" + msgid "Error Messages" -msgstr "Error Message Suppression" - -#, fuzzy +msgstr "" + msgid "Highlighted Messages" -msgstr "Send Message" - -#, fuzzy +msgstr "" + msgid "System Messages" -msgstr "Send Message" - -#, fuzzy +msgstr "" + msgid "Sent Messages" -msgstr "Send Message" - -#, fuzzy +msgstr "" + msgid "Received Messages" -msgstr "Send Message" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Select Color for %s" -msgstr "Select Text Colour" - -#, fuzzy +msgstr "Select Colour for %s" + msgid "Ignore incoming format" -msgstr "Ignore c_olours" - -#, fuzzy +msgstr "" + msgid "Apply in Chats" -msgstr "Alias Chat" +msgstr "" msgid "Apply in IMs" msgstr "" #. Note to translators: The string "Enter an XMPP Server" is asking the #. user to type the name of an XMPP server which will then be queried -#, fuzzy msgid "Server name request" -msgstr "Server address" - -#, fuzzy +msgstr "" + msgid "Enter an XMPP Server" -msgstr "Enter a Conference Server" - -#, fuzzy +msgstr "" + msgid "Select an XMPP server to query" -msgstr "Select a conference server to query" - -#, fuzzy +msgstr "" + msgid "Find Services" -msgstr "Online Services" - -#, fuzzy +msgstr "" + msgid "Add to Buddy List" -msgstr "Send Buddy List" - -#, fuzzy +msgstr "" + msgid "Gateway" -msgstr "When away" - -#, fuzzy +msgstr "" + msgid "Directory" -msgstr "_Search for:" - -#, fuzzy +msgstr "" + msgid "PubSub Collection" -msgstr "Sound Selection" +msgstr "" msgid "PubSub Leaf" msgstr "" -#, fuzzy +msgid "Other" +msgstr "" + msgid "" "\n" "Description: " msgstr "" -"\n" -"Description: Spooky" #. Create the window. -#, fuzzy msgid "Service Discovery" -msgstr "Set Dir Info" - -#, fuzzy +msgstr "" + msgid "_Browse" -msgstr "_Browser:" - -#, fuzzy +msgstr "" + msgid "Server does not exist" -msgstr "User does not exist" - -#, fuzzy +msgstr "" + msgid "Server does not support service discovery" -msgstr "Server does not use any supported authentication method" - -#, fuzzy +msgstr "" + msgid "XMPP Service Discovery" -msgstr "Set Dir Info" +msgstr "" msgid "Allows browsing and registering services." msgstr "" @@ -15363,10 +12986,10 @@ msgstr "" msgid "By conversation count" -msgstr "By conversation count" +msgstr "" msgid "Conversation Placement" -msgstr "Conversation Placement" +msgstr "" #. Translators: "New conversations" should match the text in the preferences dialog and "By conversation count" should be the same text used above msgid "" @@ -15375,10 +12998,10 @@ msgstr "" msgid "Number of conversations per window" -msgstr "Number of conversations per window" +msgstr "" msgid "Separate IM and Chat windows when placing by number" -msgstr "Separate IM and Chat windows when placing by number" +msgstr "" #. *< type #. *< ui_requirement @@ -15387,12 +13010,12 @@ #. *< priority #. *< id msgid "ExtPlacement" -msgstr "ExtPlacement" +msgstr "" #. *< name #. *< version msgid "Extra conversation placement options." -msgstr "Extra conversation placement options." +msgstr "" #. *< summary #. * description @@ -15400,22 +13023,20 @@ "Restrict the number of conversations per windows, optionally separating IMs " "and Chats" msgstr "" -"Restrict the number of conversations per windows, optionally separating IMs " -"and Chats" #. Configuration frame msgid "Mouse Gestures Configuration" -msgstr "Mouse Gestures Configuration" +msgstr "" msgid "Middle mouse button" -msgstr "Middle mouse button" +msgstr "" msgid "Right mouse button" -msgstr "Right mouse button" +msgstr "" #. "Visual gesture display" checkbox msgid "_Visual gesture display" -msgstr "_Visual gesture display" +msgstr "" #. *< type #. *< ui_requirement @@ -15424,16 +13045,15 @@ #. *< priority #. *< id msgid "Mouse Gestures" -msgstr "Mouse Gestures" +msgstr "" #. *< name #. *< version #. * summary msgid "Provides support for mouse gestures" -msgstr "Provides support for mouse gestures" +msgstr "" #. * description -#, fuzzy msgid "" "Allows support for mouse gestures in conversation windows. Drag the middle " "mouse button to perform certain actions:\n" @@ -15441,51 +13061,41 @@ " • Drag up and then to the left to switch to the previous conversation.\n" " • Drag up and then to the right to switch to the next conversation." msgstr "" -"Allows support for mouse gestures in conversation windows.\n" -"Drag the middle mouse button to perform certain actions:\n" -"\n" -"Drag down and then to the right to close a conversation.\n" -"Drag up and then to the left to switch to the previous conversation.\n" -"Drag up and then to the right to switch to the next conversation." msgid "Instant Messaging" -msgstr "Instant Messaging" +msgstr "" #. Add the label. msgid "Select a person from your address book below, or add a new person." -msgstr "Select a person from your address book below, or add a new person." +msgstr "" msgid "Group:" -msgstr "Group:" +msgstr "" #. "New Person" button msgid "New Person" -msgstr "New Person" +msgstr "" #. "Select Buddy" button msgid "Select Buddy" -msgstr "Select Buddy" +msgstr "" #. Add the label. msgid "" "Select a person from your address book to add this buddy to, or create a new " "person." msgstr "" -"Select a person from your address book to add this buddy to, or create a new " -"person." #. Add the expander -#, fuzzy msgid "User _details" -msgstr "Hide user details" +msgstr "" #. "Associate Buddy" button msgid "_Associate Buddy" -msgstr "_Associate Buddy" - -#, fuzzy +msgstr "" + msgid "Unable to send email" -msgstr "Unable to send message." +msgstr "" msgid "The evolution executable was not found in the PATH." msgstr "" @@ -15494,19 +13104,18 @@ msgstr "" msgid "Add to Address Book" -msgstr "Add to Address Book" - -#, fuzzy +msgstr "" + msgid "Send Email" -msgstr "Email" +msgstr "" #. Configuration frame msgid "Evolution Integration Configuration" -msgstr "Evolution Integration Configuration" +msgstr "" #. Label msgid "Select all accounts that buddies should be auto-added to." -msgstr "Select all accounts that buddies should be auto-added to." +msgstr "" #. *< type #. *< ui_requirement @@ -15515,38 +13124,36 @@ #. *< priority #. *< id msgid "Evolution Integration" -msgstr "Evolution Integration" +msgstr "" #. *< name #. *< version #. * summary #. * description -#, fuzzy msgid "Provides integration with Evolution." -msgstr "Provides integration with Ximian Evolution." +msgstr "" msgid "Please enter the person's information below." -msgstr "Please enter the person's information below." - -#, fuzzy +msgstr "" + msgid "Please enter the buddy's username and account type below." -msgstr "Please enter the buddy's screen name and account type below." +msgstr "" msgid "Account type:" -msgstr "Account type:" +msgstr "" #. Optional Information section msgid "Optional information:" -msgstr "Optional information:" +msgstr "" msgid "First name:" -msgstr "First name:" +msgstr "" msgid "Last name:" -msgstr "Last name:" +msgstr "" msgid "Email:" -msgstr "Email:" +msgstr "" #. *< type #. *< ui_requirement @@ -15555,25 +13162,23 @@ #. *< priority #. *< id msgid "GTK Signals Test" -msgstr "GTK Signals Test" +msgstr "" #. *< name #. *< version #. * summary #. * description msgid "Test to see that all ui signals are working properly." -msgstr "Test to see that all UI signals are working properly." - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "" "\n" "Buddy Note: %s" msgstr "" -"\n" -"Idle:" msgid "History" -msgstr "History" +msgstr "" #. *< type #. *< ui_requirement @@ -15582,43 +13187,41 @@ #. *< priority #. *< id msgid "Iconify on Away" -msgstr "Iconify on Away" +msgstr "" #. *< name #. *< version #. * summary #. * description msgid "Iconifies the buddy list and your conversations when you go away." -msgstr "Iconifies the buddy list and your conversations when you go away." +msgstr "" msgid "Mail Checker" -msgstr "Mail Checker" +msgstr "" msgid "Checks for new local mail." -msgstr "Checks for new local mail." +msgstr "" msgid "Adds a small box to the buddy list that shows if you have new mail." -msgstr "Adds a small box to the buddy list that shows if you have new mail." - -#, fuzzy +msgstr "" + msgid "Markerline" -msgstr "Underline" +msgstr "" msgid "Draw a line to indicate new messages in a conversation." msgstr "" -#, fuzzy msgid "Jump to markerline" -msgstr "Underline" +msgstr "" msgid "Draw Markerline in " msgstr "" msgid "_IM windows" -msgstr "_IM windows" +msgstr "" msgid "C_hat windows" -msgstr "C_hat windows" +msgstr "" msgid "" "A music messaging session has been requested. Please click the MM icon to " @@ -15628,31 +13231,27 @@ msgid "Music messaging session confirmed." msgstr "" -#, fuzzy msgid "Music Messaging" -msgstr "Instant Messaging" +msgstr "" msgid "There was a conflict in running the command:" msgstr "" -#, fuzzy msgid "Error Running Editor" -msgstr "Error joining chat %s" - -#, fuzzy +msgstr "" + msgid "The following error has occurred:" -msgstr "An unknown signon error has occurred: %s." +msgstr "" #. Configuration frame -#, fuzzy msgid "Music Messaging Configuration" -msgstr "Mouse Gestures Configuration" +msgstr "" msgid "Score Editor Path" msgstr "" msgid "_Apply" -msgstr "_Apply" +msgstr "" #. *< type #. *< ui_requirement @@ -15673,72 +13272,67 @@ #. ---------- "Notify For" ---------- msgid "Notify For" -msgstr "Notify For" - -#, fuzzy +msgstr "" + msgid "\t_Only when someone says your username" -msgstr "Someone says your name in chat" +msgstr "" msgid "_Focused windows" -msgstr "_Focused windows" +msgstr "" #. ---------- "Notification Methods" ---------- msgid "Notification Methods" -msgstr "Notification Methods" +msgstr "" msgid "Prepend _string into window title:" -msgstr "Prepend _string into window title:" +msgstr "" #. Count method button msgid "Insert c_ount of new messages into window title" -msgstr "Insert c_ount of new messages into window title" +msgstr "" #. Count xprop method button -#, fuzzy msgid "Insert count of new message into _X property" -msgstr "Insert c_ount of new messages into window title" +msgstr "" #. Urgent method button msgid "Set window manager \"_URGENT\" hint" -msgstr "Set window manager \"_URGENT\" hint" - -#, fuzzy +msgstr "" + msgid "_Flash window" -msgstr "C_hat windows" +msgstr "" #. Raise window method button -#, fuzzy msgid "R_aise conversation window" -msgstr "IM Conversation Windows" +msgstr "" #. Present conversation method button -#, fuzzy msgid "_Present conversation window" -msgstr "IM Conversation Windows" +msgstr "" #. ---------- "Notification Removals" ---------- msgid "Notification Removal" -msgstr "Notification Removal" +msgstr "" #. Remove on focus button msgid "Remove when conversation window _gains focus" -msgstr "Remove when conversation window _gains focus" +msgstr "" #. Remove on click button msgid "Remove when conversation window _receives click" -msgstr "Remove when conversation window _receives click" +msgstr "" #. Remove on type button msgid "Remove when _typing in conversation window" -msgstr "Remove when _typing in conversation window" +msgstr "" #. Remove on message send button msgid "Remove when a _message gets sent" -msgstr "Remove when a _message gets sent" +msgstr "" #. Remove on conversation switch button msgid "Remove on switch to conversation ta_b" -msgstr "Remove on switch to conversation ta_b" +msgstr "" #. *< type #. *< ui_requirement @@ -15747,14 +13341,14 @@ #. *< priority #. *< id msgid "Message Notification" -msgstr "Message Notification" +msgstr "" #. *< name #. *< version #. * summary #. * description msgid "Provides a variety of ways of notifying you of unread messages." -msgstr "Provides a variety of ways of notifying you of unread messages." +msgstr "" #. *< type #. *< ui_requirement @@ -15762,15 +13356,14 @@ #. *< dependencies #. *< priority #. *< id -#, fuzzy msgid "Pidgin Demonstration Plugin" -msgstr "Pidgin Demonstration Plugin" +msgstr "" #. *< name #. *< version #. * summary msgid "An example plugin that does stuff - see the description." -msgstr "An example plugin that does stuff - see the description." +msgstr "" #. * description msgid "" @@ -15779,87 +13372,68 @@ "- It reverses all incoming text\n" "- It sends a message to people on your list immediately when they sign on" msgstr "" -"This is a really cool plugin that does a lot of stuff:\n" -"- It tells you who wrote the program when you log in\n" -"- It reverses all incoming text\n" -"- It sends a message to people on your list immediately when they sign on" - -#, fuzzy + msgid "Hyperlink Color" -msgstr "Hyperlink colour" - -#, fuzzy +msgstr "Hyperlink Colour" + msgid "Visited Hyperlink Color" -msgstr "Hyperlink colour" - -#, fuzzy +msgstr "Visited Hyperlink Colour" + msgid "Highlighted Message Name Color" -msgstr "Send Message" - -#, fuzzy +msgstr "Highlighted Message Name Colour" + msgid "Typing Notification Color" -msgstr "Notification Removal" +msgstr "Typing Notification Colour" msgid "GtkTreeView Horizontal Separation" msgstr "" -#, fuzzy msgid "Conversation Entry" -msgstr "Conversations" - -#, fuzzy +msgstr "" + msgid "Conversation History" -msgstr "Conversations" - -#, fuzzy +msgstr "" + msgid "Request Dialog" -msgstr "Request ambiguous" - -#, fuzzy +msgstr "" + msgid "Notify Dialog" -msgstr "Notify For" - -#, fuzzy +msgstr "" + msgid "Select Color" -msgstr "Select Text Colour" - -#, fuzzy, c-format +msgstr "Select Colour" + +#, c-format msgid "Select Interface Font" -msgstr "Select Font" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "Select Font for %s" -msgstr "Select Font" - -#, fuzzy +msgstr "" + msgid "GTK+ Interface Font" -msgstr "Interface Options" +msgstr "" msgid "GTK+ Text Shortcut Theme" msgstr "" -#, fuzzy msgid "Disable Typing Notification Text" -msgstr "New mail notifications" - -#, fuzzy +msgstr "" + msgid "GTK+ Theme Control Settings" -msgstr "Pidgin File Control" - -#, fuzzy +msgstr "" + msgid "Colors" -msgstr "Close" - -#, fuzzy +msgstr "Colours" + msgid "Fonts" -msgstr "Accounts" +msgstr "" msgid "Miscellaneous" msgstr "" -#, fuzzy msgid "Gtkrc File Tools" -msgstr "Pidgin File Control" +msgstr "" #, c-format msgid "Write settings to %s%sgtkrc-2.0" @@ -15868,40 +13442,35 @@ msgid "Re-read gtkrc files" msgstr "" -#, fuzzy msgid "Pidgin GTK+ Theme Control" -msgstr "Pidgin File Control" +msgstr "" msgid "Provides access to commonly used gtkrc settings." msgstr "" msgid "Raw" -msgstr "Raw" +msgstr "" msgid "Lets you send raw input to text-based protocols." -msgstr "Lets you send raw input to text-based protocols." +msgstr "" msgid "" "Lets you send raw input to text-based protocols (XMPP, MSN, IRC, TOC). Hit " "'Enter' in the entry box to send. Watch the debug window." msgstr "" -"Lets you send raw input to text-based protocols (XMPP, MSN, IRC, TOC). Hit " -"'Enter' in the entry box to send. Watch the debug window." #, c-format msgid "You can upgrade to %s %s today." msgstr "" msgid "New Version Available" -msgstr "New Version Available" - -#, fuzzy +msgstr "" + msgid "Later" -msgstr "Date" - -#, fuzzy +msgstr "" + msgid "Download Now" -msgstr "Users on %s: %s" +msgstr "" #. *< type #. *< ui_requirement @@ -15910,21 +13479,19 @@ #. *< priority #. *< id msgid "Release Notification" -msgstr "Release Notification" +msgstr "" #. *< name #. *< version #. * summary msgid "Checks periodically for new releases." -msgstr "Checks periodically for new releases." +msgstr "" #. * description msgid "" "Checks periodically for new releases and notifies the user with the " "ChangeLog." msgstr "" -"Checks periodically for new releases and notifies the user with the " -"ChangeLog." #. *< major version #. *< minor version @@ -15934,15 +13501,13 @@ #. *< dependencies #. *< priority #. *< id -#, fuzzy msgid "Send Button" -msgstr "_Send As" +msgstr "" #. *< name #. *< version -#, fuzzy msgid "Conversation Window Send Button." -msgstr "IM Conversation Windows" +msgstr "" #. *< summary msgid "" @@ -15957,13 +13522,13 @@ msgstr "" msgid "Text Replacements" -msgstr "Text Replacements" +msgstr "" msgid "You type" -msgstr "You type" +msgstr "" msgid "You send" -msgstr "You send" +msgstr "" msgid "Whole words only" msgstr "" @@ -15972,13 +13537,13 @@ msgstr "" msgid "Add a new text replacement" -msgstr "Add a new text replacement" +msgstr "" msgid "You _type:" -msgstr "You _type:" +msgstr "" msgid "You _send:" -msgstr "You _send:" +msgstr "" #. Created here so it can be passed to whole_words_button_toggled. msgid "_Exact case match (uncheck for automatic case handling)" @@ -15987,107 +13552,88 @@ msgid "Only replace _whole words" msgstr "" -#, fuzzy msgid "General Text Replacement Options" -msgstr "Text Replacements" +msgstr "" msgid "Enable replacement of last word on send" msgstr "" msgid "Text replacement" -msgstr "Text replacement" +msgstr "" msgid "Replaces text in outgoing messages according to user-defined rules." -msgstr "Replaces text in outgoing messages according to user-defined rules." - -#, fuzzy +msgstr "" + msgid "Just logged in" -msgstr "Not logged in" - -#, fuzzy +msgstr "" + msgid "Just logged out" -msgstr "%s logged out." +msgstr "" msgid "" "Icon for Contact/\n" "Icon for Unknown person" msgstr "" -#, fuzzy msgid "Icon for Chat" -msgstr "Join a Chat" - -#, fuzzy +msgstr "" + msgid "Ignored" -msgstr "Ignore" - -#, fuzzy +msgstr "" + msgid "Founder" -msgstr "hour" +msgstr "" #. A user in a chat room who has special privileges. -#, fuzzy msgid "Operator" -msgstr "Opera" +msgstr "" #. A half operator is someone who has a subset of the privileges #. that an operator has. msgid "Half Operator" msgstr "" -#, fuzzy msgid "Authorization dialog" -msgstr "Authorization Given" - -#, fuzzy +msgstr "" + msgid "Error dialog" -msgstr "Error" - -#, fuzzy +msgstr "" + msgid "Information dialog" -msgstr "Information" +msgstr "" msgid "Mail dialog" msgstr "" -#, fuzzy msgid "Question dialog" -msgstr "Request ambiguous" - -#, fuzzy +msgstr "" + msgid "Warning dialog" -msgstr "Warning Level" +msgstr "" msgid "What kind of dialog is this?" msgstr "" -#, fuzzy msgid "Status Icons" -msgstr "Status: %s" - -#, fuzzy +msgstr "" + msgid "Chatroom Emblems" -msgstr "Chat Room List Url" - -#, fuzzy +msgstr "" + msgid "Dialog Icons" -msgstr "Save Icon" - -#, fuzzy +msgstr "" + msgid "Pidgin Icon Theme Editor" -msgstr "Pidgin File Control" - -#, fuzzy +msgstr "" + msgid "Contact" -msgstr "Account Info" - -#, fuzzy +msgstr "" + msgid "Pidgin Buddylist Theme Editor" -msgstr "Buddy List" - -#, fuzzy +msgstr "" + msgid "Edit Buddylist Theme" -msgstr "Buddy List" +msgstr "" msgid "Edit Icon Theme" msgstr "" @@ -16099,16 +13645,14 @@ #. *< priority #. *< id #. * description -#, fuzzy msgid "Pidgin Theme Editor" -msgstr "Pidgin File Control" +msgstr "" #. *< name #. *< version #. * summary -#, fuzzy msgid "Pidgin Theme Editor." -msgstr "Pidgin File Control" +msgstr "" #. *< type #. *< ui_requirement @@ -16117,18 +13661,17 @@ #. *< priority #. *< id msgid "Buddy Ticker" -msgstr "Buddy Ticker" +msgstr "" #. *< name #. *< version #. * summary #. * description msgid "A horizontal scrolling version of the buddy list." -msgstr "A horizontal scrolling version of the buddy list." - -#, fuzzy +msgstr "" + msgid "Display Timestamps Every" -msgstr "iChat Timestamp" +msgstr "" #. *< type #. *< ui_requirement @@ -16137,19 +13680,17 @@ #. *< priority #. *< id msgid "Timestamp" -msgstr "Timestamp" +msgstr "" #. *< name #. *< version #. * summary -#, fuzzy msgid "Display iChat-style timestamps" -msgstr "iChat Timestamp" +msgstr "" #. * description -#, fuzzy msgid "Display iChat-style timestamps every N minutes." -msgstr "Adds iChat-style timestamps to conversations every N minutes." +msgstr "" msgid "Timestamp Format Options" msgstr "" @@ -16158,9 +13699,8 @@ msgid "_Force timestamp format:" msgstr "" -#, fuzzy msgid "Use system default" -msgstr "Accept Defaults" +msgstr "" msgid "12 hour time format" msgstr "" @@ -16168,24 +13708,20 @@ msgid "24 hour time format" msgstr "" -#, fuzzy msgid "Show dates in..." -msgstr "Show more options" - -#, fuzzy +msgstr "" + msgid "Co_nversations:" -msgstr "Conversations" - -#, fuzzy +msgstr "" + msgid "For delayed messages" -msgstr "New away message" +msgstr "" msgid "For delayed messages and in chats" msgstr "" -#, fuzzy msgid "_Message Logs:" -msgstr "Message Logs" +msgstr "" #. *< type #. *< ui_requirement @@ -16208,35 +13744,44 @@ "timestamp formats." msgstr "" -#, fuzzy msgid "Audio" -msgstr "Authorize" - -#, fuzzy +msgstr "" + msgid "Video" -msgstr "Live Video" +msgstr "" msgid "Output" msgstr "" -#, fuzzy msgid "_Plugin" -msgstr "Plugins" - -#, fuzzy +msgstr "" + msgid "_Device" -msgstr "Device" +msgstr "" msgid "Input" msgstr "" -#, fuzzy msgid "P_lugin" -msgstr "Plugins" - -#, fuzzy +msgstr "" + msgid "D_evice" -msgstr "Device" +msgstr "" + +msgid "DROP" +msgstr "" + +msgid "Volume:" +msgstr "" + +msgid "Silence threshold:" +msgstr "" + +msgid "Input and Output Settings" +msgstr "" + +msgid "Microphone Test" +msgstr "" #. *< magic #. *< major version @@ -16247,13 +13792,8 @@ #. *< dependencies #. *< priority #. *< id -#, fuzzy msgid "Voice/Video Settings" -msgstr "Use Environmental Settings" - -#, fuzzy -msgid "Voice and Video Settings" -msgstr "Use Environmental Settings" +msgstr "" #. *< name #. *< version @@ -16265,36 +13805,33 @@ msgstr "" msgid "Opacity:" -msgstr "Opacity:" +msgstr "" #. IM Convo trans options msgid "IM Conversation Windows" -msgstr "IM Conversation Windows" +msgstr "" msgid "_IM window transparency" -msgstr "_IM window transparency" +msgstr "" msgid "_Show slider bar in IM window" -msgstr "_Show slider bar in IM window" - -#, fuzzy +msgstr "" + msgid "Remove IM window transparency on focus" -msgstr "_IM window transparency" - -#, fuzzy +msgstr "" + msgid "Always on top" -msgstr "Alias Contact" +msgstr "" #. Buddy List trans options msgid "Buddy List Window" -msgstr "Buddy List Window" +msgstr "" msgid "_Buddy List window transparency" -msgstr "_Buddy List window transparency" - -#, fuzzy +msgstr "" + msgid "Remove Buddy List window transparency on focus" -msgstr "_Buddy List window transparency" +msgstr "" #. *< type #. *< ui_requirement @@ -16303,62 +13840,53 @@ #. *< priority #. *< id msgid "Transparency" -msgstr "Transparency" +msgstr "" #. *< name #. *< version #. * summary msgid "Variable Transparency for the buddy list and conversations." -msgstr "Variable Transparency for the buddy list and conversations." +msgstr "" #. * description -#, fuzzy msgid "" "This plugin enables variable alpha transparency on conversation windows and " "the buddy list.\n" "\n" "* Note: This plugin requires Win2000 or greater." msgstr "" -"This plugin enables variable alpha transparency on conversation windows and " -"the buddy list.\n" -"\n" -"* Note: This plugin requires Win2000 or WinXP." #. Autostart msgid "Startup" -msgstr "Startup" - -#, fuzzy, c-format +msgstr "" + +#, c-format msgid "_Start %s on Windows startup" -msgstr "_Start Pidgin on Windows startup" +msgstr "" msgid "Allow multiple instances" msgstr "" msgid "_Dockable Buddy List" -msgstr "_Dockable Buddy List" +msgstr "" #. Blist On Top -#, fuzzy msgid "_Keep Buddy List window on top:" -msgstr "_Keep Buddy List window on top" +msgstr "" #. XXX: Did this ever work? msgid "Only when docked" msgstr "" -#, fuzzy msgid "Windows Pidgin Options" -msgstr "Login Options" - -#, fuzzy +msgstr "" + msgid "Options specific to Pidgin for Windows." -msgstr "Options specific to Windows Pidgin." - -#, fuzzy +msgstr "" + msgid "" "Provides options specific to Pidgin for Windows, such as buddy list docking." -msgstr "Options specific to Windows Pidgin." +msgstr "" msgid "Logged out." msgstr "" @@ -16369,13 +13897,11 @@ #. *< dependencies #. *< priority #. *< id -#, fuzzy msgid "XMPP Console" -msgstr "XMPP Profile" - -#, fuzzy +msgstr "" + msgid "Account: " -msgstr "Account:" +msgstr "" msgid "Not connected to XMPP" msgstr "" @@ -16422,9 +13948,8 @@ msgstr "" #. Installer Subsection Text -#, fuzzy msgid "Desktop" -msgstr "Accept Defaults" +msgstr "" #. $R2 will display the URL that the GTK+ Runtime failed to download from msgid "" @@ -16448,24 +13973,20 @@ msgstr "" #. Installer Subsection Text -#, fuzzy msgid "GTK+ Runtime (required if not present)" -msgstr "GTK+ Runtime Version" +msgstr "" #. Installer Subsection Text -#, fuzzy msgid "Localizations" -msgstr "Location" +msgstr "" #. "Next >" appears on a button on the License Page of the Installer -#, fuzzy msgid "Next >" -msgstr "Text" +msgstr "" #. Installer Subsection Text -#, fuzzy msgid "Pidgin Instant Messaging Client (required)" -msgstr "Instant Messagers" +msgstr "" msgid "" "Pidgin requires a compatible GTK+ Runtime (which doesn't appear to be " @@ -16474,9 +13995,8 @@ msgstr "" #. Installer Subsection Text -#, fuzzy msgid "Shortcuts" -msgstr "Shortcuts" +msgstr "" #. Installer Subsection Detailed Description msgid "Shortcuts for starting Pidgin" @@ -16487,18 +14007,16 @@ msgstr "" #. Installer Subsection Text -#, fuzzy msgid "Start Menu" -msgstr "Startup" +msgstr "" #. Installer Subsection Detailed Description msgid "" "Support for Spellchecking. (Internet connection required for installation)" msgstr "" -#, fuzzy msgid "The installer is already running." -msgstr "That file already exists" +msgstr "" msgid "" "The uninstaller could not find registry entries for Pidgin.$\\rIt is likely " @@ -16506,9 +14024,8 @@ msgstr "" #. Installer Subsection Text -#, fuzzy msgid "URI Handlers" -msgstr "_Handle:" +msgstr "" msgid "" "Unable to uninstall the currently installed version of Pidgin. The new " @@ -16521,2447 +14038,3 @@ msgid "You do not have permission to uninstall this application." msgstr "" - -#, fuzzy -#~ msgid "An error occurred on the in-band bytestream transfer\n" -#~ msgstr "An error occurred while opening the file." - -#, fuzzy -#~ msgid "Transfer was closed." -#~ msgstr "File transfer cancelled" - -#~ msgid "Set your friendly name." -#~ msgstr "Set your friendly name." - -#, fuzzy -#~ msgid "Error requesting %s" -#~ msgstr "Error creating connection" - -#, fuzzy -#~ msgid "Force old (port 5223) SSL" -#~ msgstr "Force old SSL" - -#, fuzzy -#~ msgid "The name you entered is invalid." -#~ msgstr "The SecurID key entered is invalid." - -#~ msgid "" -#~ "[Unable to display a message from this user because it contained invalid " -#~ "characters.]" -#~ msgstr "" -#~ "[Unable to display a message from this user because it contained invalid " -#~ "characters.]" - -#~ msgid "Search for Buddy by Information" -#~ msgstr "Search for Buddy by Information" - -#, fuzzy -#~ msgid "The certificate is not valid yet." -#~ msgstr "The SecurID key entered is invalid." - -#, fuzzy -#~ msgid "The nick name you entered is invalid." -#~ msgstr "The SecurID key entered is invalid." - -#, fuzzy -#~ msgid "Nick Name" -#~ msgstr "Nickname" - -#, fuzzy -#~ msgid "Your Mobile Number..." -#~ msgstr "Set Mobile Phone Number" - -#~ msgid "Rate to host" -#~ msgstr "Rate to host" - -#~ msgid "Rate to client" -#~ msgstr "Rate to client" - -#~ msgid "Unknown reason." -#~ msgstr "Unknown reason." - -#, fuzzy -#~ msgid "Artist" -#~ msgstr "Address" - -#, fuzzy -#~ msgid "Current Mood" -#~ msgstr "Your Current Mood" - -#, fuzzy -#~ msgid "New Mood" -#~ msgstr "User Modes" - -#, fuzzy -#~ msgid "Change your Mood" -#~ msgstr "Change Password" - -#, fuzzy -#~ msgid "Change Mood..." -#~ msgstr "Change Password..." - -#, fuzzy -#~ msgid "Pager server" -#~ msgstr "Proxy Server" - -#, fuzzy -#~ msgid "Yahoo Chat port" -#~ msgstr "Yahoo Japan" - -#, fuzzy -#~ msgid "Orientation" -#~ msgstr "Organization" - -#, fuzzy -#~ msgid "Error creating conference." -#~ msgstr "Error creating connection" - -#, fuzzy -#~ msgid "Unable to bind socket to port: %s" -#~ msgstr "Couldn't create socket" - -#, fuzzy -#~ msgid "Unable to listen on socket: %s" -#~ msgstr "Unable to create socket" - -#, fuzzy -#~ msgid "%s just sent you a Nudge!" -#~ msgstr "%s wants to send you a file" - -#~ msgid "Friendly name changes too rapidly" -#~ msgstr "Friendly name changes too rapidly" - -#~ msgid "Profile URL" -#~ msgstr "Profile URL" - -#~ msgid "MSN Protocol Plugin" -#~ msgstr "MSN Protocol Plugin" - -#~ msgid "%s is not a valid group." -#~ msgstr "%s is not a valid group." - -#~ msgid "Unknown error." -#~ msgstr "Unknown error." - -#~ msgid "%s on %s (%s)" -#~ msgstr "%s on %s (%s)" - -#~ msgid "Unable to add user on %s (%s)" -#~ msgstr "Unable to add user on %s (%s)" - -#~ msgid "Unable to block user on %s (%s)" -#~ msgstr "Unable to block user on %s (%s)" - -#~ msgid "Unable to permit user on %s (%s)" -#~ msgstr "Unable to permit user on %s (%s)" - -#~ msgid "%s could not be added because your buddy list is full." -#~ msgstr "%s could not be added because your buddy list is full." - -#~ msgid "%s is not a valid passport account." -#~ msgstr "%s is not a valid passport account." - -#, fuzzy -#~ msgid "Service Temporarily Unavailable." -#~ msgstr "Service Temporarily Unavailable" - -#~ msgid "Unable to rename group" -#~ msgstr "Unable to rename group" - -#~ msgid "Unable to delete group" -#~ msgstr "Unable to delete group" - -#, fuzzy -#~ msgid "%s has added you to his or her buddy list." -#~ msgstr "The user %s wants to add %s to his or her buddy list." - -#, fuzzy -#~ msgid "%s has removed you from his or her buddy list." -#~ msgstr "The user %s wants to add %s to his or her buddy list." - -#, fuzzy -#~ msgid "" -#~ "The last action you attempted could not be performed because you are over " -#~ "the rate limit. Please wait 10 seconds and try again.\n" -#~ msgstr "" -#~ "The last action you attempted could not be performed because you are over " -#~ "the rate limit. Please wait 10 seconds and try again." - -#, fuzzy -#~ msgid "" -#~ "IRC Channel: #pidgin on irc.freenode.net

" -#~ msgstr "IRC: #Pidgin on irc.freenode.net

" - -#, fuzzy -#~ msgid "XMPP MUC: devel@conference.pidgin.im

" -#~ msgstr "IRC: #Pidgin on irc.freenode.net

" - -#, fuzzy -#~ msgid "Debugging Information" -#~ msgstr "User Information" - -#, fuzzy -#~ msgid "" -#~ "Error saving image\n" -#~ "\n" -#~ "%s" -#~ msgstr "Error saving image: %s" - -#, fuzzy -#~ msgid "(Default)" -#~ msgstr "Gnome Default" - -#~ msgid "Icon" -#~ msgstr "Icon" - -#, fuzzy -#~ msgid "Proxy Server & Browser" -#~ msgstr "Proxy Server" - -#~ msgid "Auto-away" -#~ msgstr "Auto-away" - -#, fuzzy -#~ msgid "Change _status to:" -#~ msgstr "Change Address To:" - -#, fuzzy -#~ msgid "Failed to open file '%s': %s" -#~ msgstr "Failed to store image: %s\n" - -#, fuzzy -#~ msgid "Insert a stanza." -#~ msgstr "Insert image" - -#, fuzzy -#~ msgid "_Start port:" -#~ msgstr "_Start Port:" - -#, fuzzy -#~ msgid "_End port:" -#~ msgstr "_End Port:" - -#~ msgid "_User:" -#~ msgstr "_User:" - -#, fuzzy -#~ msgid "Calling ... " -#~ msgstr "Calculating..." - -#, fuzzy -#~ msgid "Invalid certificate chain" -#~ msgstr "Invalid Authorization Mechanism" - -#, fuzzy -#~ msgid "Join/Part Hiding Configuration" -#~ msgstr "Evolution Integration Configuration" - -#, fuzzy -#~ msgid "Malformed BOSH Connect Server" -#~ msgstr "Failed to connect to server." - -#, fuzzy -#~ msgid "Failed to open the file" -#~ msgstr "Failed to store image: %s\n" - -#, fuzzy -#~ msgid "Unable to not load SILC key pair" -#~ msgstr "Could not load public key" - -#~ msgid "Your account is locked, please log in to the Yahoo! website." -#~ msgstr "Your account is locked. Please log in to the Yahoo! website." - -#~ msgid "" -#~ "%s declined your conference invitation to room \"%s\" because \"%s\"." -#~ msgstr "" -#~ "%s declined your conference invitation to room \"%s\" because \"%s\"." - -#~ msgid "Invitation Rejected" -#~ msgstr "Invitation Rejected" - -#, fuzzy -#~ msgid "_Proxy" -#~ msgstr "No Proxy" - -#~ msgid "_Resume" -#~ msgstr "_Resume" - -#, fuzzy -#~ msgid "Cannot open socket" -#~ msgstr "Unable to open socket" - -#, fuzzy -#~ msgid "Could not listen on socket" -#~ msgstr "Couldn't create socket" - -#~ msgid "Unable to read socket" -#~ msgstr "Unable to read socket" - -#, fuzzy -#~ msgid "Connection failed." -#~ msgstr "Connection failed" - -#~ msgid "Server has disconnected" -#~ msgstr "Server has disconnected" - -#~ msgid "Couldn't create socket" -#~ msgstr "Couldn't create socket" - -#~ msgid "Couldn't connect to host" -#~ msgstr "Couldn't connect to host" - -#~ msgid "Read error" -#~ msgstr "Read error" - -#~ msgid "Write error" -#~ msgstr "Write error" - -#, fuzzy -#~ msgid "Service Discovery Info" -#~ msgstr "Set Dir Info" - -#, fuzzy -#~ msgid "Extended Stanza Addressing" -#~ msgstr "Extended Address" - -#, fuzzy -#~ msgid "Multi-User Chat" -#~ msgstr "Alias Chat" - -#, fuzzy -#~ msgid "Multi-User Chat Extended Presence Information" -#~ msgstr "User has no directory information." - -#, fuzzy -#~ msgid "Ad-Hoc Commands" -#~ msgstr "Command" - -#, fuzzy -#~ msgid "XHTML-IM" -#~ msgstr "HTML" - -#, fuzzy -#~ msgid "In-Band Registration" -#~ msgstr "Registration Error" - -#, fuzzy -#~ msgid "Chat State Notifications" -#~ msgstr "Buddy State Notification" - -#, fuzzy -#~ msgid "Software Version" -#~ msgstr "Unsupported Version" - -#, fuzzy -#~ msgid "Stream Initiation" -#~ msgstr "Organization" - -#, fuzzy -#~ msgid "User Activity" -#~ msgstr "User Limit" - -#, fuzzy -#~ msgid "Entity Capabilities" -#~ msgstr "Capabilities" - -#, fuzzy -#~ msgid "User Tune" -#~ msgstr "Username" - -#, fuzzy -#~ msgid "Roster Item Exchange" -#~ msgstr "IM with Key Exchange" - -#, fuzzy -#~ msgid "Reachability Address" -#~ msgstr "Email Address" - -#, fuzzy -#~ msgid "Jingle" -#~ msgstr "Ping" - -#, fuzzy -#~ msgid "User Nickname" -#~ msgstr "Nickname" - -#, fuzzy -#~ msgid "Jingle Video" -#~ msgstr "Live Video" - -#, fuzzy -#~ msgid "Message Receipts" -#~ msgstr "Message received" - -#, fuzzy -#~ msgid "Public Key Publishing" -#~ msgstr "Public Key Babbleprint" - -#, fuzzy -#~ msgid "User Chatting" -#~ msgstr "User Options" - -#, fuzzy -#~ msgid "User Browsing" -#~ msgstr "User Modes" - -#, fuzzy -#~ msgid "User Viewing" -#~ msgstr "User Limit" - -#, fuzzy -#~ msgid "Stanza Encryption" -#~ msgstr "Trillian Encryption" - -#~ msgid "Read Error" -#~ msgstr "Read Error" - -#~ msgid "Failed to connect to server." -#~ msgstr "Failed to connect to server." - -#, fuzzy -#~ msgid "Read buffer full (2)" -#~ msgstr "Queue full" - -#, fuzzy -#~ msgid "Unparseable message" -#~ msgstr "Unable to parse message" - -#, fuzzy -#~ msgid "Couldn't connect to host: %s (%d)" -#~ msgstr "Couldn't connect to host" - -#~ msgid "Login failed (%s)." -#~ msgstr "Login failed (%s)." - -#~ msgid "Unable to connect to server." -#~ msgstr "Unable to connect to server." - -#~ msgid "" -#~ "You have been logged out because you logged in at another workstation." -#~ msgstr "" -#~ "You have been logged out because you logged in at another workstation." - -#~ msgid "Error. SSL support is not installed." -#~ msgstr "Error. SSL support is not installed." - -#~ msgid "Incorrect password." -#~ msgstr "Incorrect password." - -#, fuzzy -#~ msgid "" -#~ "Could not connect to BOS server:\n" -#~ "%s" -#~ msgstr "Failed to connect to server." - -#, fuzzy -#~ msgid "You may be disconnected shortly. Check %s for updates." -#~ msgstr "" -#~ "You may be disconnected shortly. You may want to use TOC until this is " -#~ "fixed. Check %s for updates." - -#~ msgid "Could Not Connect" -#~ msgstr "Could Not Connect" - -#, fuzzy -#~ msgid "Invalid username." -#~ msgstr "Invalid Username" - -#, fuzzy -#~ msgid "Could not decrypt server reply" -#~ msgstr "Cannot get server information" - -#, fuzzy -#~ msgid "Connection lost" -#~ msgstr "Connection Closed" - -#, fuzzy -#~ msgid "Couldn't resolve host" -#~ msgstr "Couldn't connect to host" - -#, fuzzy -#~ msgid "Connection closed (writing)" -#~ msgstr "Connection Closed" - -#, fuzzy -#~ msgid "Error reading from socket: %s" -#~ msgstr "Error while reading from socket." - -#, fuzzy -#~ msgid "Unable to connect to host" -#~ msgstr "Unable to connect to server." - -#, fuzzy -#~ msgid "Could not write" -#~ msgstr "Could not send" - -#, fuzzy -#~ msgid "Could not create listen socket" -#~ msgstr "Couldn't create socket" - -#, fuzzy -#~ msgid "Could not resolve hostname" -#~ msgstr "Unable to resolve hostname." - -#, fuzzy -#~ msgid "Incorrect Password" -#~ msgstr "Incorrect password." - -#~ msgid "Yahoo Japan" -#~ msgstr "Yahoo Japan" - -#, fuzzy -#~ msgid "Japan Pager server" -#~ msgstr "Japan Pager host" - -#, fuzzy -#~ msgid "Japan file transfer server" -#~ msgstr "Japan File transfer host" - -#, fuzzy -#~ msgid "" -#~ "Lost connection with server\n" -#~ "%s" -#~ msgstr "You were disconnected from the server." - -#, fuzzy -#~ msgid "Could not resolve host name" -#~ msgstr "Unable to resolve hostname." - -#, fuzzy -#~ msgid "" -#~ "Unable to connect to %s: Server requires TLS/SSL, but no TLS/SSL support " -#~ "was found." -#~ msgstr "Server requires TLS/SSL for login. No TLS/SSL support found." - -#, fuzzy -#~ msgid "Conversation Window Hiding" -#~ msgstr "IM Conversation Windows" - -#, fuzzy -#~ msgid "Activate which ID?" -#~ msgstr "Active which ID?" - -#, fuzzy -#~ msgid "Interface colors" -#~ msgstr "Ignore c_olours" - -#, fuzzy -#~ msgid "Invite message" -#~ msgstr "(1 message)" - -#, fuzzy -#~ msgid "" -#~ "Please enter the name of the user you wish to invite,\n" -#~ "along with an optional invite message." -#~ msgstr "" -#~ "Please enter the name of the user you wish to invite, along with an " -#~ "optional invite message." - -#, fuzzy -#~ msgid "Unable to retrieve MSN Address Book" -#~ msgstr "Unable To Retrieve Buddy List" - -#~ msgid "" -#~ "You may be disconnected shortly. You may want to use TOC until this is " -#~ "fixed. Check %s for updates." -#~ msgstr "" -#~ "You may be disconnected shortly. You may want to use TOC until this is " -#~ "fixed. Check %s for updates." - -#, fuzzy -#~ msgid "Add buddy Q&A" -#~ msgstr "Add Buddy" - -#, fuzzy -#~ msgid "Can not decrypt get server reply" -#~ msgstr "Cannot get server information" - -#, fuzzy -#~ msgid "Keep alive error" -#~ msgstr "Reading error" - -#, fuzzy -#~ msgid "" -#~ "Lost connection with server:\n" -#~ "%d, %s" -#~ msgstr "You were disconnected from the server." - -#, fuzzy -#~ msgid "Connecting server ..." -#~ msgstr "Connect server" - -#, fuzzy -#~ msgid "Failed to send IM." -#~ msgstr "Failed to join chat" - -#~ msgid "Looking up %s" -#~ msgstr "Looking up %s" - -#~ msgid "Connect to %s failed" -#~ msgstr "Connect to %s failed" - -#~ msgid "Signon: %s" -#~ msgstr "Signon: %s" - -#~ msgid "Unable to write file %s." -#~ msgstr "Unable to write file %s." - -#~ msgid "Unable to read file %s." -#~ msgstr "Unable to read file %s." - -#~ msgid "Message too long, last %s bytes truncated." -#~ msgstr "Message too long, last %s bytes truncated." - -#~ msgid "%s not currently logged in." -#~ msgstr "%s not currently logged in." - -#~ msgid "Warning of %s not allowed." -#~ msgstr "Warning of %s not allowed." - -#~ msgid "" -#~ "A message has been dropped, you are exceeding the server speed limit." -#~ msgstr "" -#~ "A message has been dropped, you are exceeding the server speed limit." - -#~ msgid "You are sending messages too fast to %s." -#~ msgstr "You are sending messages too fast to %s." - -#~ msgid "You missed an IM from %s because it was too big." -#~ msgstr "You missed an IM from %s because it was too big." - -#~ msgid "You missed an IM from %s because it was sent too fast." -#~ msgstr "You missed an IM from %s because it was sent too fast." - -#~ msgid "Failure." -#~ msgstr "Failure." - -#~ msgid "Too many matches." -#~ msgstr "Too many matches." - -#~ msgid "Need more qualifiers." -#~ msgstr "Need more qualifiers." - -#~ msgid "Dir service temporarily unavailable." -#~ msgstr "Dir service temporarily unavailable." - -#~ msgid "Email lookup restricted." -#~ msgstr "Email lookup restricted." - -#~ msgid "Keyword ignored." -#~ msgstr "Keyword ignored." - -#~ msgid "No keywords." -#~ msgstr "No keywords." - -#~ msgid "User has no directory information." -#~ msgstr "User has no directory information." - -#~ msgid "Country not supported." -#~ msgstr "Country not supported." - -#~ msgid "Failure unknown: %s." -#~ msgstr "Failure unknown: %s." - -#, fuzzy -#~ msgid "Incorrect username or password." -#~ msgstr "Incorrect nickname or password." - -#~ msgid "The service is temporarily unavailable." -#~ msgstr "The service is temporarily unavailable." - -#~ msgid "Your warning level is currently too high to log in." -#~ msgstr "Your warning level is currently too high to log in." - -#~ msgid "" -#~ "You have been connecting and disconnecting too frequently. Wait ten " -#~ "minutes and try again. If you continue to try, you will need to wait " -#~ "even longer." -#~ msgstr "" -#~ "You have been connecting and disconnecting too frequently. Wait ten " -#~ "minutes and try again. If you continue to try, you will need to wait " -#~ "even longer." - -#~ msgid "An unknown error, %d, has occurred. Info: %s" -#~ msgstr "An unknown error, %d, has occurred. Info: %s" - -#, fuzzy -#~ msgid "Invalid Groupname" -#~ msgstr "Invalid group" - -#~ msgid "Connection Closed" -#~ msgstr "Connection Closed" - -#~ msgid "Waiting for reply..." -#~ msgstr "Waiting for reply..." - -#~ msgid "TOC has come back from its pause. You may now send messages again." -#~ msgstr "TOC has come back from its pause. You may now send messages again." - -#~ msgid "Password Change Successful" -#~ msgstr "Password Change Successful" - -#~ msgid "Get Dir Info" -#~ msgstr "Get Dir Info" - -#~ msgid "Set Dir Info" -#~ msgstr "Set Dir Info" - -#~ msgid "Could not open %s for writing!" -#~ msgstr "Could not open %s for writing!" - -#~ msgid "File transfer failed; other side probably cancelled." -#~ msgstr "File transfer failed; other side probably cancelled." - -#~ msgid "Could not connect for transfer." -#~ msgstr "Could not connect for transfer." - -#~ msgid "Could not write file header. The file will not be transferred." -#~ msgstr "Could not write file header. The file will not be transferred." - -#, fuzzy -#~ msgid "Save As..." -#~ msgstr "Save Icon As..." - -#~ msgid "%s requests %s to accept %d file: %s (%.2f %s)%s%s" -#~ msgid_plural "%s requests %s to accept %d files: %s (%.2f %s)%s%s" -#~ msgstr[0] "%s requests %s to accept %d file: %s (%.2f %s)%s%s" -#~ msgstr[1] "%s requests %s to accept %d files: %s (%.2f %s)%s%s" - -#~ msgid "%s requests you to send them a file" -#~ msgstr "%s requests you to send them a file" - -#~ msgid "TOC Protocol Plugin" -#~ msgstr "TOC Protocol Plugin" - -#~ msgid "User information for %s unavailable" -#~ msgstr "User information for %s unavailable" - -#~ msgid "%s Options" -#~ msgstr "%s Options" - -#~ msgid "Proxy Options" -#~ msgstr "Proxy Options" - -#~ msgid "By log size" -#~ msgstr "By log size" - -#~ msgid "_Open Link in Browser" -#~ msgstr "_Open Link in Browser" - -#, fuzzy -#~ msgid "Smiley _Image" -#~ msgstr "Save Image" - -#, fuzzy -#~ msgid "Smiley S_hortcut" -#~ msgstr "Shortcuts" - -#, fuzzy -#~ msgid "_Flash window when chat messages are received" -#~ msgstr "_Flash Window when messages are received" - -#, fuzzy -#~ msgid "A group with the name already exists." -#~ msgstr "A folder with that name already exists" - -#, fuzzy -#~ msgid "Primary Information" -#~ msgstr "Profile Information" - -#, fuzzy -#~ msgid "Update information" -#~ msgstr "User Information" - -#, fuzzy -#~ msgid "Invalid QQ Face" -#~ msgstr "Invalid Room Name" - -#, fuzzy -#~ msgid "You rejected %d's request" -#~ msgstr "Unexpected Request" - -#, fuzzy -#~ msgid "Reject request" -#~ msgstr "Unexpected Request" - -#, fuzzy -#~ msgid "Add buddy with auth request failed" -#~ msgstr "Add buddy rejected" - -#, fuzzy -#~ msgid "Add into %d's buddy list" -#~ msgstr "Add the chat to your buddy list" - -#, fuzzy -#~ msgid "QQ Number Error" -#~ msgstr "Read Error" - -#, fuzzy -#~ msgid "Group Description" -#~ msgstr "Description" - -#, fuzzy -#~ msgid "Auth" -#~ msgstr "Authorize" - -#, fuzzy -#~ msgid "I am requesting" -#~ msgstr "Bad Request" - -#, fuzzy -#~ msgid "Unknown status" -#~ msgstr "Unknown message" - -#, fuzzy -#~ msgid "Remove from Qun" -#~ msgstr "Remove Group" - -#, fuzzy -#~ msgid "Are you sure you want to leave this Qun?" -#~ msgstr "Are you sure you want to delete %s?" - -#, fuzzy -#~ msgid "Do you want to approve the request?" -#~ msgstr "Are you sure you want to remove the away message \"%s\"?" - -#, fuzzy -#~ msgid "System Message" -#~ msgstr "Send Message" - -#, fuzzy -#~ msgid "Last Login IP: %s
\n" -#~ msgstr "Alias: %s
" - -#, fuzzy -#~ msgid "Last Login Time: %s\n" -#~ msgstr "" -#~ "\n" -#~ "%s: %s" - -#, fuzzy -#~ msgid "Set My Information" -#~ msgstr "Server Information" - -#, fuzzy -#~ msgid "Block this buddy" -#~ msgstr "Block the user" - -#, fuzzy -#~ msgid "Error password: %s" -#~ msgstr "Error changing password" - -#, fuzzy -#~ msgid "Failed to connect all servers" -#~ msgstr "Failed to connect to server." - -#, fuzzy -#~ msgid "Connecting server %s, retries %d" -#~ msgstr "" -#~ "Connection error from %s server (%s):\n" -#~ "%s" - -#, fuzzy -#~ msgid "Do you approve the requestion?" -#~ msgstr "Are you sure you want to remove the away message \"%s\"?" - -#, fuzzy -#~ msgid "Do you add the buddy?" -#~ msgstr "Do you want to add this buddy to your buddy list?" - -#, fuzzy -#~ msgid "%s added you [%s] to buddy list" -#~ msgstr "The user %s wants to add %s to his or her buddy list." - -#, fuzzy -#~ msgid "QQ Budy" -#~ msgstr "Add Buddy" - -#, fuzzy -#~ msgid "%s wants to add you [%s] as a friend" -#~ msgstr "%s wants to send you a file" - -#, fuzzy -#~ msgid "%s is not in buddy list" -#~ msgstr "Add the user to your buddy list" - -#, fuzzy -#~ msgid "Would you add?" -#~ msgstr "Would you like to overwrite it?" - -#, fuzzy -#~ msgid "QQ Server Notice" -#~ msgstr "Server port" - -#, fuzzy -#~ msgid "Network disconnected" -#~ msgstr "Disconnected." - -#~ msgid "developer" -#~ msgstr "developer" - -#, fuzzy -#~ msgid "XMPP developer" -#~ msgstr "former XMPP developer" - -#, fuzzy -#~ msgid "" -#~ "You are using %s version %s. The current version is %s. You can get it " -#~ "from %s
" -#~ msgstr "You are using Pidgin version %s. The current version is %s.
" - -#, fuzzy -#~ msgid "ChangeLog:
%s" -#~ msgstr "" -#~ "ChangeLog:\n" -#~ "%s

" - -#, fuzzy -#~ msgid "Screen name:" -#~ msgstr "Screenname:" - -#, fuzzy -#~ msgid "Show offline buddies" -#~ msgstr "/Buddies/Show Offline Buddies" - -#, fuzzy -#~ msgid "Sort by status" -#~ msgstr "Status" - -#, fuzzy -#~ msgid "Sort alphabetically" -#~ msgstr "Alphabetical" - -#, fuzzy -#~ msgid "Sort by log size" -#~ msgstr "By log size" - -#, fuzzy -#~ msgid "EOF while reading from resolver process" -#~ msgstr "Error while reading from socket." - -#, fuzzy -#~ msgid "There were errors unloading the plugin." -#~ msgstr "Provides support for loading perl plugins." - -#, fuzzy -#~ msgid "Error setting socket options" -#~ msgstr "Error creating connection" - -#, fuzzy -#~ msgid "Couldn't open file" -#~ msgstr "Cannot send file" - -#~ msgid "" -#~ "This server requires plaintext authentication over an unencrypted " -#~ "connection. Allow this and continue authentication?" -#~ msgstr "" -#~ "This server requires plaintext authentication over an unencrypted " -#~ "connection. Allow this and continue authentication?" - -#~ msgid "Error initializing session" -#~ msgstr "Error initializing session" - -#, fuzzy -#~ msgid "Invalid screen name" -#~ msgstr "Invalid Username" - -#~ msgid "Too evil (sender)" -#~ msgstr "Too evil (sender)" - -#~ msgid "Too evil (receiver)" -#~ msgstr "Too evil (receiver)" - -#~ msgid "Screen name sent" -#~ msgstr "Screen name sent" - -#, fuzzy -#~ msgid "Invalid screen name." -#~ msgstr "Invalid username." - -#, fuzzy -#~ msgid "Available Message" -#~ msgstr "Available Message:" - -#, fuzzy -#~ msgid "Screen name" -#~ msgstr "_Screen name" - -#~ msgid "Invalid chat name specified." -#~ msgstr "Invalid chat name specified." - -#~ msgid "Away Message" -#~ msgstr "Away Message" - -#, fuzzy -#~ msgid "(retrieving)" -#~ msgstr " (identified)" - -#, fuzzy -#~ msgid "Use recent buddies group" -#~ msgstr "User not in group" - -#, fuzzy -#~ msgid "Show how long you have been idle" -#~ msgstr "Allows you to hand-configure how long you've been idle for" - -#, fuzzy -#~ msgid "Your information has been updated" -#~ msgstr "Your password has been changed." - -#, fuzzy -#~ msgid "You have added %d to buddy list" -#~ msgstr "Add the user to your buddy list" - -#, fuzzy -#~ msgid "Invalid QQid" -#~ msgstr "Invalid authzid" - -#, fuzzy -#~ msgid "Please enter external group ID" -#~ msgstr "Please enter the name of the group to be added." - -#, fuzzy -#~ msgid "Reason: %s" -#~ msgstr "Users on %s: %s" - -#, fuzzy -#~ msgid "Group Operation Error" -#~ msgstr "File operation error" - -#, fuzzy -#~ msgid "Enter your reason:" -#~ msgstr "%s not currently logged in." - -#, fuzzy -#~ msgid "Unable to login, check debug log" -#~ msgstr "Unable to login to AIM" - -#, fuzzy -#~ msgid "TCP Address" -#~ msgstr "IP Address" - -#, fuzzy -#~ msgid "UDP Address" -#~ msgstr "IP Address" - -#, fuzzy -#~ msgid "Show Login Information" -#~ msgstr "User Information" - -#, fuzzy -#~ msgid "Login failed, no reply" -#~ msgstr "Login failed (%s)." - -#, fuzzy -#~ msgid "Cannot find/access ~/.silc directory" -#~ msgstr "Cannot send a directory." - -#, fuzzy -#~ msgid "%s changed status from %s to %s" -#~ msgstr "%s has changed the topic to: %s" - -#, fuzzy -#~ msgid "%s is now %s" -#~ msgstr "%s is now known as %s" - -#, fuzzy -#~ msgid "%s is no longer %s" -#~ msgstr "%s is no longer away." - -#, fuzzy -#~ msgid "Screen _name:" -#~ msgstr "Screenname:" - -#, fuzzy -#~ msgid "_Send File" -#~ msgstr "Send File" - -#, fuzzy -#~ msgid "Add Buddy _Pounce" -#~ msgstr "Add Buddy _Pounce" - -#~ msgid "Add a C_hat" -#~ msgstr "Add a C_hat" - -#, fuzzy -#~ msgid "/Accounts/Add\\/Edit" -#~ msgstr "Accounts" - -#, fuzzy -#~ msgid "%s disconnected: %s" -#~ msgstr "" -#~ "%s has been disconnected.\n" -#~ "\n" -#~ "%s\n" -#~ "%s" - -#~ msgid "" -#~ "Please enter the screen name of the person you would like to add to your " -#~ "buddy list. You may optionally enter an alias, or nickname, for the " -#~ "buddy. The alias will be displayed in place of the screen name whenever " -#~ "possible.\n" -#~ msgstr "" -#~ "Please enter the screen name of the person you would like to add to your " -#~ "buddy list. You may optionally enter an alias, or nickname, for the " -#~ "buddy. The alias will be displayed in place of the screen name whenever " -#~ "possible.\n" - -#, fuzzy -#~ msgid "_Screen name:" -#~ msgstr "_Screen name" - -#, fuzzy -#~ msgid "User has typed something and stopped" -#~ msgstr "User has typed something and paused" - -#, fuzzy -#~ msgid "_Send To" -#~ msgstr "_Send As" - -#, fuzzy -#~ msgid "" -#~ "%s%sWritten by:\t%s\n" -#~ "Website:\t\t%s\n" -#~ "Filename:\t\t%s" -#~ msgstr "" -#~ "%s %s\n" -#~ "\n" -#~ "Written by:\t%s\n" -#~ "Web site:\t\t%s\n" -#~ "File name:\t%s" - -#, fuzzy -#~ msgid "Display Statistics" -#~ msgstr "Display timeout notices" - -#, fuzzy -#~ msgid "Log Viewer" -#~ msgstr "Login server" - -#, fuzzy -#~ msgid "Unable to connect to contact server" -#~ msgstr "Unable to connect to server." - -#, fuzzy -#~ msgid "Current media" -#~ msgstr "Currently on" - -#, fuzzy -#~ msgid "_Merge" -#~ msgstr "_Message:" - -#~ msgid "Hide Disconnect Errors" -#~ msgstr "Hide Disconnect Errors" - -#, fuzzy -#~ msgid "Hide Reconnecting Dialog" -#~ msgstr "Hide Disconnect Errors" - -#~ msgid "When you are kicked offline, this reconnects you." -#~ msgstr "When you are kicked offline, this reconnects you." - -#~ msgid "Use last matching buddy" -#~ msgstr "Use last matching buddy" - -#, fuzzy -#~ msgid "" -#~ "The buddy with the lowest score is the buddy who will have priority in " -#~ "the contact.\n" -#~ "The default values (offline = 4, away = 2, and idle = 1) will use what " -#~ "used to be\n" -#~ "the built-in order: active, idle, away, away + idle, offline." -#~ msgstr "" -#~ "The buddy with the lowest score is the buddy who will have priority in " -#~ "the contact.\n" -#~ "The default values (offline = 4,away = 2, and idle = 1)\n" -#~ "will use what used to be the built-in order active->idle->away->away+idle-" -#~ ">offline." - -#~ msgid "Pidgin - Signed off" -#~ msgstr "Pidgin - Signed off" - -#~ msgid "Pidgin - Away" -#~ msgstr "Pidgin - Away" - -#~ msgid "Displays an icon for Pidgin in the system tray." -#~ msgstr "Displays an icon for Pidgin in the system tray." - -#~ msgid "" -#~ "Displays a system tray icon (in GNOME, KDE or Windows for example) to " -#~ "show the current status of Pidgin, allow fast access to commonly used " -#~ "functions, and to toggle display of the buddy list or login window. Also " -#~ "allows messages to be queued until the icon is clicked, similar to ICQ." -#~ msgstr "" -#~ "Displays a system tray icon (in GNOME, KDE or Windows for example) to " -#~ "show the current status of Pidgin, allow fast access to commonly used " -#~ "functions, and to toggle display of the buddy list or login window. Also " -#~ "allows messages to be queued until the icon is clicked, similar to ICQ." - -#, fuzzy -#~ msgid "GtkTreeView Expander Size" -#~ msgstr "Expander Size" - -#~ msgid "" -#~ "You can get version %s from:
http://Pidgin.sourceforge.net." -#~ msgstr "" -#~ "You can get version %s from:
http://Pidgin.sourceforge.net." - -#~ msgid "Delay" -#~ msgstr "Delay" - -#~ msgid "WinPidgin Options" -#~ msgstr "WinPidgin Options" - -#~ msgid "" -#~ "%d buddy from group %s was not removed because its account was not logged " -#~ "in. This buddy and the group were not removed.\n" -#~ msgid_plural "" -#~ "%d buddies from group %s were not removed because their accounts were not " -#~ "logged in. These buddies and the group were not removed.\n" -#~ msgstr[0] "" -#~ "%d buddy from group %s was not removed because its account was not logged " -#~ "in. This buddy and the group were not removed.\n" -#~ msgstr[1] "" -#~ "%d buddies from group %s were not removed because their accounts were not " -#~ "logged in. These buddies and the group were not removed.\n" - -#~ msgid "Group not removed" -#~ msgstr "Group not removed" - -#~ msgid "(+%d more)" -#~ msgstr "(+%d more)" - -#~ msgid " left the room (%s)." -#~ msgstr " left the room (%s)." - -#~ msgid "Screen Name:" -#~ msgstr "Screen Name:" - -#~ msgid "Buddy icon:" -#~ msgstr "Buddy icon:" - -#~ msgid "" -#~ "\n" -#~ "\n" -#~ "Do you wish to add him or her to your buddy list?" -#~ msgstr "" -#~ "\n" -#~ "\n" -#~ "Do you wish to add him or her to your buddy list?" - -#~ msgid "_Alias Buddy..." -#~ msgstr "_Alias Buddy..." - -#~ msgid "Alias Contact..." -#~ msgstr "Alias Contact..." - -#~ msgid "/Tools/Account Ac_tions" -#~ msgstr "/Tools/Account Ac_tions" - -#~ msgid "/Tools/A_ccounts" -#~ msgstr "/Tools/A_ccounts" - -#, fuzzy -#~ msgid "" -#~ "\n" -#~ "Contact Alias: %s" -#~ msgstr "" -#~ "\n" -#~ "Contact Alias:" - -#, fuzzy -#~ msgid "" -#~ "\n" -#~ "Alias: %s" -#~ msgstr "" -#~ "\n" -#~ "Alias:" - -#, fuzzy -#~ msgid "" -#~ "\n" -#~ "Nickname: %s" -#~ msgstr "" -#~ "\n" -#~ "Nickname:" - -#, fuzzy -#~ msgid "" -#~ "\n" -#~ "Logged In: %s" -#~ msgstr "" -#~ "\n" -#~ "Logged In:" - -#~ msgid "" -#~ "\n" -#~ "Status: Offline" -#~ msgstr "" -#~ "\n" -#~ "Status: Offline" - -#, fuzzy -#~ msgid "" -#~ "\n" -#~ "Status: Awesome" -#~ msgstr "" -#~ "\n" -#~ "Status: Awesome" - -#, fuzzy -#~ msgid "" -#~ "\n" -#~ "Status: Rockin'" -#~ msgstr "" -#~ "\n" -#~ "Status: Rockin'" - -#~ msgid "/Tools/Buddy Pounce" -#~ msgstr "/Tools/Buddy Pounce" - -#~ msgid "/Tools/Account Actions" -#~ msgstr "/Tools/Account Actions" - -#~ msgid "me is using Pidgin v%s." -#~ msgstr "me is using Pidgin v%s." - -#, fuzzy -#~ msgid "/Options/Show Buddy _Icon" -#~ msgstr "Show buddy _icons" - -#, fuzzy -#~ msgid "/Options/Show Buddy Icon" -#~ msgstr "Show buddy _icons" - -#~ msgid "IM the user" -#~ msgstr "IM the user" - -#~ msgid "Ignore the user" -#~ msgstr "Ignore the user" - -#~ msgid "Get the user's information" -#~ msgstr "Get the user's information" - -#, fuzzy -#~ msgid "" -#~ "Pidgin is a modular messaging client capable of using AIM, MSN, Yahoo!, " -#~ "XMPP, ICQ, IRC, SILC, Novell GroupWise, Napster, Zephyr, and Gadu-Gadu " -#~ "all at once. It is written using GTK+ and is licensed under the GNU GPL." -#~ "

" -#~ msgstr "" -#~ "Pidgin is a modular messaging client capable of using AIM, MSN, Yahoo!, " -#~ "XMPP, ICQ, IRC, SILC, Novell GroupWise, Napster, Zephyr, and Gadu-Gadu " -#~ "all at once. It is written using Gtk+ and is licenced under the GPL." -#~ "

" - -#~ msgid "IRC: #winPidgin on irc.freenode.net

" -#~ msgstr "IRC: #winPidgin on irc.freenode.net

" - -#~ msgid "Active Developers" -#~ msgstr "Active Developers" - -#~ msgid "_Keep the dialog open" -#~ msgstr "_Keep the dialogue open" - -#~ msgid "Smaller font size" -#~ msgstr "Smaller font size" - -#~ msgid "Insert link" -#~ msgstr "Insert link" - -#~ msgid "Insert image" -#~ msgstr "Insert image" - -#~ msgid "From: %s\n" -#~ msgstr "From: %s\n" - -#~ msgid "Subject: %s\n" -#~ msgstr "Subject: %s\n" - -#~ msgid "" -#~ "You have mail!\n" -#~ "\n" -#~ "%s%s%s%s" -#~ msgstr "" -#~ "You have mail!\n" -#~ "\n" -#~ "%s%s%s%s" - -#~ msgid "Error launching %s: %s" -#~ msgstr "Error launching %s: %s" - -#~ msgid "A_way" -#~ msgstr "A_way" - -#~ msgid "_Idle" -#~ msgstr "_Idle" - -#~ msgid "Pounce Action" -#~ msgstr "Pounce Action" - -#~ msgid "Bro_wse..." -#~ msgstr "Bro_wse..." - -#~ msgid "Sav_e this pounce after activation" -#~ msgstr "Sav_e this pounce after activation" - -#~ msgid "Remove Buddy Pounce" -#~ msgstr "Remove Buddy Pounce" - -#~ msgid "Send unknown \"_slash\" commands as messages" -#~ msgstr "Send unknown \"_slash\" commands as messages" - -#~ msgid "Show buddy _icons" -#~ msgstr "Show buddy _icons" - -#~ msgid "Tab Options" -#~ msgstr "Tab Options" - -#~ msgid "_Sounds while away" -#~ msgstr "_Sounds while away" - -#~ msgid "_Queue new messages when away" -#~ msgstr "_Queue new messages when away" - -#, fuzzy -#~ msgid "Custom status" -#~ msgstr "By status" - -#~ msgid "" -#~ "Unable to play sound because the 'Command' sound method has been chosen, " -#~ "but no command has been set." -#~ msgstr "" -#~ "Unable to play sound because the 'Command' sound method has been chosen, " -#~ "but no command has been set." - -#~ msgid "" -#~ "Unable to play sound because the configured sound command could not be " -#~ "launched: %s" -#~ msgstr "" -#~ "Unable to play sound because the configured sound command could not be " -#~ "launched: %s" - -#~ msgid "_Warn" -#~ msgstr "_Warn" - -#, fuzzy -#~ msgid "" -#~ "\n" -#~ "Status: %s" -#~ msgstr "" -#~ "\n" -#~ "Status: Awesome" - -#, fuzzy -#~ msgid "" -#~ "\n" -#~ "Message: %s" -#~ msgstr "" -#~ "\n" -#~ "%s: %s" - -#, fuzzy -#~ msgid "Could't open file" -#~ msgstr "Cannot send file" - -#, fuzzy -#~ msgid "Change password" -#~ msgstr "Change Password" - -#~ msgid "%s: %s" -#~ msgstr "%s: %s" - -#~ msgid "" -#~ "Server requires TLS/SSL for login. Select \"Use TLS if available\" in " -#~ "account properties" -#~ msgstr "" -#~ "Server requires TLS/SSL for login. Select \"Use TLS if available\" in " -#~ "account properties" - -#~ msgid "The user %s wants to add %s to his or her buddy list." -#~ msgstr "The user %s wants to add %s to his or her buddy list." - -#~ msgid "Hidden" -#~ msgstr "Hidden" - -#~ msgid "MSN Profile" -#~ msgstr "MSN Profile" - -#~ msgid "Login server" -#~ msgstr "Login server" - -#~ msgid "The user %s (%s) wants to add %s to his or her buddy list." -#~ msgstr "The user %s (%s) wants to add %s to his or her buddy list." - -#~ msgid "Unable to read header from server" -#~ msgstr "Unable to read header from server" - -#~ msgid "" -#~ "Unable to read message from server: %s. Command is %hd, length is %hd." -#~ msgstr "" -#~ "Unable to read message from server: %s. Command is %hd, length is %hd." - -#~ msgid "users: %s, files: %s, size: %sGB" -#~ msgstr "users: %s, files: %s, size: %sGB" - -#~ msgid "Unable to add \"%s\" to your Napster hotlist" -#~ msgstr "Unable to add \"%s\" to your Napster hotlist" - -#~ msgid "%s requested a PING" -#~ msgstr "%s requested a PING" - -#~ msgid "NAPSTER Protocol Plugin" -#~ msgstr "NAPSTER Protocol Plugin" - -#~ msgid "Error processing event or response (%s)." -#~ msgstr "Error processing event or response (%s)." - -#~ msgid "Direct IM with %s closed" -#~ msgstr "Direct IM with %s closed" - -#~ msgid "Direct IM with %s failed" -#~ msgstr "Direct IM with %s failed" - -#~ msgid "Unable to open Direct IM" -#~ msgstr "Unable to open Direct IM" - -#, fuzzy -#~ msgid "Unable to log into file transfer proxy." -#~ msgstr "Unable to write file %s." - -#, fuzzy -#~ msgid "" -#~ "Unable to establish listener socket or no AOL proxy connection present." -#~ msgstr "Unable to establish listener socket." - -#~ msgid "" -#~ "The user %s requires authorization before being added to a buddy list. " -#~ "Do you want to send an authorization request?" -#~ msgstr "" -#~ "The user %s requires authorization before being added to a buddy list. " -#~ "Do you want to send an authorization request?" - -#, fuzzy -#~ msgid "" -#~ "The user %u wants to add %s to their buddy list for the following " -#~ "reason:\n" -#~ "%s" -#~ msgstr "" -#~ "The user %u wants to add you to their buddy list for the following " -#~ "reason:\n" -#~ "%s" - -#~ msgid "Authorization Request" -#~ msgstr "Authorization Request" - -#~ msgid "UIN: %s
Status: %s
%s" -#~ msgstr "UIN: %s
Status: %s
%s" - -#~ msgid "SNAC threw error: %s\n" -#~ msgstr "SNAC threw error: %s\n" - -#~ msgid "User information for %s unavailable:" -#~ msgstr "User information for %s unavailable:" - -#~ msgid "Rate limiting error." -#~ msgstr "Rate limiting error." - -#~ msgid "You have been signed off for an unknown reason." -#~ msgstr "You have been signed off for an unknown reason." - -#~ msgid "" -#~ "Your screen name is currently formatted as follows:\n" -#~ "%s" -#~ msgstr "" -#~ "Your screen name is currently formatted as follows:\n" -#~ "%s" - -#~ msgid "Unable to set AIM away message." -#~ msgstr "Unable to set AIM away message." - -#~ msgid "" -#~ "You have probably requested to set your away message before the login " -#~ "procedure completed. You remain in a \"present\" state; try setting it " -#~ "again when you are fully connected." -#~ msgstr "" -#~ "You have probably requested to set your away message before the login " -#~ "procedure completed. You remain in a \"present\" state; try setting it " -#~ "again when you are fully connected." - -#~ msgid "" -#~ "Could not add the buddy %s for an unknown reason. The most common reason " -#~ "for this is that you have the maximum number of allowed buddies in your " -#~ "buddy list." -#~ msgstr "" -#~ "Could not add the buddy %s for an unknown reason. The most common reason " -#~ "for this is that you have the maximum number of allowed buddies in your " -#~ "buddy list." - -#, fuzzy -#~ msgid "" -#~ "The user %s wants to add %s to their buddy list for the following " -#~ "reason:\n" -#~ "%s" -#~ msgstr "" -#~ "The user %s wants to add you to their buddy list for the following " -#~ "reason:\n" -#~ "%s" - -#, fuzzy -#~ msgid "Hide IP address" -#~ msgstr "IP Address" - -#, fuzzy -#~ msgid "Web aware" -#~ msgstr "Web Aware" - -#~ msgid "New screen name formatting:" -#~ msgstr "New screen name formatting:" - -#~ msgid "Format Screen Name..." -#~ msgstr "Format Screen Name..." - -#~ msgid "Auth host" -#~ msgstr "Auth host" - -#~ msgid "Active" -#~ msgstr "Active" - -#~ msgid "EMail" -#~ msgstr "EMail" - -#~ msgid "Instant Messages" -#~ msgstr "Instant Messages" - -#~ msgid "Verify all IM message signatures" -#~ msgstr "Verify all IM message signatures" - -#~ msgid "Channel Messages" -#~ msgstr "Channel Messages" - -#~ msgid "Digitally sign all channel messages" -#~ msgstr "Digitally sign all channel messages" - -#~ msgid "Verify all channel message signatures" -#~ msgstr "Verify all channel message signatures" - -#~ msgid "Reject watching by other users" -#~ msgstr "Reject watching by other users" - -#~ msgid "Block invites" -#~ msgstr "Block invites" - -#~ msgid "Reject online status attribute requests" -#~ msgstr "Reject online status attribute requests" - -#~ msgid "TOC has sent a PAUSE command." -#~ msgstr "TOC has sent a PAUSE command." - -#~ msgid "" -#~ "When this happens, TOC ignores any messages sent to it, and may kick you " -#~ "off if you send a message. Pidgin will prevent anything from going " -#~ "through. This is only temporary, please be patient." -#~ msgstr "" -#~ "When this happens, TOC ignores any messages sent to it, and may kick you " -#~ "off if you send a message. Pidgin will prevent anything from going " -#~ "through. This is only temporary, please be patient." - -#~ msgid "Pidgin - Save As..." -#~ msgstr "Pidgin - Save As..." - -#~ msgid "TOC host" -#~ msgstr "TOC host" - -#~ msgid "TOC port" -#~ msgstr "TOC port" - -#~ msgid "" -#~ "The normal authentication method has failed. This means either your " -#~ "password is incorrect, or Yahoo!'s authentication scheme has changed. " -#~ "Pidgin will now attempt to log in using Web Messenger authentication, " -#~ "which will result in reduced functionality and features." -#~ msgstr "" -#~ "The normal authentication method has failed. This means either your " -#~ "password is incorrect, or Yahoo!'s authentication scheme has changed. " -#~ "Pidgin will now attempt to log in using Web Messenger authentication, " -#~ "which will result in reduced functionality and features." - -#~ msgid "Unable to read" -#~ msgstr "Unable to read" - -#, fuzzy -#~ msgid "Stealth" -#~ msgstr "Province/Territory" - -#~ msgid "Pager host" -#~ msgstr "Pager host" - -#~ msgid "YCHT Host" -#~ msgstr "YCHT Host" - -#~ msgid "YCHT Port" -#~ msgstr "YCHT Port" - -#~ msgid "(%d message)" -#~ msgid_plural "(%d messages)" -#~ msgstr[0] "(%d message)" -#~ msgstr[1] "(%d messages)" - -#, fuzzy -#~ msgid "Default auto-away" -#~ msgstr "Auto-away" - -#~ msgid "g003: Error opening connection.\n" -#~ msgstr "g003: Error opening connection.\n" - -#, fuzzy -#~ msgid "Show more buddy details" -#~ msgstr "Show user details" - -#~ msgid "Gnome Default" -#~ msgstr "Gnome Default" - -#~ msgid "Away m_essage:" -#~ msgstr "Away m_essage:" - -#~ msgid "Restore Away State On Reconnect" -#~ msgstr "Restore Away State On Reconnect" - -#~ msgid "Mail Server" -#~ msgstr "Mail Server" - -#~ msgid "%s (%d new/%d total)" -#~ msgstr "%s (%d new/%d total)" - -#~ msgid "Check Mail" -#~ msgstr "Check Mail" - -#~ msgid "Check email every X seconds.\n" -#~ msgstr "Check email every X seconds.\n" - -#~ msgid "Auto-login" -#~ msgstr "Auto-login" - -#~ msgid "Signoff" -#~ msgstr "Signoff" - -#~ msgid "_Hide new messages until tray icon is clicked" -#~ msgstr "_Hide new messages until tray icon is clicked" - -#~ msgid "Not connected to AIM" -#~ msgstr "Not connected to AIM" - -#~ msgid "No roomname given." -#~ msgstr "No roomname given." - -#~ msgid "Invalid AIM URI" -#~ msgstr "Invalid AIM URI" - -#~ msgid "" -#~ "Failed to assign %s to a socket:\n" -#~ "%s" -#~ msgstr "" -#~ "Failed to assign %s to a socket:\n" -#~ "%s" - -#~ msgid "Remote Control" -#~ msgstr "Remote Control" - -#~ msgid "Provides remote control for Pidgin applications." -#~ msgstr "Provides remote control for Pidgin applications." - -#~ msgid "" -#~ "Gives Pidgin the ability to be remote-controlled through third-party " -#~ "applications or through the Pidgin-remote tool." -#~ msgstr "" -#~ "Gives Pidgin the ability to be remote-controlled through third-party " -#~ "applications or through the Pidgin-remote tool." - -#~ msgid "Docked _Buddy List is always on top" -#~ msgstr "Docked _Buddy List is always on top" - -#~ msgid "Away!" -#~ msgstr "Away!" - -#~ msgid "Edit This Message" -#~ msgstr "Edit This Message" - -#~ msgid "I'm Back!" -#~ msgstr "I'm Back!" - -#~ msgid "Remove Away Message" -#~ msgstr "Remove Away Message" - -#~ msgid "Set All Away" -#~ msgstr "Set All Away" - -#~ msgid "You cannot save an away message with a blank title" -#~ msgstr "You cannot save an away message with a blank title" - -#~ msgid "" -#~ "Please give the message a title, or choose \"Use\" to use without saving." -#~ msgstr "" -#~ "Please give the message a title, or choose \"Use\" to use without saving." - -#~ msgid "You cannot create an empty away message" -#~ msgstr "You cannot create an empty away message" - -#~ msgid "Away title: " -#~ msgstr "Away title: " - -#~ msgid "Size of the expander arrow" -#~ msgstr "Size of the expander arrow" - -#~ msgid "" -#~ "Usage: %s command [OPTIONS] [URI]\n" -#~ "\n" -#~ " COMMANDS:\n" -#~ " uri Handle AIM: URI\n" -#~ " away Popup the away dialog with the default " -#~ "message\n" -#~ " back Remove the away dialog\n" -#~ " quit Close running copy of Pidgin\n" -#~ "\n" -#~ " OPTIONS:\n" -#~ " -h, --help [command] Show help for command\n" -#~ msgstr "" -#~ "Usage: %s command [OPTIONS] [URI]\n" -#~ "\n" -#~ " COMMANDS:\n" -#~ " uri Handle AIM: URI\n" -#~ " away Pop up the away dialogue with the default " -#~ "message\n" -#~ " back Remove the away dialogue\n" -#~ " quit Close running copy of Pidgin\n" -#~ "\n" -#~ " OPTIONS:\n" -#~ " -h, --help [command] Show help for command\n" - -#~ msgid "" -#~ "Pidgin not running (on session 0)\n" -#~ "Is the \"Remote Control\" plugin loaded?\n" -#~ msgstr "" -#~ "Pidgin not running (on session 0)\n" -#~ "Is the \"Remote Control\" plugin loaded?\n" - -#~ msgid "" -#~ "\n" -#~ "Using AIM: URIs:\n" -#~ "Sending an IM to a screen name:\n" -#~ "\tPidgin-remote uri 'aim:goim?screenname=Penguin&message=hello+world'\n" -#~ "In this case, 'Penguin' is the screen name we wish to IM, and 'hello " -#~ "world'\n" -#~ "is the message to be sent. '+' must be used in place of spaces.\n" -#~ "Please note the quoting used above - if you run this from a shell the " -#~ "'&'\n" -#~ "needs to be escaped, or the command will stop at that point.\n" -#~ "Also,the following will just open a conversation window to a screen " -#~ "name,\n" -#~ "with no message:\n" -#~ "\tPidgin-remote uri 'aim:goim?screenname=Penguin'\n" -#~ "\n" -#~ "Joining a chat:\n" -#~ "\tPidgin-remote uri 'aim:gochat?roomname=PenguinLounge'\n" -#~ "...joins the 'PenguinLounge' chat room.\n" -#~ "\n" -#~ "Adding a buddy to your buddy list:\n" -#~ "\tPidgin-remote uri 'aim:addbuddy?screenname=Penguin'\n" -#~ "...prompts you to add 'Penguin' to your buddy list.\n" -#~ msgstr "" -#~ "\n" -#~ "Using AIM: URIs:\n" -#~ "Sending an IM to a screen name:\n" -#~ "\tPidgin-remote uri 'aim:goim?screenname=Penguin&message=hello+world'\n" -#~ "In this case, 'Penguin' is the screen name we wish to IM, and 'hello " -#~ "world'\n" -#~ "is the message to be sent. '+' must be used in place of spaces.\n" -#~ "Please note the quoting used above - if you run this from a shell the " -#~ "'&'\n" -#~ "needs to be escaped, or the command will stop at that point.\n" -#~ "Also, the following will just open a conversation window to a screen " -#~ "name,\n" -#~ "with no message:\n" -#~ "\tPidgin-remote uri 'aim:goim?screenname=Penguin'\n" -#~ "\n" -#~ "Joining a chat:\n" -#~ "\tPidgin-remote uri 'aim:gochat?roomname=PenguinLounge'\n" -#~ "...joins the 'PenguinLounge' chat room.\n" -#~ "\n" -#~ "Adding a buddy to your buddy list:\n" -#~ "\tPidgin-remote uri 'aim:addbuddy?screenname=Penguin'\n" -#~ "...prompts you to add 'Penguin' to your buddy list.\n" - -#~ msgid "" -#~ "\n" -#~ "Close running copy of Pidgin\n" -#~ msgstr "" -#~ "\n" -#~ "Close running copy of Pidgin\n" - -#~ msgid "" -#~ "\n" -#~ "Mark all accounts as \"away\" with the default message.\n" -#~ msgstr "" -#~ "\n" -#~ "Mark all accounts as \"away\" with the default message.\n" - -#~ msgid "" -#~ "\n" -#~ "Set all accounts as not away.\n" -#~ msgstr "" -#~ "\n" -#~ "Set all accounts as not away.\n" - -#~ msgid "/Tools/Pl_ugin Actions" -#~ msgstr "/Tools/Pl_ugin Actions" - -#~ msgid "Rename Group" -#~ msgstr "Rename Group" - -#~ msgid "New group name" -#~ msgstr "New group name" - -#~ msgid "%d%%" -#~ msgstr "%d%%" - -#~ msgid "" -#~ "\n" -#~ "Account:" -#~ msgstr "" -#~ "\n" -#~ "Account:" - -#~ msgid "Warned (%d%%) " -#~ msgstr "Warned (%d%%) " - -#~ msgid "/Tools/Away" -#~ msgstr "/Tools/Away" - -#~ msgid "Send a message to the selected buddy" -#~ msgstr "Send a message to the selected buddy" - -#~ msgid "_Chat" -#~ msgstr "_Chat" - -#~ msgid "Join a chat room" -#~ msgstr "Join a chat room" - -#~ msgid "_Away" -#~ msgstr "_Away" - -#~ msgid "Set an away message" -#~ msgstr "Set an away message" - -#~ msgid "Done." -#~ msgstr "Done." - -#~ msgid "Signon: " -#~ msgstr "Signon: " - -#~ msgid "Signon" -#~ msgstr "Signon" - -#~ msgid "Cancel All" -#~ msgstr "Cancel All" - -#~ msgid "Reason Unknown." -#~ msgstr "Reason Unknown." - -#~ msgid "Reconnect _All" -#~ msgstr "Reconnect _All" - -#~ msgid "Get Away Msg" -#~ msgstr "Get Away Msg" - -#~ msgid "/Conversation/_Warn..." -#~ msgstr "/Conversation/_Warn..." - -#~ msgid "/Conversation/A_lias..." -#~ msgstr "/Conversation/A_lias..." - -#~ msgid "/Options/Show T_imestamps" -#~ msgstr "/Options/Show T_imestamps" - -#~ msgid "/Conversation/Warn..." -#~ msgstr "/Conversation/Warn..." - -#~ msgid "Send a file to the user" -#~ msgstr "Send a file to the user" - -#~ msgid "Invite a user" -#~ msgstr "Invite a user" - -#~ msgid "
/Conversation/Close" -#~ msgstr "
/Conversation/Close" - -#~ msgid "former lead developer" -#~ msgstr "former lead developer" - -#~ msgid "former maintainer" -#~ msgstr "former maintainer" - -#, fuzzy -#~ msgid "Azerbaijani" -#~ msgstr "Serbian" - -#~ msgid "Burmese" -#~ msgstr "Burmese" - -#~ msgid "Chinese" -#~ msgstr "Chinese" - -#~ msgid "" -#~ "Warn %s?\n" -#~ "\n" -#~ "This will increase %s's warning level and he or she will be subject to " -#~ "harsher rate limiting.\n" -#~ msgstr "" -#~ "Warn %s?\n" -#~ "\n" -#~ "This will increase %s's warning level and he or she will be subject to " -#~ "harsher rate limiting.\n" - -#~ msgid "Warn _anonymously?" -#~ msgstr "Warn _anonymously?" - -#~ msgid "Anonymous warnings are less severe." -#~ msgstr "Anonymous warnings are less severe." - -#~ msgid "Show transfer details" -#~ msgstr "Show transfer details" - -#~ msgid "D_isplay remote nicknames if no alias is set" -#~ msgstr "D_isplay remote nicknames if no alias is set" - -#~ msgid "Show _timestamp on messages" -#~ msgstr "Show _timestamp on messages" - -#~ msgid "Ignore font _faces" -#~ msgstr "Ignore font _faces" - -#~ msgid "_Send default formatting with outgoing messages" -#~ msgstr "_Send default formatting with outgoing messages" - -#~ msgid "Enter _sends message" -#~ msgstr "Enter _sends message" - -#~ msgid "Window Closing" -#~ msgstr "Window Closing" - -#~ msgid "_Escape closes window" -#~ msgstr "_Escape closes window" - -#~ msgid "Insertions" -#~ msgstr "Insertions" - -#~ msgid "Control-{B/I/U} changes _formatting" -#~ msgstr "Control-{B/I/U} changes _formatting" - -#~ msgid "Control-(number) _inserts smileys" -#~ msgstr "Control-(number) _inserts smileys" - -#~ msgid "Show _buttons as:" -#~ msgstr "Show _buttons as:" - -#~ msgid "Pictures and text" -#~ msgstr "Pictures and text" - -#~ msgid "_Raise window on events" -#~ msgstr "_Raise window on events" - -#~ msgid "Show _warning levels" -#~ msgstr "Show _warning levels" - -#~ msgid "Enable \"_slash\" commands" -#~ msgstr "Enable \"_slash\" commands" - -#~ msgid "_Raise IM window on events" -#~ msgstr "_Raise IM window on events" - -#~ msgid "Raise chat _window on events" -#~ msgstr "Raise chat _window on events" - -#~ msgid "Use _multi-colored screen names in chats" -#~ msgstr "Use _multi-coloured screen names in chats" - -#~ msgid "Tab p_lacement:" -#~ msgstr "Tab p_lacement:" - -#~ msgid "New conversation _placement:" -#~ msgstr "New conversation _placement:" - -#~ msgid "System Logs" -#~ msgstr "System Logs" - -#~ msgid "_Enable system log" -#~ msgstr "_Enable system log" - -#~ msgid "Log when buddies _sign on/sign off" -#~ msgstr "Log when buddies _sign on/sign off" - -#~ msgid "Log when buddies become _idle/un-idle" -#~ msgstr "Log when buddies become _idle/un-idle" - -#~ msgid "Log when buddies go away/come _back" -#~ msgstr "Log when buddies go away/come _back" - -#~ msgid "Log your _own signons/idleness/awayness" -#~ msgstr "Log your _own signons/idleness/awayness" - -#~ msgid "Idle _time reporting:" -#~ msgstr "Idle _time reporting:" - -#~ msgid "Pidgin usage" -#~ msgstr "Pidgin usage" - -#~ msgid "X usage" -#~ msgstr "X usage" - -#~ msgid "Windows usage" -#~ msgstr "Windows usage" - -#~ msgid "" -#~ "%s %s\n" -#~ "\n" -#~ "Written by: %s\n" -#~ "URL: %s\n" -#~ "File name: %s" -#~ msgstr "" -#~ "%s %s\n" -#~ "\n" -#~ "Written by: %s\n" -#~ "URL: %s\n" -#~ "File name: %s" - -#~ msgid "Summary" -#~ msgstr "Summary" - -#~ msgid "Away Messages" -#~ msgstr "Away Messages" - -#~ msgid "Please create an account." -#~ msgstr "Please create an account." - -#~ msgid "_Account:" -#~ msgstr "_Account:" - -#~ msgid "A_ccounts" -#~ msgstr "A_ccounts" - -#~ msgid "P_references" -#~ msgstr "P_references" - -#~ msgid "_Sign on" -#~ msgstr "_Sign on" - -#~ msgid "" -#~ "Pidgin %s\n" -#~ "Usage: %s [OPTION]...\n" -#~ "\n" -#~ " -a, --acct display account editor window\n" -#~ " -w, --away[=MESG] make away on signon (optional argument MESG " -#~ "specifies\n" -#~ " name of away message to use)\n" -#~ " -l, --login[=NAME] automatically login (optional argument NAME " -#~ "specifies\n" -#~ " account(s) to use, separated by commas)\n" -#~ " -n, --loginwin don't automatically login; show login window\n" -#~ " -u, --user=NAME use account NAME\n" -#~ " -c, --config=DIR use DIR for config files\n" -#~ " -d, --debug print debugging messages to stdout\n" -#~ " -v, --version display the current version and exit\n" -#~ " -h, --help display this help and exit\n" -#~ msgstr "" -#~ "Pidgin %s\n" -#~ "Usage: %s [OPTION]...\n" -#~ "\n" -#~ " -a, --acct display account editor window\n" -#~ " -w, --away[=MESG] make away on signon (optional argument MESG " -#~ "specifies\n" -#~ " name of away message to use)\n" -#~ " -l, --login[=NAME] automatically log in (optional argument NAME " -#~ "specifies\n" -#~ " account(s) to use, separated by commas)\n" -#~ " -n, --loginwin do not automatically log in; show login window\n" -#~ " -u, --user=NAME use account NAME\n" -#~ " -c, --config=DIR use DIR for config files\n" -#~ " -d, --debug print debugging messages to stdout\n" -#~ " -v, --version display the current version and exit\n" -#~ " -h, --help display this help and exit\n" - -#~ msgid "Unable to load preferences" -#~ msgstr "Unable to load preferences" - -#~ msgid "" -#~ "Pidgin was not able to load your preferences because they are stored in " -#~ "an old format that is no longer used. Please reconfigure your settings " -#~ "using the Preferences window." -#~ msgstr "" -#~ "Pidgin was not able to load your preferences because they are stored in " -#~ "an old format that is no longer used. Please reconfigure your settings " -#~ "using the Preferences window." - -#~ msgid "Slightly less boring default" -#~ msgstr "Slightly less boring default" - -#~ msgid "Available for friends only" -#~ msgstr "Available for friends only" - -#~ msgid "Away for friends only" -#~ msgstr "Away for friends only" - -#~ msgid "Invisible for friends only" -#~ msgstr "Invisible for friends only" - -#~ msgid "Error while writing to socket." -#~ msgstr "Error while writing to socket." - -#~ msgid "Authentication failed." -#~ msgstr "Authentication failed." - -#~ msgid "Unknown Error Code." -#~ msgstr "Unknown Error Code." - -#~ msgid "Balancer handshake" -#~ msgstr "Balancer handshake" - -#~ msgid "Reading server key" -#~ msgstr "Reading server key" - -#~ msgid "Exchanging key hash" -#~ msgstr "Exchanging key hash" - -#~ msgid "Critical error in GG library\n" -#~ msgstr "Critical error in GG library\n" - -#~ msgid "Send as message" -#~ msgstr "Send as message" - -#~ msgid "Looking up GG server" -#~ msgstr "Looking up GG server" - -#~ msgid "Invalid Gadu-Gadu UIN specified" -#~ msgstr "Invalid Gadu-Gadu UIN specified" - -#~ msgid "You are trying to send a message to an invalid Gadu-Gadu UIN." -#~ msgstr "You are trying to send a message to an invalid Gadu-Gadu UIN." - -#~ msgid "Couldn't get search results" -#~ msgstr "Couldn't get search results" - -#~ msgid "Sex" -#~ msgstr "Sex" - -#~ msgid "Buddy List successfully transferred to Gadu-Gadu server" -#~ msgstr "Buddy List successfully transferred to Gadu-Gadu server" - -#~ msgid "Couldn't transfer Buddy List to Gadu-Gadu server" -#~ msgstr "Couldn't transfer Buddy List to Gadu-Gadu server" - -#~ msgid "Buddy List successfully deleted from Gadu-Gadu server" -#~ msgstr "Buddy List successfully deleted from Gadu-Gadu server" - -#~ msgid "Couldn't delete Buddy List from Gadu-Gadu server" -#~ msgstr "Couldn't delete Buddy List from Gadu-Gadu server" - -#~ msgid "Password couldn't be changed" -#~ msgstr "Password couldn't be changed" - -#~ msgid "Error communicating with Gadu-Gadu server" -#~ msgstr "Error communicating with Gadu-Gadu server" - -#~ msgid "" -#~ "Pidgin was unable to complete your request due to a problem communicating " -#~ "with the Gadu-Gadu HTTP server. Please try again later." -#~ msgstr "" -#~ "Pidgin was unable to complete your request due to a problem communicating " -#~ "with the Gadu-Gadu HTTP server. Please try again later." - -#~ msgid "Unable to import Gadu-Gadu buddy list" -#~ msgstr "Unable to import Gadu-Gadu buddy list" - -#~ msgid "" -#~ "Pidgin was unable to connect to the Gadu-Gadu buddy list server. Please " -#~ "try again later." -#~ msgstr "" -#~ "Pidgin was unable to connect to the Gadu-Gadu buddy list server. Please " -#~ "try again later." - -#~ msgid "Unable to delete Gadu-Gadu buddy list" -#~ msgstr "Unable to delete Gadu-Gadu buddy list" - -#~ msgid "Unable to access directory" -#~ msgstr "Unable to access directory" - -#~ msgid "" -#~ "Pidgin was unable to search the Directory because it was unable to " -#~ "connect to the directory server. Please try again later." -#~ msgstr "" -#~ "Pidgin was unable to search the Directory because it was unable to " -#~ "connect to the directory server. Please try again later." - -#~ msgid "" -#~ "Pidgin was unable to change your password due to an error connecting to " -#~ "the Gadu-Gadu server. Please try again later." -#~ msgstr "" -#~ "Pidgin was unable to change your password due to an error connecting to " -#~ "the Gadu-Gadu server. Please try again later." - -#~ msgid "Directory Search" -#~ msgstr "Directory Search" - -#~ msgid "Unable to access user profile." -#~ msgstr "Unable to access user profile." - -#~ msgid "" -#~ "Pidgin was unable to access this user's profile due to an error " -#~ "connecting to the directory server. Please try again later." -#~ msgstr "" -#~ "Pidgin was unable to access this user's profile due to an error " -#~ "connecting to the directory server. Please try again later." - -#~ msgid "Pidgin encountered an error communicating with the ICQ server." -#~ msgstr "Pidgin encountered an error communicating with the ICQ server." - -#~ msgid "The user %s (%s%s%s%s%s) wants you to authorize them." -#~ msgstr "The user %s (%s%s%s%s%s) wants you to authorize them." - -#~ msgid "Send message through server" -#~ msgstr "Send message through server" - -#~ msgid "Nick:" -#~ msgstr "Nick:" - -#~ msgid "Pidgin User" -#~ msgstr "Pidgin User" - -#~ msgid "File Transfer Aborted" -#~ msgstr "File Transfer Aborted" - -#~ msgid "Buddy Information for %s" -#~ msgstr "Buddy Information for %s" - -#, fuzzy -#~ msgid "Invalid nickname '%s'" -#~ msgstr "Invalid Username" - -#~ msgid "Roomlist Error" -#~ msgstr "Roomlist Error" - -#~ msgid "Display conversation closed notices" -#~ msgstr "Display conversation closed notices" - -#~ msgid "The conversation has become inactive and timed out." -#~ msgstr "The conversation has become inactive and timed out." - -#~ msgid "" -#~ "You were disconnected from the server, because you logged on from a " -#~ "different location" -#~ msgstr "" -#~ "You were disconnected from the server, because you logged on from a " -#~ "different location" - -#~ msgid "User Properties" -#~ msgstr "User Properties" - -#, fuzzy -#~ msgid "Transfer of file %s timed out." -#~ msgstr "Transfer of file %s complete" - -#~ msgid "" -#~ "You have been disconnected because you have signed on with this screen " -#~ "name at another location." -#~ msgstr "" -#~ "You have been disconnected because you have signed on with this screen " -#~ "name at another location." - -#~ msgid "Not specified" -#~ msgstr "Not specified" - -#~ msgid "ICQ Info for %s" -#~ msgstr "ICQ Info for %s" - -#~ msgid "" -#~ "Error 0x%04x: Unable to format screen name because the requested screen " -#~ "name ends in a space." -#~ msgstr "" -#~ "Error 0x%04x: Unable to format screen name because the requested screen " -#~ "name ends in a space." - -#~ msgid "I'm doing work and hoping for a distraction--IM me!" -#~ msgstr "I'm doing work and hoping for a distraction--IM me!" - -#~ msgid "Set Available Message..." -#~ msgstr "Set Available Message..." - -#~ msgid "Failed to leave channel" -#~ msgstr "Failed to leave channel" - -#~ msgid "Basic Profile" -#~ msgstr "Basic Profile" - -#~ msgid "AIM" -#~ msgstr "AIM" - -#~ msgid "Yahoo" -#~ msgstr "Yahoo" - -#~ msgid "I'm From" -#~ msgstr "I'm From" - -#~ msgid "Set your Trepia profile data." -#~ msgstr "Set your Trepia profile data." - -#~ msgid "Visit Homepage" -#~ msgstr "Visit Homepage" - -#~ msgid "Local Users" -#~ msgstr "Local Users" - -#~ msgid "Trepia Protocol Plugin" -#~ msgstr "Trepia Protocol Plugin" - -#~ msgid "" -#~ "You have been logged off as you have logged in on a different machine or " -#~ "device." -#~ msgstr "" -#~ "You have been logged off as you have logged in on a different machine or " -#~ "device." - -#~ msgid "Please enter your password" -#~ msgstr "Please enter your password" - -#~ msgid "%s logged in." -#~ msgstr "%s logged in." - -#~ msgid "" -#~ "%s has just been warned by %s.\n" -#~ "Your new warning level is %d%%" -#~ msgstr "" -#~ "%s has just been warned by %s.\n" -#~ "Your new warning level is %d%%" - -#~ msgid "an anonymous person" -#~ msgstr "an anonymous person" - -#~ msgid "" -#~ "%s has invited %s to the chat room %s:\n" -#~ "%s" -#~ msgstr "" -#~ "%s has invited %s to the chat room %s:\n" -#~ "%s" - -#~ msgid "" -#~ "Unable to guess the image type based on the file extension supplied. " -#~ "Defaulting to PNG." -#~ msgstr "" -#~ "Unable to guess the image type based on the file extension supplied. " -#~ "Defaulting to PNG." - -#~ msgid "SILC Public Key" -#~ msgstr "SILC Public Key" - -#~ msgid "SILC Private Key" -#~ msgstr "SILC Private Key" diff -r ea4bb5fe1fdc -r 0d4702446530 po/fr.po --- a/po/fr.po Thu May 05 03:40:29 2011 +0000 +++ b/po/fr.po Mon May 09 04:26:46 2011 +0000 @@ -21,8 +21,8 @@ msgstr "" "Project-Id-Version: Pidgin\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2011-01-30 21:28+0100\n" -"PO-Revision-Date: 2011-01-30 21:14+0100\n" +"POT-Creation-Date: 2011-05-06 19:19+0200\n" +"PO-Revision-Date: 2011-05-06 19:16+0200\n" "Last-Translator: Éric Boumaour \n" "Language-Team: fr \n" "MIME-Version: 1.0\n" @@ -229,6 +229,9 @@ msgid "Alias (optional)" msgstr "Alias (facultatif)`" +msgid "Invite message (optional)" +msgstr "Message d'invitation (facultatif)" + msgid "Add in group" msgstr "Ajouter au groupe" @@ -1952,6 +1955,9 @@ msgid "Unknown reason" msgstr "Raison inconnue" +msgid "Aborting DNS lookup in Tor Proxy mode." +msgstr "Annulation de la recherche DNS en mode Proxy Tor." + #, c-format msgid "" "Error reading %s: \n" @@ -3214,6 +3220,21 @@ msgid "Change Gadu-Gadu Password" msgstr "Changer le le mot de passe Gadu-Gadu" +msgid "Show status to:" +msgstr "Montrer l'état à :" + +msgid "All people" +msgstr "Tout le monde" + +msgid "Only buddies" +msgstr "Aux contacts" + +msgid "Change status broadcasting" +msgstr "Changer la diffusion de l'état" + +msgid "Please, select who can see your status" +msgstr "Veuillez choisir qui peut voir votre état" + #, c-format msgid "Select a chat for buddy: %s" msgstr "Choisissez un salon de discussions pour le contact : %s" @@ -3246,9 +3267,7 @@ msgstr "UIN" #. first name -#. purple_notify_user_info_add_pair( info, _( "Hidden Number" ), profile->hidden ? _( "Yes" ) : _( "No" ) ); #. optional information -#. purple_notify_user_info_add_pair( info, _( "Title" ), profile->title ); msgid "First Name" msgstr "Prénom" @@ -3360,6 +3379,19 @@ msgid "GG server" msgstr "Serveur GG" +msgid "Don't use encryption" +msgstr "Ne pas utiliser de chiffrement" + +msgid "Use encryption if available" +msgstr "Utiliser le chiffrement si disponible" + +#. TODO +msgid "Require encryption" +msgstr "Nécessite chiffrement" + +msgid "Connection security" +msgstr "Sécurité de la connexion" + #, c-format msgid "Unknown command: %s" msgstr "Commande inconnue : %s" @@ -3395,7 +3427,6 @@ #. * buffer that stores what is "being sent" until the #. * PurpleHTTPConnection reports it is fully sent. #. -#. TODO: what to do here - do we really have to disconnect? #. TODO: do we really want to disconnect on a failure to write? #, c-format msgid "Lost connection with server: %s" @@ -3651,6 +3682,9 @@ msgid "action <action to perform>: Perform an action." msgstr "action <action à faire> : Réaliser une action." +msgid "authserv: Send a command to authserv" +msgstr "authserv : Envoyer une commande au service authserv." + msgid "" "away [message]: Set an away message, or use no message to return from being " "away." @@ -4014,7 +4048,6 @@ msgid "Postal Code" msgstr "Code postal" -#. purple_notify_user_info_add_pair( info, _( "Email" ), profile->email ); msgid "Country" msgstr "Pays" @@ -4788,18 +4821,9 @@ msgid "Domain" msgstr "Domaine" -msgid "Require encryption" -msgstr "Nécessite chiffrement" - -msgid "Use encryption if available" -msgstr "Utiliser le chiffrement si disponible" - msgid "Use old-style SSL" msgstr "Utiliser le SSL ancien style" -msgid "Connection security" -msgstr "Sécurité de la connexion" - msgid "Allow plaintext auth over unencrypted streams" msgstr "Autoriser l'authentification en clair pour les flux cryptés" @@ -4911,6 +4935,7 @@ "Impossible d'envoyer le fichier à %s, cet utilisateur ne supporte pas le " "transfert de fichiers" +#. not success msgid "File Send Failed" msgstr "Échec d'envoi de fichier" @@ -5636,18 +5661,6 @@ msgid "Unable to Add" msgstr "Impossible d'ajouter" -msgid "Authorization Request Message:" -msgstr "Message pour la demande d'autorisation :" - -msgid "Please authorize me!" -msgstr "Autorise moi, s'il te plaît !" - -#. * -#. * A wrapper for purple_request_action() that uses @c OK and @c Cancel buttons. -#. -msgid "_OK" -msgstr "_OK" - msgid "Error retrieving profile" msgstr "Erreur à la récupération du profil." @@ -5859,6 +5872,9 @@ msgid "Mobile message was not sent because it was too long." msgstr "Le message mobile n'a pas été envoyé parce qu'il est trop long." +msgid "Mobile message was not sent because an unknown error occurred." +msgstr "Le message mobile n'a pas été envoyé à cause d'une erreur inconnue." + #, c-format msgid "" "The MSN server will shut down for maintenance in %d minute. You will " @@ -6023,19 +6039,6 @@ msgid "The username specified is invalid." msgstr "Le nom d'utilisateur fourni est non valide." -msgid "The PIN you entered is invalid." -msgstr "Le code d'accès est non valide." - -msgid "The PIN you entered has an invalid length [4-10]." -msgstr "Le code d'accès n'a pas la bonne longueur [4-10]." - -msgid "The PIN is invalid. It should only consist of digits [0-9]." -msgstr "" -"Le code d'accès est non valide. Il doit être uniquement composé de chiffres." - -msgid "The two PINs you entered do not match." -msgstr "Les nouveaux codes d'accès diffèrent." - msgid "The Display Name you entered is invalid." msgstr "Le nom à afficher saisi est non valide." @@ -6058,35 +6061,66 @@ "Les informations de votre profil n'ont pu être récupérées. Veuillez " "réessayer plus tard." -msgid "Your UID" -msgstr "Votre UID" +#. display name +#. nick name (required) +msgid "Display Name" +msgstr "Nom affiché" + +#. about me +msgid "About Me" +msgstr "À propos de moi" + +#. where I live +msgid "Where I Live" +msgstr "Où je vis" + +#. mobile number +msgid "Mobile Number" +msgstr "Téléphone portable" + +#. is searchable +msgid "Can be searched" +msgstr "Peut être recherché" + +#. is suggestable +msgid "Can be suggested" +msgstr "Peut être suggéré" + +msgid "Update your MXit Profile" +msgstr "Mettre à jour votre profil MXit" + +msgid "The PIN you entered is invalid." +msgstr "Le code d'accès est non valide." + +msgid "The PIN you entered has an invalid length [4-10]." +msgstr "Le code d'accès n'a pas la bonne longueur [4-10]." + +msgid "The PIN is invalid. It should only consist of digits [0-9]." +msgstr "" +"Le code d'accès est non valide. Il doit être uniquement composé de chiffres." + +msgid "The two PINs you entered do not match." +msgstr "Les nouveaux codes d'accès diffèrent." + +#. show error to user +msgid "PIN Update Error" +msgstr "Erreur à la mise à jour du code PIN" #. pin #. pin (required) msgid "PIN" msgstr "Code" +#. verify pin msgid "Verify PIN" msgstr "Vérification code" -#. display name -#. nick name (required) -msgid "Display Name" -msgstr "Nom affiché" - -#. hidden -msgid "Hide my number" -msgstr "Cacher mon numéro" - -#. mobile number -msgid "Mobile Number" -msgstr "Téléphone portable" - -msgid "Update your Profile" -msgstr "Mettre à jour votre profil" - -msgid "Here you can update your MXit profile" -msgstr "Vous pouvez mettre à jour votre profil MXit ici" +#. (reference: "libpurple/request.h") +msgid "Change PIN" +msgstr "Changer le code PIN" + +msgid "Change MXit PIN" +msgstr "Changer le code PIN MXit" msgid "View Splash" msgstr "Voir la bannière" @@ -6097,10 +6131,34 @@ msgid "About" msgstr "À propos" +msgid "Search for user" +msgstr "Rechercher un utilisateur" + +msgid "Search for a MXit contact" +msgstr "Rechercher un contact MXit" + +msgid "Type search information" +msgstr "Saisissez les informations de recherche" + +msgid "_Search" +msgstr "_Recherche" + #. display / change profile msgid "Change Profile..." msgstr "Changer le profil..." +#. change PIN +msgid "Change PIN..." +msgstr "Changer le code PIN..." + +#. suggested friends +msgid "Suggested friends..." +msgstr "Suggérer des amis..." + +#. search for contacts +msgid "Search for contacts..." +msgstr "Chercher des contacts..." + #. display splash-screen msgid "View Splash..." msgstr "Voir la bannière..." @@ -6131,6 +6189,9 @@ msgid "Connecting..." msgstr "Connexion..." +msgid "The Display Name you entered is too short." +msgstr "Le nom à afficher saisi est trop court." + msgid "The PIN you entered has an invalid length [7-10]." msgstr "Le code d'accès saisi n'a pas la bonne taille [7-10]." @@ -6205,13 +6266,12 @@ msgid "Retrieving User Information..." msgstr "Récupération des informations de l'utilisateur..." -#. you were kicked +msgid "was kicked" +msgstr "a été expulsé" + msgid "You have been kicked from this MultiMX." msgstr "Vous avez été expulsé de ce MultiMX." -msgid "was kicked" -msgstr "a été expulsé" - msgid "_Room Name:" msgstr "_Salon :" @@ -6232,9 +6292,19 @@ msgid "Hidden Number" msgstr "Numéro caché" +msgid "No profile available" +msgstr "Aucun profil disponible" + +msgid "This contact does not have a profile." +msgstr "Ce contact n'a pas de profil." + msgid "Your MXit ID..." msgstr "Votre identifiant MXitId..." +#. contact is in Deleted, Rejected or None state +msgid "Re-Invite" +msgstr "Ré-inviter" + #. Configuration options #. WAP server (reference: "libpurple/accountopt.h") msgid "WAP Server" @@ -6249,6 +6319,30 @@ msgid "Last Online" msgstr "En ligne dernièrement" +msgid "Invite Message" +msgstr "Message d'invitation" + +msgid "No results" +msgstr "Aucun résultat" + +msgid "No contacts found." +msgstr "Aucun utilisateur trouvé." + +#. define columns +msgid "UserId" +msgstr "ID d'utilisateur" + +msgid "Where I live" +msgstr "Où je vis" + +#, c-format +msgid "You have %i suggested friends." +msgstr "Vous avez %i amis suggérés." + +#, c-format +msgid "We found %i contacts that match your search." +msgstr "%i contacts correspondent à votre recherche." + #. we must have lost the connection, so terminate it so that we can reconnect msgid "We have lost the connection to MXit. Please reconnect." msgstr "Connexion perdue avec MXit. Veuillez vous reconnecter." @@ -6988,6 +7082,12 @@ msgid "Authorization Denied Message:" msgstr "Message de refus d'autorisation :" +#. * +#. * A wrapper for purple_request_action() that uses @c OK and @c Cancel buttons. +#. +msgid "_OK" +msgstr "_OK" + #, c-format msgid "Received unexpected response from %s: %s" msgstr "Réception d'une réponse non attendue de %s : %s" @@ -7346,7 +7446,6 @@ msgstr "Autorisation reçue." #. Unregistered username -#. uid is not exist #. the username does not exist msgid "Username does not exist" msgstr "Cet utilisateur n'existe pas" @@ -7529,6 +7628,14 @@ msgid "You have been disconnected from chat room %s." msgstr "Vous avez été déconnecté du salon %s" +msgid "The new formatting is invalid." +msgstr "Le nouvel affichage est non valide" + +msgid "Username formatting can change only capitalization and whitespace." +msgstr "" +"Le format d'affichage du nom d'utilisateur permet uniquement de changer les " +"majuscules et les espaces." + msgid "Pop-Up Message" msgstr "Message en fenêtre" @@ -7802,14 +7909,6 @@ msgid "ICQ Privacy Options" msgstr "Options de confidentialité ICQ" -msgid "The new formatting is invalid." -msgstr "Le nouvel affichage est non valide" - -msgid "Username formatting can change only capitalization and whitespace." -msgstr "" -"Le format d'affichage du nom d'utilisateur permet uniquement de changer les " -"majuscules et les espaces." - msgid "Change Address To:" msgstr "Nouvelle adresse :" @@ -7835,9 +7934,6 @@ msgid "Type the email address of the buddy you are searching for." msgstr "Saisissez l'adresse électronique du contact que vous cherchez" -msgid "_Search" -msgstr "_Recherche" - msgid "Set User Info (web)..." msgstr "Modifier les informations (web)..." @@ -7874,9 +7970,6 @@ msgid "Search for Buddy by Email Address..." msgstr "Chercher un contact par adresse électronique..." -msgid "Don't use encryption" -msgstr "Ne pas utiliser de chiffrement" - msgid "Use clientLogin" msgstr "Utiliser clientLogin" @@ -8151,717 +8244,6 @@ msgid "These buddies will always see you as offline" msgstr "Ces contacts ne vous verront jamais connectés" -msgid "Aquarius" -msgstr "Verseau" - -msgid "Pisces" -msgstr "Poissons" - -msgid "Aries" -msgstr "Bélier" - -msgid "Taurus" -msgstr "Taureau" - -msgid "Gemini" -msgstr "Gémeaux" - -msgid "Cancer" -msgstr "Cancer" - -msgid "Leo" -msgstr "Lion" - -msgid "Virgo" -msgstr "Vierge" - -msgid "Libra" -msgstr "Balance" - -msgid "Scorpio" -msgstr "Scorpion" - -msgid "Sagittarius" -msgstr "Sagittaire" - -msgid "Capricorn" -msgstr "Capricorne" - -msgid "Rat" -msgstr "Rat" - -msgid "Ox" -msgstr "Bœuf" - -msgid "Tiger" -msgstr "Tigre" - -msgid "Rabbit" -msgstr "Lièvre" - -msgid "Dragon" -msgstr "Dragon" - -msgid "Snake" -msgstr "Serpent" - -msgid "Horse" -msgstr "Cheval" - -msgid "Goat" -msgstr "Chèvre" - -msgid "Monkey" -msgstr "Singe" - -msgid "Rooster" -msgstr "Coq" - -msgid "Dog" -msgstr "Chien" - -msgid "Pig" -msgstr "Cochon" - -msgid "Other" -msgstr "Autre" - -msgid "Visible" -msgstr "Visible" - -msgid "Friend Only" -msgstr "Amis seulement" - -msgid "Private" -msgstr "Privé" - -msgid "QQ Number" -msgstr "Numéro QQ" - -msgid "Country/Region" -msgstr "Pays/région" - -msgid "Province/State" -msgstr "Province/État" - -msgid "Zipcode" -msgstr "Code postal" - -msgid "Phone Number" -msgstr "Téléphone fixe" - -msgid "Authorize adding" -msgstr "Autoriser l'ajout" - -msgid "Cellphone Number" -msgstr "Téléphone portable" - -msgid "Personal Introduction" -msgstr "Informations personnelles" - -msgid "City/Area" -msgstr "Ville/Localité" - -msgid "Publish Mobile" -msgstr "Publier le téléphone portable" - -msgid "Publish Contact" -msgstr "Publier les informations de contact" - -msgid "College" -msgstr "Éducation" - -msgid "Horoscope" -msgstr "Signe du zodiaque" - -msgid "Zodiac" -msgstr "Signe du zodiaque chinois" - -msgid "Blood" -msgstr "Groupe sanguin" - -msgid "True" -msgstr "Vrai" - -msgid "False" -msgstr "Faux" - -msgid "Modify Contact" -msgstr "Modifier les infos de contact" - -msgid "Modify Address" -msgstr "Modifier l'adresse" - -msgid "Modify Extended Information" -msgstr "Modifier mes infos étendues" - -msgid "Modify Information" -msgstr "Modifier mes informations" - -msgid "Update" -msgstr "Mettre à jour" - -msgid "Could not change buddy information." -msgstr "Impossible de changer les informations du contact." - -msgid "Note" -msgstr "Commentaire" - -#. callback -msgid "Buddy Memo" -msgstr "Mémo du contact" - -msgid "Change his/her memo as you like" -msgstr "Vous pouvez changer son mémo à votre convenance" - -msgid "_Modify" -msgstr "_Modifier" - -msgid "Memo Modify" -msgstr "Changer mémo" - -msgid "Server says:" -msgstr "Message du serveur :" - -msgid "Your request was accepted." -msgstr "Votre requête a été acceptée." - -msgid "Your request was rejected." -msgstr "Votre requête a été rejetée." - -#, c-format -msgid "%u requires verification: %s" -msgstr "%u demande une vérification : %s" - -msgid "Add buddy question" -msgstr "Ajouter une question pour les nouveaux contacts" - -msgid "Enter answer here" -msgstr "Saisissez la réponse ici" - -msgid "Send" -msgstr "Envoyer" - -msgid "Invalid answer." -msgstr "Réponse non valide." - -msgid "Authorization denied message:" -msgstr "Message de refus d'autorisation :" - -msgid "Sorry, you're not my style." -msgstr "Désolé, tu n'es pas mon genre." - -#, c-format -msgid "%u needs authorization" -msgstr "%u demande une autorisation" - -msgid "Add buddy authorize" -msgstr "Ajouter une autorisation de contact" - -msgid "Enter request here" -msgstr "Saisissez votre demande" - -msgid "Would you be my friend?" -msgstr "Veux-tu être mon ami ?" - -msgid "QQ Buddy" -msgstr "Contact QQ" - -msgid "Add buddy" -msgstr "Ajouter un contact" - -msgid "Invalid QQ Number" -msgstr "Numéro QQ non valide" - -msgid "Failed sending authorize" -msgstr "Échec à l'envoi de l'autorisation" - -#, c-format -msgid "Failed removing buddy %u" -msgstr "Échec lors de la suppression du contact %u" - -#, c-format -msgid "Failed removing me from %d's buddy list" -msgstr "Échec lors de ma suppression de la liste de %d" - -msgid "No reason given" -msgstr "Pas de raison donnée" - -#. only need to get value -#, c-format -msgid "You have been added by %s" -msgstr "Vous avez été ajouté par %s." - -msgid "Would you like to add him?" -msgstr "Voulez-vous l'ajouter ?" - -#, c-format -msgid "Rejected by %s" -msgstr "Refusé par %s" - -#, c-format -msgid "Message: %s" -msgstr "Message : %s" - -msgid "ID: " -msgstr "ID : " - -msgid "Group ID" -msgstr "ID du groupe" - -msgid "QQ Qun" -msgstr "QQ Qun" - -msgid "Please enter Qun number" -msgstr "Saisissez le numéro Qun" - -msgid "You can only search for permanent Qun\n" -msgstr "Vous ne pouvez chercher que les Qun permanents.\n" - -msgid "(Invalid UTF-8 string)" -msgstr "(Chaine de caractères UTF-8 non valide)" - -msgid "Not member" -msgstr "Non membre" - -msgid "Member" -msgstr "Membre" - -msgid "Requesting" -msgstr "Demande en cours" - -msgid "Admin" -msgstr "Admin" - -#. XXX: Should this be "Topic"? -msgid "Room Title" -msgstr "Titre du salon" - -msgid "Notice" -msgstr "Envoi d'infos" - -msgid "Detail" -msgstr "Détail" - -msgid "Creator" -msgstr "Créateur" - -msgid "About me" -msgstr "À mon propos" - -msgid "Category" -msgstr "Catégorie" - -msgid "The Qun does not allow others to join" -msgstr "Ce Qun est fermé aux inscriptions" - -msgid "Join QQ Qun" -msgstr "Rejoindre un Qun QQ" - -msgid "Input request here" -msgstr "Saisissez votre demande" - -#, c-format -msgid "Successfully joined Qun %s (%u)" -msgstr "Entrée réussie dans le Qun %s (%u)" - -msgid "Successfully joined Qun" -msgstr "Entrée réussie dans le Qun" - -#, c-format -msgid "Qun %u denied from joining" -msgstr "L'entrée dans le Qun %u a été refusée" - -msgid "QQ Qun Operation" -msgstr "Opération QQ Qun" - -msgid "Failed:" -msgstr "Échec :" - -msgid "Join Qun, Unknown Reply" -msgstr "Joindre un Qun, réponse inconnue" - -msgid "Quit Qun" -msgstr "Parir du Qun" - -msgid "" -"Note, if you are the creator, \n" -"this operation will eventually remove this Qun." -msgstr "" -"Note : si vous en êtes le créateur, \n" -"cette opération peut supprimer ce Qun." - -msgid "Sorry, you are not our style" -msgstr "Désolés, tu n'es pas notre genre." - -msgid "Successfully changed Qun members" -msgstr "Vous avez modifié la liste des membres du Qun." - -msgid "Successfully changed Qun information" -msgstr "Vous avez modifié les informations du Qun." - -msgid "You have successfully created a Qun" -msgstr "Vous avez créé un Qun." - -msgid "Would you like to set up detailed information now?" -msgstr "Voulez-vous modifier les infos détaillées maintenant ?" - -msgid "Setup" -msgstr "Options" - -#, c-format -msgid "%u requested to join Qun %u for %s" -msgstr "L'utilisateur %u demande à rejoindre le Qun %u pour %s" - -#, c-format -msgid "%u request to join Qun %u" -msgstr "L'utilisateur %u demande à rejoindre le Qun %u" - -#, c-format -msgid "Failed to join Qun %u, operated by admin %u" -msgstr "Échec pour rejoindre le Qun %u, administré par %u" - -#, c-format -msgid "Joining Qun %u is approved by admin %u for %s" -msgstr "L'entrée dans le Qun %u a été approuvée par l'admin %u pour %s" - -#, c-format -msgid "Removed buddy %u." -msgstr "Contact supprimé %u." - -#, c-format -msgid "New buddy %u joined." -msgstr "Nouveau contact %u entré." - -#, c-format -msgid "Unknown-%d" -msgstr "Inconnu-%d" - -msgid "Level" -msgstr "Niveau" - -msgid " VIP" -msgstr " VIP" - -msgid " TCP" -msgstr " TCP" - -msgid " FromMobile" -msgstr " FromMobile" - -msgid " BindMobile" -msgstr " BindMobile" - -msgid " Video" -msgstr " Vidéo" - -msgid " Zone" -msgstr " Zone" - -msgid "Flag" -msgstr "Drapeau" - -msgid "Ver" -msgstr "Ver" - -msgid "Invalid name" -msgstr "Nom d'utilisateur non valide" - -msgid "Select icon..." -msgstr "Choisir une icône..." - -#, c-format -msgid "Login time: %d-%d-%d, %d:%d:%d
\n" -msgstr "Heure de connexion : %d-%d-%d, %d:%d:%d
\n" - -#, c-format -msgid "Total Online Buddies: %d
\n" -msgstr "Contacts connectés : %d
\n" - -#, c-format -msgid "Last Refresh: %d-%d-%d, %d:%d:%d
\n" -msgstr "Dernière mise à jour : %d-%d-%d, %d:%d:%d
\n" - -#, c-format -msgid "Server: %s
\n" -msgstr "Serveur : %s
\n" - -#, c-format -msgid "Client Tag: %s
\n" -msgstr "Étiquette du client : %s
\n" - -#, c-format -msgid "Connection Mode: %s
\n" -msgstr "Type de connexion : %s
\n" - -#, c-format -msgid "My Internet IP: %s:%d
\n" -msgstr "Adresse internet IP : %s:%d
\n" - -#, c-format -msgid "Sent: %lu
\n" -msgstr "Envoyés : %lu
\n" - -#, c-format -msgid "Resend: %lu
\n" -msgstr "Ré-envoyés : %lu
\n" - -#, c-format -msgid "Lost: %lu
\n" -msgstr "Perdus : %lu
\n" - -#, c-format -msgid "Received: %lu
\n" -msgstr "Reçus : %lu
\n" - -#, c-format -msgid "Received Duplicate: %lu
\n" -msgstr "Doubles reçus : %lu
\n" - -#, c-format -msgid "Time: %d-%d-%d, %d:%d:%d
\n" -msgstr "Heure : %d-%d-%d, %d:%d:%d
\n" - -#, c-format -msgid "IP: %s
\n" -msgstr "IP : %s
\n" - -msgid "Login Information" -msgstr "Informations de connexion" - -msgid "

Original Author:
\n" -msgstr "

Auteur original :
\n" - -msgid "

Code Contributors:
\n" -msgstr "

Contributeurs au code :
\n" - -msgid "

Lovely Patch Writers:
\n" -msgstr "

Charmants contributeurs de patchs :
\n" - -msgid "

Acknowledgement:
\n" -msgstr "

Remerciements :
\n" - -msgid "

Scrupulous Testers:
\n" -msgstr "

Testeurs scrupuleux :
\n" - -msgid "and more, please let me know... thank you!))" -msgstr "et d'autres, faites-nous le savoir... merci !" - -msgid "

And, all the boys in the backroom...
\n" -msgstr "

et toutes les personnes dans les coulisses...
\n" - -msgid "Feel free to join us! :)" -msgstr "N'hésitez pas à nous rejoindre ! :)" - -#, c-format -msgid "About OpenQ %s" -msgstr "À propos de OpenQ %s" - -msgid "Change Icon" -msgstr "Changer l'icône" - -msgid "Change Password" -msgstr "Changer de mot de passe" - -msgid "Account Information" -msgstr "Informations du compte" - -msgid "Update all QQ Quns" -msgstr "Mettre à jour tous les Quns QQ" - -msgid "About OpenQ" -msgstr "À propos de OpenQ" - -msgid "Modify Buddy Memo" -msgstr "Changer le mémo de l'utilisateur" - -#. *< type -#. *< ui_requirement -#. *< flags -#. *< dependencies -#. *< priority -#. *< id -#. *< name -#. *< version -#. * summary -#. * description -msgid "QQ Protocol Plugin" -msgstr "Plugin pour le protocole QQ" - -msgid "Auto" -msgstr "Auto" - -msgid "Select Server" -msgstr "Choisir le serveur" - -msgid "QQ2008" -msgstr "QQ2008" - -msgid "QQ2007" -msgstr "QQ2007" - -msgid "QQ2005" -msgstr "QQ2005" - -msgid "Connect by TCP" -msgstr "Connexion par TCP" - -msgid "Show server notice" -msgstr "Afficher les infos du serveur" - -msgid "Show server news" -msgstr "Afficher les nouveautés du serveur" - -msgid "Show chat room when msg comes" -msgstr "Afficher le salon de discussions quand un message arrive" - -msgid "Keep alive interval (seconds)" -msgstr "Délai de Keep alive (en secondes)" - -msgid "Update interval (seconds)" -msgstr "Délai de mise à jour (en secondes)" - -msgid "Unable to decrypt server reply" -msgstr "Impossible de déchiffrer la réponse du serveur" - -#, c-format -msgid "Failed requesting token, 0x%02X" -msgstr "Échec lors de la demande du token, 0x%02X" - -#, c-format -msgid "Invalid token len, %d" -msgstr "Taille de token non valide : %d" - -#. extend redirect used in QQ2006 -msgid "Redirect_EX is not currently supported" -msgstr "Redirect_EX n'est pas supportée pour l'instant" - -#. need activation -#. need activation -#. need activation -msgid "Activation required" -msgstr "Activation nécessaire" - -#, c-format -msgid "Unknown reply code when logging in (0x%02X)" -msgstr "Réponse inconnue à la connexion (0x%02X)" - -msgid "Requesting captcha" -msgstr "Demande de captcha" - -msgid "Checking captcha" -msgstr "Vérification du code du captcha" - -msgid "Failed captcha verification" -msgstr "Échec à la vérification du captcha" - -msgid "Captcha Image" -msgstr "Image captcha" - -msgid "Enter code" -msgstr "Saisissez le code" - -msgid "QQ Captcha Verification" -msgstr "Vérification du captcha QQ" - -msgid "Enter the text from the image" -msgstr "Saisissez le texte de l'image" - -#, c-format -msgid "Unknown reply when checking password (0x%02X)" -msgstr "Réponse inconnue à la vérification du mot de passe (0x%02X)" - -#, c-format -msgid "" -"Unknown reply code when logging in (0x%02X):\n" -"%s" -msgstr "" -"Réponse inconnue à la connexion (0x%02X) :\n" -"%s" - -msgid "Socket error" -msgstr "Erreur de socket." - -msgid "Getting server" -msgstr "Récupération du serveur" - -msgid "Requesting token" -msgstr "Requête d'un token" - -msgid "Unable to resolve hostname" -msgstr "Impossible de résoudre l'adresse internet." - -msgid "Invalid server or port" -msgstr "Serveur ou port non valide" - -msgid "Connecting to server" -msgstr "Connexion au serveur" - -msgid "QQ Error" -msgstr "Erreur QQ" - -#, c-format -msgid "" -"Server News:\n" -"%s\n" -"%s\n" -"%s" -msgstr "" -"Nouveautés du serveur :\n" -"%s\n" -"%s\n" -"%s" - -#, c-format -msgid "%s:%s" -msgstr "%s : %s" - -#, c-format -msgid "From %s:" -msgstr "De %s :" - -#, c-format -msgid "" -"Server notice From %s: \n" -"%s" -msgstr "" -"Info du serveur de %s : \n" -"%s" - -msgid "Unknown SERVER CMD" -msgstr "Commande SERVER inconnue" - -#, c-format -msgid "" -"Error reply of %s(0x%02X)\n" -"Room %u, reply 0x%02X" -msgstr "" -"Erreur à la réponse %s(0x%02X)\n" -"Salon %u, réponse 0x%02X" - -msgid "QQ Qun Command" -msgstr "Commande Qun QQ" - -msgid "Unable to decrypt login reply" -msgstr "Impossible de déchiffrer la réponse de connexion" - -msgid "Unknown LOGIN CMD" -msgstr "Commande LOGIN inconnue" - -msgid "Unknown CLIENT CMD" -msgstr "Commande CLIENT inconnue" - -#, c-format -msgid "%d has declined the file %s" -msgstr "%d a refusé le fichier %s" - -msgid "File Send" -msgstr "Envoi de fichier" - -#, c-format -msgid "%d cancelled the transfer of %s" -msgstr "%d a annulé le transfert de %s" - #, c-format msgid "Group Title: %s
" msgstr "Titre du groupe : %s
" @@ -9629,6 +9011,9 @@ msgid "Unit" msgstr "Groupe" +msgid "Note" +msgstr "Commentaire" + msgid "Join Chat" msgstr "Rejoindre une discussion" @@ -10278,6 +9663,9 @@ msgid "Unable to create listen socket" msgstr "Impossible de se mettre en écoute sur la connexion" +msgid "Unable to resolve hostname" +msgstr "Impossible de résoudre l'adresse internet." + msgid "SIP usernames may not contain whitespaces or @ symbols" msgstr "" "Les noms d'utilisateur SIP ne peuvent pas avoir d'espace ou de symbole @." @@ -10395,6 +9783,9 @@ msgid "Yahoo! system message for %s:" msgstr "Message système Yahoo! pour %s :" +msgid "Authorization denied message:" +msgstr "Message de refus d'autorisation :" + #, c-format msgid "" "%s has (retroactively) denied your request to add them to your list for the " @@ -11189,15 +10580,18 @@ msgid "No Proxy" msgstr "Pas de proxy" -msgid "HTTP" -msgstr "HTTP" - msgid "SOCKS 4" msgstr "SOCKS 4" msgid "SOCKS 5" msgstr "SOCKS 5" +msgid "Tor/Privacy (SOCKS5)" +msgstr "Tor/Privacy (SOCKS5)" + +msgid "HTTP" +msgstr "HTTP" + msgid "Use Environmental Settings" msgstr "Utiliser les paramètres d'environnement" @@ -11225,6 +10619,12 @@ msgid "Pa_ssword:" msgstr "_Mot de passe :" +msgid "Use _silence suppression" +msgstr "Utiliser la suppression de_ silences" + +msgid "_Voice and Video" +msgstr "_Voix et vidéo" + msgid "Unable to save new account" msgstr "Impossible d'enregistrer le nouveau compte." @@ -11273,9 +10673,20 @@ "liste de contacts." #, c-format +msgid "" +"%s%s%s%s wants to add you (%s) to his or her buddy " +"list%s%s" +msgstr "" +"%s%s%s%s veut vous (%s) ajouter à sa liste de " +"contacts%s%s" + +#, c-format msgid "%s%s%s%s wants to add you (%s) to his or her buddy list%s%s" msgstr "%s%s%s%s veut vous (%s) ajouter à sa liste de contacts%s%s" +msgid "Send Instant Message" +msgstr "Envoyer un message" + #. Buddy List msgid "Background Color" msgstr "Couleur de fond" @@ -11829,6 +11240,9 @@ msgid "(Optional) A_lias:" msgstr "A_lias (facultatif) :" +msgid "(Optional) _Invite message:" +msgstr "Message d'_invitation (facultatif) :" + msgid "Add buddy to _group:" msgstr "Ajouter ce contact au _groupe :" @@ -13299,8 +12713,15 @@ msgid "New Pounces" msgstr "Nouvelles alertes" +#. Translators: Make sure you translate "Dismiss" differently than +#. "close"! This string is used in the "You have pounced" dialog +#. that appears when one of your Buddy Pounces is triggered. In +#. this context "Dismiss" means "I acknowledge that I've seen that +#. this pounce was triggered--remove it from this list." Translating +#. it as "Remove" is acceptable if you can't think of a more precise +#. word. msgid "Dismiss" -msgstr "Fermer" +msgstr "Disposer" msgid "You have pounced!" msgstr "Vous avez des alertes !" @@ -14419,6 +13840,9 @@ msgid "PubSub Leaf" msgstr "Feuillet PubSub" +msgid "Other" +msgstr "Autre" + msgid "" "\n" "Description: " @@ -15286,6 +14710,21 @@ msgid "D_evice" msgstr "Appa_reil" +msgid "DROP" +msgstr "Couper" + +msgid "Volume:" +msgstr "Volume :" + +msgid "Silence threshold:" +msgstr "Seuil du silence :" + +msgid "Input and Output Settings" +msgstr "Configuration d'entrée/sortie" + +msgid "Microphone Test" +msgstr "Test du microphone" + #. *< magic #. *< major version #. *< minor version @@ -15298,9 +14737,6 @@ msgid "Voice/Video Settings" msgstr "Paramètres voix et vidéo" -msgid "Voice and Video Settings" -msgstr "Paramètres voix et vidéo" - #. *< name #. *< version msgid "Configure your microphone and webcam." @@ -15578,16 +15014,197 @@ msgid "You do not have permission to uninstall this application." msgstr "Vous n'avez pas les permissions pour supprimer cette application." -#~ msgid "Automatically reject from users not in buddy list" -#~ msgstr "" -#~ "Refuser automatiquement si l'utilisateur n'est pas dans ma liste de " -#~ "contacts" - -#~ msgid "bug master" -#~ msgstr "maitre des bogues" - -#~ msgid "An error occurred on the in-band bytestream transfer\n" -#~ msgstr "Erreur lors du transfert dans le flux de données in-band.\n" +#~ msgid "Authorization Request Message:" +#~ msgstr "Message pour la demande d'autorisation :" + +#~ msgid "Please authorize me!" +#~ msgstr "Autorise moi, s'il te plaît !" + +#~ msgid "Your UID" +#~ msgstr "Votre UID" + +#~ msgid "Hide my number" +#~ msgstr "Cacher mon numéro" + +#~ msgid "Aquarius" +#~ msgstr "Verseau" + +#~ msgid "Pisces" +#~ msgstr "Poissons" + +#~ msgid "Aries" +#~ msgstr "Bélier" + +#~ msgid "Taurus" +#~ msgstr "Taureau" + +#~ msgid "Gemini" +#~ msgstr "Gémeaux" + +#~ msgid "Cancer" +#~ msgstr "Cancer" + +#~ msgid "Leo" +#~ msgstr "Lion" + +#~ msgid "Virgo" +#~ msgstr "Vierge" + +#~ msgid "Libra" +#~ msgstr "Balance" + +#~ msgid "Scorpio" +#~ msgstr "Scorpion" + +#~ msgid "Sagittarius" +#~ msgstr "Sagittaire" + +#~ msgid "Capricorn" +#~ msgstr "Capricorne" + +#~ msgid "Rat" +#~ msgstr "Rat" + +#~ msgid "Ox" +#~ msgstr "Bœuf" + +#~ msgid "Tiger" +#~ msgstr "Tigre" + +#~ msgid "Rabbit" +#~ msgstr "Lièvre" + +#~ msgid "Dragon" +#~ msgstr "Dragon" + +#~ msgid "Snake" +#~ msgstr "Serpent" + +#~ msgid "Horse" +#~ msgstr "Cheval" + +#~ msgid "Goat" +#~ msgstr "Chèvre" + +#~ msgid "Monkey" +#~ msgstr "Singe" + +#~ msgid "Rooster" +#~ msgstr "Coq" + +#~ msgid "Dog" +#~ msgstr "Chien" + +#~ msgid "Pig" +#~ msgstr "Cochon" + +#~ msgid "Visible" +#~ msgstr "Visible" + +#~ msgid "Friend Only" +#~ msgstr "Amis seulement" + +#~ msgid "Private" +#~ msgstr "Privé" + +#~ msgid "Country/Region" +#~ msgstr "Pays/région" + +#~ msgid "Province/State" +#~ msgstr "Province/État" + +#~ msgid "Zipcode" +#~ msgstr "Code postal" + +#~ msgid "Phone Number" +#~ msgstr "Téléphone fixe" + +#~ msgid "Authorize adding" +#~ msgstr "Autoriser l'ajout" + +#~ msgid "Cellphone Number" +#~ msgstr "Téléphone portable" + +#~ msgid "Personal Introduction" +#~ msgstr "Informations personnelles" + +#~ msgid "City/Area" +#~ msgstr "Ville/Localité" + +#~ msgid "Publish Mobile" +#~ msgstr "Publier le téléphone portable" + +#~ msgid "Publish Contact" +#~ msgstr "Publier les informations de contact" + +#~ msgid "College" +#~ msgstr "Éducation" + +#~ msgid "Horoscope" +#~ msgstr "Signe du zodiaque" + +#~ msgid "Zodiac" +#~ msgstr "Signe du zodiaque chinois" + +#~ msgid "Blood" +#~ msgstr "Groupe sanguin" + +#~ msgid "True" +#~ msgstr "Vrai" + +#~ msgid "False" +#~ msgstr "Faux" + +#~ msgid "Modify Contact" +#~ msgstr "Modifier les infos de contact" + +#~ msgid "Modify Address" +#~ msgstr "Modifier l'adresse" + +#~ msgid "Modify Extended Information" +#~ msgstr "Modifier mes infos étendues" + +#~ msgid "Modify Information" +#~ msgstr "Modifier mes informations" + +#~ msgid "Update" +#~ msgstr "Mettre à jour" + +#~ msgid "Could not change buddy information." +#~ msgstr "Impossible de changer les informations du contact." + +#~ msgid "Buddy Memo" +#~ msgstr "Mémo du contact" + +#~ msgid "Change his/her memo as you like" +#~ msgstr "Vous pouvez changer son mémo à votre convenance" + +#~ msgid "_Modify" +#~ msgstr "_Modifier" + +#~ msgid "Memo Modify" +#~ msgstr "Changer mémo" + +#~ msgid "Server says:" +#~ msgstr "Message du serveur :" + +#~ msgid "Your request was accepted." +#~ msgstr "Votre requête a été acceptée." + +#~ msgid "Your request was rejected." +#~ msgstr "Votre requête a été rejetée." + +#~ msgid "%u requires verification: %s" +#~ msgstr "%u demande une vérification : %s" + +#~ msgid "Add buddy question" +#~ msgstr "Ajouter une question pour les nouveaux contacts" + +#~ msgid "Enter answer here" +#~ msgstr "Saisissez la réponse ici" + +#~ msgid "Send" +#~ msgstr "Envoyer" #~ msgid "Transfer was closed." #~ msgstr "Le transfert a été interrompu." @@ -15747,9 +15364,6 @@ #~ msgid "Auto-away" #~ msgstr "Absence automatique" -#~ msgid "Change _status to:" -#~ msgstr "_Changer l'état en :" - #~ msgid "Send instant messages over multiple protocols" #~ msgstr "Envoie des messages instantanés en utilisant divers protocoles" @@ -15963,9 +15577,6 @@ #~ msgid "Please provide a shortcut to associate with the smiley." #~ msgstr "Veuillez fournir un raccourci correspondant à cette frimousse." -#~ msgid "Please select an image for the smiley." -#~ msgstr "Veuillez choisir une image pour cette frimousse." - #~ msgid "Cursor Color" #~ msgstr "Couleur du curseur" @@ -15978,9 +15589,6 @@ #~ msgid "Widget Sizes" #~ msgstr "Tailles des éléments" -#~ msgid "Invite message" -#~ msgstr "Message d'invitation" - #~ msgid "" #~ "Please enter the name of the user you wish to invite,\n" #~ "along with an optional invite message."