Mercurial > pidgin
changeset 26116:cb3c6ec9291e
merge of '6034e4df300b7da5e8fc3095e128f6215af903ab'
and '6f6a810b0411a1e2b7a1bba79dae2b02ea200d19'
author | Mike Ruprecht <maiku@soc.pidgin.im> |
---|---|
date | Sat, 21 Feb 2009 05:15:28 +0000 |
parents | 1830d339f9b9 (current diff) 9b0761b77218 (diff) |
children | 6cf36f68033c |
files | pidgin/gtkmedia.c |
diffstat | 77 files changed, 1021 insertions(+), 548 deletions(-) [+] |
line wrap: on
line diff
--- a/COPYRIGHT Sat Feb 21 05:15:14 2009 +0000 +++ b/COPYRIGHT Sat Feb 21 05:15:28 2009 +0000 @@ -14,6 +14,7 @@ Patrick Aussems Anibal Avelar Ali Albazaz +Kosta Arvanitis Christopher Ayoup Alex Badea John Bailey @@ -66,6 +67,7 @@ Ludovico Cavedon Steve Cavilia Julien Cegarra +Matěj Cepl Cerulean Studios, LLC Jonathan Champ Christophe Chapuis @@ -204,6 +206,7 @@ Intel Corporation Scott Jackson Hans Petter Jansson +David Jedelsky Henry Jen Benjamin Kahn Anders Kaseorg @@ -212,6 +215,7 @@ John Kelm Jochen Kemnade Yann Kerherve +Gordian Klein Akuke Kok Kir Kolyshkin Konstantin Korikov @@ -418,6 +422,7 @@ Andreas Stührk Oleg Sukhodolsky Sun Microsystems +Marcus Sundberg Mårten Svantesson (fursten) Amir Szekely (kichik) Robert T.
--- a/ChangeLog Sat Feb 21 05:15:14 2009 +0000 +++ b/ChangeLog Sat Feb 21 05:15:28 2009 +0000 @@ -7,6 +7,9 @@ enable, check the "Use SSL" option from the Advanced tab when editing your AIM or ICQ account. (Paul Aurich) * Fix a memory leak in SILC. (Luke Petre) + * Fix some string handling in the SIMPLE prpl, which fixes some buddy name + handling and other issues. (Paul Aurich, Marcus Sundberg) + * Implement support for resolving DNS via the SOCKS4 proxy (SOCKS4a). ICQ: * Fix retrieval of status messages from users of ICQ 6.x, Miranda, and @@ -15,6 +18,7 @@ of buddy icons and available messages. * Properly publish status messages for statuses other than Available. ICQ 6.x users can now see these status messages. (Daniel Ljungborg) + * Fix recipt of messages from the mobile client Slick. (David Jedelsky) MSN: * Fix transfer of buddy icons, custom smileys, and files from the @@ -23,8 +27,45 @@ * Large (multi-part) messages are now correctly re-combined. * Federated/Yahoo! buddies should now stop creating sync issues at every signin. You may need to remove duplicates in the Address - Book. See the FAQ for more information. + Book. See the FAQ for more information. Thanks to Jason Lingohr + for lots of debugging and testing. * Messages from Yahoo! buddies are no longer silently dropped. + * We now save and use the CacheKey for ABCH SOAP requests. + * Don't try to parse Personal Status Messages or Current Media if they + don't exist. + * Convert from ISO-8859-1 encoding to UTF-8 when no charset is specified + on incoming messages. This should fix some issues with messages from + older clients. + * Force sending the font "Segoe UI" if outgoing formatting doesn't specify + a font already. + * Queue callbacks when token updates are in progress to prevent two token + update attempts from trampling each other. + * Fixed a crash on Windows when removing a buddy's alias. + * Update the Address Book when buddies' friendly names change. This + prevents seeing an outdated alias or not seeing an alias at all for + buddies who are offline when you sign in. + * Update tokens for FindMembership and ABFindAll SOAP requests. + * We no longer try to send empty messages. This could happen when a + message contained only formatting and that formatting was not supported + on MSN. + * Buddies on both the Allow and Block list are now automatically + removed from the Allow list. Users with this problem will now no + longer receive an ADL 241 error. The problematic buddy should now + appear on the buddy list and can be removed or unblocked as desired. + + XMPP: + * Resources using __HOSTNAME__ substitution will now grab only the short + hostname instead of the FQDN on systems which put the FQDN in the + hostname. (Matěj Cepl) + * No longer send a 'to' attribute on an outgoing stanza when we haven't + received one. This fixes a registration bug as described in ticket + #6635. + + Pidgin: + * Tooltip windows now appear below the mouse cursor. (Kosta Arvanitis) + * Tooltip windows now disappear on keypress events. (Kosta Arvanitis) + * Tooltip windows no longer linger when scrolling the buddy list. (Kosta + Arvanitis) Finch: * Allow rebinding keys to change the focused widget (details in the
--- a/Makefile.am Sat Feb 21 05:15:14 2009 +0000 +++ b/Makefile.am Sat Feb 21 05:15:28 2009 +0000 @@ -99,7 +99,7 @@ @echo "Not generating devhelp index: xsltproc was not found by configure" endif else - @echo "doxygen was not found during configure. Aborting." + @echo "doxygen was not found during configure. Unable to build documentation." @echo; endif
--- a/finch/finch.c Sat Feb 21 05:15:14 2009 +0000 +++ b/finch/finch.c Sat Feb 21 05:15:28 2009 +0000 @@ -210,7 +210,7 @@ text = g_strdup_printf(_("%s\n" "Usage: %s [OPTION]...\n\n" " -c, --config=DIR use DIR for config files\n" - " -d, --debug print debugging messages to stdout\n" + " -d, --debug print debugging messages to stderr\n" " -h, --help display this help and exit\n" " -n, --nologin don't automatically login\n" " -v, --version display the current version and exit\n"), DISPLAY_VERSION, name);
--- a/finch/libgnt/gntkeys.c Sat Feb 21 05:15:14 2009 +0000 +++ b/finch/libgnt/gntkeys.c Sat Feb 21 05:15:28 2009 +0000 @@ -163,7 +163,8 @@ (*(text + 2) >= 'A' && *(text + 2) <= 'D')) { /* Apparently this is necessary for urxvt and screen and xterm */ if (strstr(term, "screen") == term || strcmp(term, "rxvt-unicode") == 0 || - strstr(term, "xterm") == term) + strstr(term, "xterm") == term || + strstr(term, "vt100") == term) *(text + 1) = 'O'; } else if (*(unsigned char*)text == 195) { if (*(text + 2) == 0 && strstr(term, "xterm") == term) {
--- a/finch/libgnt/gntwm.c Sat Feb 21 05:15:14 2009 +0000 +++ b/finch/libgnt/gntwm.c Sat Feb 21 05:15:28 2009 +0000 @@ -353,7 +353,8 @@ p->y = y; g_hash_table_replace(wm->positions, g_strdup(title + 1), p); } else { - gnt_warning("Invalid number of arguments (%d) for positioning a window.", l); + gnt_warning("Invalid number of arguments (%" G_GSIZE_FORMAT + ") for positioning a window.", l); } g_strfreev(coords); }
--- a/finch/plugins/gntclipboard.c Sat Feb 21 05:15:14 2009 +0000 +++ b/finch/plugins/gntclipboard.c Sat Feb 21 05:15:28 2009 +0000 @@ -22,7 +22,7 @@ #include "internal.h" #include <glib.h> -#define PLUGIN_STATIC_NAME "GntClipboard" +#define PLUGIN_STATIC_NAME GntClipboard #ifdef HAVE_X11 #include <X11/Xlib.h>
--- a/finch/plugins/gntgf.c Sat Feb 21 05:15:14 2009 +0000 +++ b/finch/plugins/gntgf.c Sat Feb 21 05:15:28 2009 +0000 @@ -21,7 +21,7 @@ #include "internal.h" -#define PLUGIN_STATIC_NAME "GntGf" +#define PLUGIN_STATIC_NAME GntGf #define PREFS_PREFIX "/plugins/gnt/gntgf" #define PREFS_EVENT PREFS_PREFIX "/events"
--- a/finch/plugins/grouping.c Sat Feb 21 05:15:14 2009 +0000 +++ b/finch/plugins/grouping.c Sat Feb 21 05:15:28 2009 +0000 @@ -383,6 +383,6 @@ { } -PURPLE_INIT_PLUGIN(ignore, init_plugin, info) +PURPLE_INIT_PLUGIN(grouping, init_plugin, info)
--- a/finch/plugins/lastlog.c Sat Feb 21 05:15:14 2009 +0000 +++ b/finch/plugins/lastlog.c Sat Feb 21 05:15:28 2009 +0000 @@ -19,7 +19,7 @@ */ -#define PLUGIN_STATIC_NAME "GntLastlog" +#define PLUGIN_STATIC_NAME GntLastlog #include "internal.h"
--- a/libpurple/account.h Sat Feb 21 05:15:14 2009 +0000 +++ b/libpurple/account.h Sat Feb 21 05:15:28 2009 +0000 @@ -132,6 +132,14 @@ /* to NULL when the account inherits */ /* proxy settings from global prefs. */ + /* + * TODO: Supplementing the next two linked lists with hash tables + * should help performance a lot when these lists are long. This + * matters quite a bit for protocols like MSN, where all your + * buddies are added to your permit list. Currently we have to + * iterate through the entire list if we want to check if someone + * is permitted or denied. We should do this for 3.0.0. + */ GSList *permit; /**< Permit list. */ GSList *deny; /**< Deny list. */ int perm_deny; /**< The permit/deny setting. */
--- a/libpurple/media.c Sat Feb 21 05:15:14 2009 +0000 +++ b/libpurple/media.c Sat Feb 21 05:15:28 2009 +0000 @@ -52,6 +52,7 @@ gchar *id; PurpleMedia *media; GstElement *src; + GstElement *tee; FsSession *session; PurpleMediaSessionType type; @@ -69,20 +70,23 @@ gchar *participant; FsStream *stream; GstElement *sink; + GstElement *src; + GstElement *tee; GList *local_candidates; GList *remote_candidates; gboolean candidates_prepared; - FsCandidate *local_candidate; - FsCandidate *remote_candidate; + GList *active_local_candidates; + GList *active_remote_candidates; gulong window_id; }; struct _PurpleMediaPrivate { + PurpleMediaManager *manager; FsConference *conference; gboolean initiator; @@ -91,7 +95,6 @@ GList *streams; /* PurpleMediaStream table */ - GstElement *pipeline; GstElement *confbin; }; @@ -111,6 +114,8 @@ static void purple_media_candidate_pair_established_cb(FsStream *stream, FsCandidate *native_candidate, FsCandidate *remote_candidate, PurpleMediaSession *session); +static gboolean media_bus_call(GstBus *bus, + GstMessage *msg, PurpleMedia *media); static GObjectClass *parent_class = NULL; @@ -129,6 +134,7 @@ enum { PROP_0, + PROP_MANAGER, PROP_CONFERENCE, PROP_INITIATOR, }; @@ -183,6 +189,13 @@ gobject_class->set_property = purple_media_set_property; gobject_class->get_property = purple_media_get_property; + g_object_class_install_property(gobject_class, PROP_MANAGER, + g_param_spec_object("manager", + "Purple Media Manager", + "The media manager that contains this media session.", + PURPLE_TYPE_MEDIA_MANAGER, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE)); + g_object_class_install_property(gobject_class, PROP_CONFERENCE, g_param_spec_object("conference", "Farsight conference", @@ -250,10 +263,10 @@ if (stream->remote_candidates) fs_candidate_list_destroy(stream->remote_candidates); - if (stream->local_candidate) - fs_candidate_destroy(stream->local_candidate); - if (stream->remote_candidate) - fs_candidate_destroy(stream->remote_candidate); + if (stream->active_local_candidates) + fs_candidate_list_destroy(stream->active_local_candidates); + if (stream->active_remote_candidates) + fs_candidate_list_destroy(stream->active_remote_candidates); g_free(stream); } @@ -276,13 +289,13 @@ purple_debug_info("media","purple_media_dispose\n"); - purple_media_manager_remove_media(purple_media_manager_get(), - PURPLE_MEDIA(media)); + purple_media_manager_remove_media(priv->manager, PURPLE_MEDIA(media)); if (priv->confbin) { gst_element_set_state(GST_ELEMENT(priv->confbin), GST_STATE_NULL); - gst_bin_remove(GST_BIN(priv->pipeline), priv->confbin); + gst_bin_remove(GST_BIN(purple_media_manager_get_pipeline( + priv->manager)), priv->confbin); priv->confbin = NULL; priv->conference = NULL; } @@ -312,6 +325,19 @@ g_object_unref(participants->data); } + if (priv->manager) { + GstElement *pipeline = purple_media_manager_get_pipeline( + priv->manager); + GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline)); + g_signal_handlers_disconnect_matched(G_OBJECT(bus), + G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, + 0, 0, 0, media_bus_call, media); + gst_object_unref(bus); + + g_object_unref(priv->manager); + priv->manager = NULL; + } + G_OBJECT_CLASS(parent_class)->finalize(media); } @@ -336,6 +362,36 @@ } static void +purple_media_setup_pipeline(PurpleMedia *media) +{ + GstBus *bus; + gchar *name; + GstElement *pipeline; + + if (media->priv->conference == NULL || media->priv->manager == NULL) + return; + + pipeline = purple_media_manager_get_pipeline(media->priv->manager); + + name = g_strdup_printf("conf_%p", + media->priv->conference); + media->priv->confbin = gst_bin_new(name); + g_free(name); + + bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline)); + g_signal_connect(G_OBJECT(bus), "message", + G_CALLBACK(media_bus_call), media); + gst_object_unref(bus); + + gst_bin_add(GST_BIN(pipeline), + media->priv->confbin); + gst_bin_add(GST_BIN(media->priv->confbin), + GST_ELEMENT(media->priv->conference)); + gst_element_set_state(GST_ELEMENT(media->priv->confbin), + GST_STATE_PLAYING); +} + +static void purple_media_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { PurpleMedia *media; @@ -344,26 +400,19 @@ media = PURPLE_MEDIA(object); switch (prop_id) { + case PROP_MANAGER: + media->priv->manager = g_value_get_object(value); + g_object_ref(media->priv->manager); + + purple_media_setup_pipeline(media); + break; case PROP_CONFERENCE: { - gchar *name; - if (media->priv->conference) gst_object_unref(media->priv->conference); media->priv->conference = g_value_get_object(value); gst_object_ref(media->priv->conference); - name = g_strdup_printf("conf_%p", - media->priv->conference); - media->priv->confbin = gst_bin_new(name); - g_free(name); - gst_bin_add(GST_BIN(purple_media_get_pipeline(media)), - media->priv->confbin); - gst_bin_add(GST_BIN(media->priv->confbin), - GST_ELEMENT(media->priv->conference)); - - gst_element_set_state(GST_ELEMENT( - media->priv->confbin), - GST_STATE_PLAYING); + purple_media_setup_pipeline(media); break; } case PROP_INITIATOR: @@ -384,6 +433,9 @@ media = PURPLE_MEDIA(object); switch (prop_id) { + case PROP_MANAGER: + g_value_set_object(value, media->priv->manager); + break; case PROP_CONFERENCE: g_value_set_object(value, media->priv->conference); break; @@ -1055,8 +1107,13 @@ gst_bin_add(GST_BIN(session->media->priv->confbin), session->src); + session->tee = gst_element_factory_make("tee", NULL); + gst_bin_add(GST_BIN(session->media->priv->confbin), session->tee); + gst_element_link(session->src, session->tee); + gst_element_set_state(session->tee, GST_STATE_PLAYING); + g_object_get(session->session, "sink-pad", &sinkpad, NULL); - srcpad = gst_element_get_static_pad(src, "ghostsrc"); + srcpad = gst_element_get_request_pad(session->tee, "src%d"); purple_debug_info("media", "connecting pad: %s\n", gst_pad_link(srcpad, sinkpad) == GST_PAD_LINK_OK ? "success" : "failure"); @@ -1181,40 +1238,15 @@ } static gboolean -media_bus_call(GstBus *bus, GstMessage *msg, gpointer dummy) +media_bus_call(GstBus *bus, GstMessage *msg, PurpleMedia *media) { switch(GST_MESSAGE_TYPE(msg)) { - case GST_MESSAGE_EOS: - purple_debug_info("media", "End of Stream\n"); - break; - case GST_MESSAGE_ERROR: { - gchar *debug = NULL; - GError *err = NULL; - - gst_message_parse_error(msg, &err, &debug); - - purple_debug_error("media", "gst pipeline error: %s\n", err->message); - g_error_free(err); - - if (debug) { - purple_debug_error("media", "Debug details: %s\n", debug); - g_free (debug); - } - break; - } case GST_MESSAGE_ELEMENT: { - PurpleMedia *media = NULL; - if (FS_IS_CONFERENCE(GST_MESSAGE_SRC(msg))) { - GList *iter = purple_media_manager_get_media( - purple_media_manager_get()); - for (; iter; iter = g_list_next(iter)) { - if (PURPLE_MEDIA(iter->data)->priv->conference - == FS_CONFERENCE(GST_MESSAGE_SRC(msg))) { - media = iter->data; - break; - } - } - } + if (!FS_IS_CONFERENCE(GST_MESSAGE_SRC(msg)) || + !PURPLE_IS_MEDIA(media) || + media->priv->conference != + FS_CONFERENCE(GST_MESSAGE_SRC(msg))) + break; if (gst_structure_has_name(msg->structure, "farsight-error")) { FsError error_no; @@ -1322,24 +1354,9 @@ GstElement * purple_media_get_pipeline(PurpleMedia *media) { - static GstElement *pipeline = NULL; - g_return_val_if_fail(PURPLE_IS_MEDIA(media), NULL); - if (!pipeline) { - GstBus *bus; - media->priv->pipeline = pipeline = gst_pipeline_new(NULL); - bus = gst_pipeline_get_bus(GST_PIPELINE(media->priv->pipeline)); - gst_bus_add_signal_watch(GST_BUS(bus)); - g_signal_connect(G_OBJECT(bus), "message", - G_CALLBACK(media_bus_call), NULL); - gst_bus_set_sync_handler(bus, gst_bus_sync_signal_handler, NULL); - gst_object_unref(bus); - gst_element_set_state(pipeline, GST_STATE_PLAYING); - } - - media->priv->pipeline = pipeline; - return media->priv->pipeline; + return purple_media_manager_get_pipeline(media->priv->manager); } void @@ -1534,7 +1551,7 @@ void purple_media_video_init_src(GstElement **sendbin) { - GstElement *src, *tee, *queue; + GstElement *src; GstPad *pad; GstPad *ghost; const gchar *video_plugin = purple_prefs_get_string( @@ -1548,20 +1565,12 @@ src = gst_element_factory_make(video_plugin, "purplevideosource"); gst_bin_add(GST_BIN(*sendbin), src); - tee = gst_element_factory_make("tee", "purplevideosrctee"); - gst_bin_add(GST_BIN(*sendbin), tee); - gst_element_link(src, tee); - - queue = gst_element_factory_make("queue", NULL); - gst_bin_add(GST_BIN(*sendbin), queue); - gst_element_link(tee, queue); - if (!strcmp(video_plugin, "videotestsrc")) { /* unless is-live is set to true it doesn't throttle videotestsrc */ g_object_set (G_OBJECT(src), "is-live", TRUE, NULL); } - pad = gst_element_get_static_pad(queue, "src"); + pad = gst_element_get_static_pad(src, "src"); ghost = gst_ghost_pad_new("ghostsrc", pad); gst_object_unref(pad); gst_element_add_pad(*sendbin, ghost); @@ -1573,7 +1582,7 @@ void purple_media_audio_init_recv(GstElement **recvbin, GstElement **recvlevel) { - GstElement *sink, *volume; + GstElement *sink, *volume, *queue; GstPad *pad, *ghost; double output_volume = purple_prefs_get_int( "/purple/media/audio/volume/output")/10.0; @@ -1586,10 +1595,13 @@ volume = gst_element_factory_make("volume", "purpleaudiooutputvolume"); g_object_set(volume, "volume", output_volume, NULL); *recvlevel = gst_element_factory_make("level", "recvlevel"); - gst_bin_add_many(GST_BIN(*recvbin), sink, volume, *recvlevel, NULL); + queue = gst_element_factory_make("queue", NULL); + gst_bin_add_many(GST_BIN(*recvbin), sink, volume, + *recvlevel, queue, NULL); gst_element_link(*recvlevel, sink); gst_element_link(volume, *recvlevel); - pad = gst_element_get_pad(volume, "sink"); + gst_element_link(queue, volume); + pad = gst_element_get_pad(queue, "sink"); ghost = gst_ghost_pad_new("ghostsink", pad); gst_element_add_pad(*recvbin, ghost); g_object_set(G_OBJECT(*recvlevel), "message", TRUE, NULL); @@ -1670,6 +1682,7 @@ gchar *name; FsParticipant *participant; PurpleMediaStream *stream; + GList *iter; g_return_if_fail(FS_IS_STREAM(fsstream)); g_return_if_fail(session != NULL); @@ -1680,8 +1693,41 @@ stream = purple_media_get_stream(session->media, session->id, name); - stream->local_candidate = fs_candidate_copy(native_candidate); - stream->remote_candidate = fs_candidate_copy(remote_candidate); + iter = stream->active_local_candidates; + for(; iter; iter = g_list_next(iter)) { + FsCandidate *c = iter->data; + if (native_candidate->component_id == c->component_id) { + fs_candidate_destroy(c); + stream->active_local_candidates = + g_list_delete_link(iter, iter); + stream->active_local_candidates = g_list_prepend( + stream->active_local_candidates, + fs_candidate_copy(native_candidate)); + break; + } + } + if (iter == NULL) + stream->active_local_candidates = g_list_prepend( + stream->active_local_candidates, + fs_candidate_copy(native_candidate)); + + iter = stream->active_remote_candidates; + for(; iter; iter = g_list_next(iter)) { + FsCandidate *c = iter->data; + if (native_candidate->component_id == c->component_id) { + fs_candidate_destroy(c); + stream->active_remote_candidates = + g_list_delete_link(iter, iter); + stream->active_remote_candidates = g_list_prepend( + stream->active_remote_candidates, + fs_candidate_copy(remote_candidate)); + break; + } + } + if (iter == NULL) + stream->active_remote_candidates = g_list_prepend( + stream->active_remote_candidates, + fs_candidate_copy(remote_candidate)); purple_debug_info("media", "candidate pair established\n"); } @@ -1701,21 +1747,53 @@ purple_media_src_pad_added_cb(FsStream *fsstream, GstPad *srcpad, FsCodec *codec, PurpleMediaStream *stream) { - PurpleMediaSessionType type = purple_media_from_fs(codec->media_type, FS_DIRECTION_RECV); - GstPad *sinkpad = NULL; + PurpleMediaPrivate *priv; + GstPad *sinkpad; g_return_if_fail(FS_IS_STREAM(fsstream)); g_return_if_fail(stream != NULL); - if (stream->sink == NULL) - stream->sink = purple_media_manager_get_element( - purple_media_manager_get(), type); - - gst_bin_add(GST_BIN(stream->session->media->priv->confbin), - stream->sink); - sinkpad = gst_element_get_static_pad(stream->sink, "ghostsink"); + priv = stream->session->media->priv; + + if (stream->src == NULL) { + GstElement *sink; + + if (codec->media_type == FS_MEDIA_TYPE_AUDIO) { + /* + * Should this instead be: + * audioconvert ! audioresample ! liveadder ! + * audioresample ! audioconvert ! realsink + */ + stream->src = gst_element_factory_make( + "liveadder", NULL); + sink = purple_media_manager_get_element(priv->manager, + PURPLE_MEDIA_RECV_AUDIO); + } else if (codec->media_type == FS_MEDIA_TYPE_VIDEO) { + stream->src = gst_element_factory_make( + "fsfunnel", NULL); + sink = gst_element_factory_make( + "fakesink", NULL); + g_object_set(G_OBJECT(sink), "async", FALSE, NULL); + } + stream->tee = gst_element_factory_make("tee", NULL); + gst_bin_add_many(GST_BIN(priv->confbin), + stream->src, stream->tee, sink, NULL); + gst_element_sync_state_with_parent(sink); + gst_element_sync_state_with_parent(stream->tee); + gst_element_sync_state_with_parent(stream->src); + gst_element_link_many(stream->src, stream->tee, sink, NULL); + } + + sinkpad = gst_element_get_request_pad(stream->src, "sink%d"); gst_pad_link(srcpad, sinkpad); - gst_element_set_state(stream->sink, GST_STATE_PLAYING); + gst_object_unref(sinkpad); + + if (codec->media_type == FS_MEDIA_TYPE_VIDEO && + stream->sink != NULL) { + gst_bin_add(GST_BIN(priv->confbin), stream->sink); + gst_element_set_state(stream->sink, GST_STATE_PLAYING); + gst_element_link(stream->tee, stream->sink); + } g_timeout_add_full(G_PRIORITY_HIGH, 0, (GSourceFunc)purple_media_connected_cb, stream, NULL); @@ -1804,7 +1882,7 @@ session_type = purple_media_from_fs(type, FS_DIRECTION_SEND); purple_media_set_src(media, session->id, purple_media_manager_get_element( - purple_media_manager_get(), session_type)); + media->priv->manager, session_type)); gst_element_set_state(session->src, GST_STATE_PLAYING); } @@ -2023,22 +2101,26 @@ } } -PurpleMediaCandidate * -purple_media_get_local_candidate(PurpleMedia *media, const gchar *sess_id, const gchar *name) +GList * +purple_media_get_active_local_candidates(PurpleMedia *media, + const gchar *sess_id, const gchar *name) { PurpleMediaStream *stream; g_return_val_if_fail(PURPLE_IS_MEDIA(media), NULL); stream = purple_media_get_stream(media, sess_id, name); - return purple_media_candidate_from_fs(stream->local_candidate); + return purple_media_candidate_list_from_fs( + stream->active_local_candidates); } -PurpleMediaCandidate * -purple_media_get_remote_candidate(PurpleMedia *media, const gchar *sess_id, const gchar *name) +GList * +purple_media_get_active_remote_candidates(PurpleMedia *media, + const gchar *sess_id, const gchar *name) { PurpleMediaStream *stream; g_return_val_if_fail(PURPLE_IS_MEDIA(media), NULL); stream = purple_media_get_stream(media, sess_id, name); - return purple_media_candidate_from_fs(stream->remote_candidate); + return purple_media_candidate_list_from_fs( + stream->active_remote_candidates); } gboolean @@ -2080,8 +2162,14 @@ for (; sessions; sessions = sessions->next) { const gchar *session = sessions->data; - if (!purple_media_get_local_candidate(media, session, name) || - !purple_media_get_remote_candidate(media, session, name)) + GList *local = purple_media_get_active_local_candidates( + media, session, name); + GList *remote = purple_media_get_active_remote_candidates( + media, session, name); + gboolean result = (local == NULL || remote == NULL); + purple_media_candidate_list_free(local); + purple_media_candidate_list_free(remote); + if (!result) return FALSE; } @@ -2268,15 +2356,14 @@ if (session->sink == NULL) { PurpleMediaXOverlayData *data; GstBus *bus; - GstElement *tee, *bin, *queue, *sink; + GstElement *bin, *queue, *sink; GstPad *request_pad, *sinkpad, *ghostpad; gchar *name; /* Create sink */ - tee = gst_bin_get_by_name(GST_BIN(session->src), - "purplevideosrctee"); bin = gst_bin_new(NULL); - gst_bin_add(GST_BIN(GST_ELEMENT_PARENT(tee)), bin); + gst_bin_add(GST_BIN(GST_ELEMENT_PARENT( + session->tee)), bin); queue = gst_element_factory_make("queue", NULL); name = g_strdup_printf( @@ -2298,7 +2385,8 @@ data->window_id = window_id; bus = gst_pipeline_get_bus(GST_PIPELINE( - purple_media_get_pipeline(media))); + purple_media_manager_get_pipeline( + media->priv->manager))); data->handler_id = g_signal_connect(bus, "sync-message::element", G_CALLBACK(window_id_cb), data); @@ -2307,7 +2395,7 @@ gst_element_set_state(bin, GST_STATE_PLAYING); request_pad = gst_element_get_request_pad( - tee, "src%d"); + session->tee, "src%d"); gst_pad_link(request_pad, ghostpad); gst_object_unref(request_pad); @@ -2329,7 +2417,7 @@ PurpleMediaStream *stream = purple_media_get_stream( media, session_id, participant); GstBus *bus; - GstElement *bin, *sink; + GstElement *bin, *queue, *sink; GstPad *pad, *peer = NULL, *ghostpad; PurpleMediaXOverlayData *data; gchar *name; @@ -2374,16 +2462,14 @@ bin = gst_bin_new(NULL); - if (stream->sink != NULL) - gst_bin_add(GST_BIN(GST_ELEMENT_PARENT( - stream->sink)), bin); - name = g_strdup_printf("stream-sink_%s_%s", session_id, participant); + queue = gst_element_factory_make("queue", NULL); sink = gst_element_factory_make("autovideosink", name); - gst_bin_add(GST_BIN(bin), sink); - pad = gst_element_get_static_pad(sink, "sink"); + gst_bin_add_many(GST_BIN(bin), queue, sink, NULL); + gst_element_link(queue, sink); + pad = gst_element_get_static_pad(queue, "sink"); ghostpad = gst_ghost_pad_new("ghostsink", pad); gst_element_add_pad(bin, ghostpad); @@ -2393,15 +2479,18 @@ data->window_id = window_id; bus = gst_pipeline_get_bus(GST_PIPELINE( - purple_media_get_pipeline(media))); + purple_media_manager_get_pipeline( + media->priv->manager))); data->handler_id = g_signal_connect(bus, "sync-message::element", G_CALLBACK(window_id_cb), data); gst_object_unref(bus); - if (stream->sink != NULL) { + if (stream->tee != NULL) { + gst_bin_add(GST_BIN(GST_ELEMENT_PARENT( + stream->tee)), bin); gst_element_set_state(bin, GST_STATE_PLAYING); - gst_pad_link(peer, ghostpad); + gst_element_link(stream->tee, bin); } stream->sink = bin; @@ -2445,6 +2534,7 @@ gst_element_release_request_pad(GST_ELEMENT_PARENT(peer), peer); gst_object_unref(peer); + gst_element_set_locked_state(sink, TRUE); gst_element_set_state(sink, GST_STATE_NULL); gst_bin_remove(GST_BIN(GST_ELEMENT_PARENT(sink)), sink); @@ -2485,6 +2575,7 @@ peer = gst_pad_get_peer(pad); gst_object_unref(pad); gst_pad_set_blocked_async(peer, TRUE, dummy_block_cb, NULL); + gst_element_set_locked_state(sink, TRUE); gst_element_set_state(sink, GST_STATE_NULL); gst_bin_remove(GST_BIN(parent), sink);
--- a/libpurple/media.h Sat Feb 21 05:15:14 2009 +0000 +++ b/libpurple/media.h Sat Feb 21 05:15:28 2009 +0000 @@ -65,6 +65,18 @@ #endif /* USE_VV */ +/** Media caps */ +typedef enum { + PURPLE_MEDIA_CAPS_NONE = 0, + PURPLE_MEDIA_CAPS_AUDIO = 1, + PURPLE_MEDIA_CAPS_AUDIO_SINGLE_DIRECTION = 1 << 1, + PURPLE_MEDIA_CAPS_VIDEO = 1 << 2, + PURPLE_MEDIA_CAPS_VIDEO_SINGLE_DIRECTION = 1 << 3, + PURPLE_MEDIA_CAPS_AUDIO_VIDEO = 1 << 4, + PURPLE_MEDIA_CAPS_MODIFY_SESSION = 1 << 5, + PURPLE_MEDIA_CAPS_CHANGE_DIRECTION = 1 << 6, +} PurpleMediaCaps; + /** Media session types */ typedef enum { PURPLE_MEDIA_NONE = 0, @@ -533,27 +545,27 @@ const gchar *name); /** - * Gets the active local candidate for the stream. + * Gets the active local candidates for the stream. * * @param media The media object to find the session in. * @param sess_id The session id of the session to find the stream in. * @param name The name of the remote user to get the active candidate from. * - * @return The active candidate retrieved. + * @return The active candidates retrieved. */ -PurpleMediaCandidate *purple_media_get_local_candidate(PurpleMedia *media, +GList *purple_media_get_active_local_candidates(PurpleMedia *media, const gchar *sess_id, const gchar *name); /** - * Gets the active remote candidate for the stream. + * Gets the active remote candidates for the stream. * * @param media The media object to find the session in. * @param sess_id The session id of the session to find the stream in. * @param name The name of the remote user to get the remote candidate from. * - * @return The remote candidate retrieved. + * @return The remote candidates retrieved. */ -PurpleMediaCandidate *purple_media_get_remote_candidate(PurpleMedia *media, +GList *purple_media_get_active_remote_candidates(PurpleMedia *media, const gchar *sess_id, const gchar *name); /**
--- a/libpurple/mediamanager.c Sat Feb 21 05:15:14 2009 +0000 +++ b/libpurple/mediamanager.c Sat Feb 21 05:15:28 2009 +0000 @@ -38,6 +38,7 @@ struct _PurpleMediaManagerPrivate { + GstElement *pipeline; GList *medias; GList *elements; @@ -144,6 +145,62 @@ return manager; } +static gboolean +pipeline_bus_call(GstBus *bus, GstMessage *msg, PurpleMediaManager *manager) +{ + switch(GST_MESSAGE_TYPE(msg)) { + case GST_MESSAGE_EOS: + purple_debug_info("mediamanager", "End of Stream\n"); + break; + case GST_MESSAGE_ERROR: { + gchar *debug = NULL; + GError *err = NULL; + + gst_message_parse_error(msg, &err, &debug); + + purple_debug_error("mediamanager", + "gst pipeline error: %s\n", + err->message); + g_error_free(err); + + if (debug) { + purple_debug_error("mediamanager", + "Debug details: %s\n", debug); + g_free (debug); + } + break; + } + default: + break; + } + return TRUE; +} + +GstElement * +purple_media_manager_get_pipeline(PurpleMediaManager *manager) +{ + g_return_val_if_fail(PURPLE_IS_MEDIA_MANAGER(manager), NULL); + + if (manager->priv->pipeline == NULL) { + GstBus *bus; + manager->priv->pipeline = gst_pipeline_new(NULL); + + bus = gst_pipeline_get_bus( + GST_PIPELINE(manager->priv->pipeline)); + gst_bus_add_signal_watch(GST_BUS(bus)); + g_signal_connect(G_OBJECT(bus), "message", + G_CALLBACK(pipeline_bus_call), manager); + gst_bus_set_sync_handler(bus, + gst_bus_sync_signal_handler, NULL); + gst_object_unref(bus); + + gst_element_set_state(manager->priv->pipeline, + GST_STATE_PLAYING); + } + + return manager->priv->pipeline; +} + PurpleMedia * purple_media_manager_create_media(PurpleMediaManager *manager, PurpleConnection *gc, @@ -165,6 +222,7 @@ } media = PURPLE_MEDIA(g_object_new(purple_media_get_type(), + "manager", manager, "conference", conference, "initiator", initiator, NULL));
--- a/libpurple/mediamanager.h Sat Feb 21 05:15:14 2009 +0000 +++ b/libpurple/mediamanager.h Sat Feb 21 05:15:28 2009 +0000 @@ -121,6 +121,16 @@ PurpleMediaManager *purple_media_manager_get(void); /** + * Gets the pipeline from the media manager. + * + * @param manager The media manager to get the pipeline from. + * + * @return The pipeline. + */ +GstElement * +purple_media_manager_get_pipeline(PurpleMediaManager *manager); + +/** * Creates a media session. * * @param manager The media manager to create the session under.
--- a/libpurple/plugin.h Sat Feb 21 05:15:14 2009 +0000 +++ b/libpurple/plugin.h Sat Feb 21 05:15:28 2009 +0000 @@ -34,11 +34,16 @@ #include "signals.h" #include "value.h" +/** @copydoc _PurplePlugin */ typedef struct _PurplePlugin PurplePlugin; +/** @copydoc _PurplePluginInfo */ typedef struct _PurplePluginInfo PurplePluginInfo; +/** @copydoc _PurplePluginUiInfo */ typedef struct _PurplePluginUiInfo PurplePluginUiInfo; +/** @copydoc _PurplePluginLoaderInfo */ typedef struct _PurplePluginLoaderInfo PurplePluginLoaderInfo; +/** @copydoc _PurplePluginAction */ typedef struct _PurplePluginAction PurplePluginAction; typedef int PurplePluginPriority; /**< Plugin priority. */
--- a/libpurple/plugins/autoaccept.c Sat Feb 21 05:15:14 2009 +0000 +++ b/libpurple/plugins/autoaccept.c Sat Feb 21 05:15:28 2009 +0000 @@ -21,7 +21,7 @@ #define PLUGIN_ID "core-plugin_pack-autoaccept" #define PLUGIN_NAME N_("Autoaccept") -#define PLUGIN_STATIC_NAME "Autoaccept" +#define PLUGIN_STATIC_NAME Autoaccept #define PLUGIN_SUMMARY N_("Auto-accept file transfer requests from selected users.") #define PLUGIN_DESCRIPTION N_("Auto-accept file transfer requests from selected users.") #define PLUGIN_AUTHOR "Sadrul H Chowdhury <sadrul@users.sourceforge.net>"
--- a/libpurple/plugins/codeinline.c Sat Feb 21 05:15:14 2009 +0000 +++ b/libpurple/plugins/codeinline.c Sat Feb 21 05:15:28 2009 +0000 @@ -95,4 +95,4 @@ { } -PURPLE_INIT_PLUGIN(urlcatcher, init_plugin, info) +PURPLE_INIT_PLUGIN(codeinline, init_plugin, info)
--- a/libpurple/plugins/newline.c Sat Feb 21 05:15:14 2009 +0000 +++ b/libpurple/plugins/newline.c Sat Feb 21 05:15:28 2009 +0000 @@ -133,4 +133,4 @@ purple_prefs_add_bool("/plugins/core/newline/chat", TRUE); } -PURPLE_INIT_PLUGIN(lastseen, init_plugin, info) +PURPLE_INIT_PLUGIN(newline, init_plugin, info)
--- a/libpurple/plugins/offlinemsg.c Sat Feb 21 05:15:14 2009 +0000 +++ b/libpurple/plugins/offlinemsg.c Sat Feb 21 05:15:28 2009 +0000 @@ -21,7 +21,7 @@ #define PLUGIN_ID "core-plugin_pack-offlinemsg" #define PLUGIN_NAME N_("Offline Message Emulation") -#define PLUGIN_STATIC_NAME "offlinemsg" +#define PLUGIN_STATIC_NAME offlinemsg #define PLUGIN_SUMMARY N_("Save messages sent to an offline user as pounce.") #define PLUGIN_DESCRIPTION N_("Save messages sent to an offline user as pounce.") #define PLUGIN_AUTHOR "Sadrul H Chowdhury <sadrul@users.sourceforge.net>"
--- a/libpurple/plugins/perl/common/Server.xs Sat Feb 21 05:15:14 2009 +0000 +++ b/libpurple/plugins/perl/common/Server.xs Sat Feb 21 05:15:28 2009 +0000 @@ -122,29 +122,28 @@ Purple::Connection gc const char *name -void -serv_join_chat(con, components) - Purple::Connection con - SV * components -INIT: - HV * t_HV; - HE * t_HE; - SV * t_SV; - GHashTable * t_GHash; +void +serv_join_chat(conn, components) + Purple::Connection conn + HV * components +PREINIT: + HE *t_HE; + SV *t_SV; I32 len; + GHashTable *t_GHash; char *t_key, *t_value; CODE: - t_HV = (HV *)SvRV(components); t_GHash = g_hash_table_new(g_str_hash, g_str_equal); - for (t_HE = hv_iternext(t_HV); t_HE != NULL; t_HE = hv_iternext(t_HV) ) { + for (t_HE = hv_iternext(components); t_HE != NULL; + t_HE = hv_iternext(components)) { t_key = hv_iterkey(t_HE, &len); - t_SV = *hv_fetch(t_HV, t_key, len, 0); - t_value = SvPVutf8_nolen(t_SV); + t_SV = *hv_fetch(components, t_key, len, 0); + t_value = SvPVutf8_nolen(t_SV); g_hash_table_insert(t_GHash, t_key, t_value); } - serv_join_chat(con, t_GHash); + serv_join_chat(conn, t_GHash); void serv_move_buddy(buddy, group1, group2)
--- a/libpurple/prefs.h Sat Feb 21 05:15:14 2009 +0000 +++ b/libpurple/prefs.h Sat Feb 21 05:15:28 2009 +0000 @@ -30,17 +30,17 @@ #include <glib.h> /** - * Pref data types. + * Preference data types. */ typedef enum _PurplePrefType { - PURPLE_PREF_NONE, - PURPLE_PREF_BOOLEAN, - PURPLE_PREF_INT, - PURPLE_PREF_STRING, - PURPLE_PREF_STRING_LIST, - PURPLE_PREF_PATH, - PURPLE_PREF_PATH_LIST + PURPLE_PREF_NONE, /**< No type. */ + PURPLE_PREF_BOOLEAN, /**< Boolean. */ + PURPLE_PREF_INT, /**< Integer. */ + PURPLE_PREF_STRING, /**< String. */ + PURPLE_PREF_STRING_LIST, /**< List of strings. */ + PURPLE_PREF_PATH, /**< Path. */ + PURPLE_PREF_PATH_LIST /**< List of paths. */ } PurplePrefType;
--- a/libpurple/privacy.c Sat Feb 21 05:15:14 2009 +0000 +++ b/libpurple/privacy.c Sat Feb 21 05:15:28 2009 +0000 @@ -42,12 +42,14 @@ name = g_strdup(purple_normalize(account, who)); for (l = account->permit; l != NULL; l = l->next) { - if (!purple_utf8_strcasecmp(name, (char *)l->data)) + if (g_str_equal(name, l->data)) + /* This buddy already exists */ break; } if (l != NULL) { + /* This buddy already exists, so bail out */ g_free(name); return FALSE; } @@ -86,11 +88,13 @@ name = purple_normalize(account, who); for (l = account->permit; l != NULL; l = l->next) { - if (!purple_utf8_strcasecmp(name, (char *)l->data)) + if (g_str_equal(name, l->data)) + /* We found the buddy we were looking for */ break; } if (l == NULL) + /* We didn't find the buddy we were looking for, so bail out */ return FALSE; /* We should not free l->data just yet. There can be occasions where @@ -130,12 +134,14 @@ name = g_strdup(purple_normalize(account, who)); for (l = account->deny; l != NULL; l = l->next) { - if (!purple_utf8_strcasecmp(name, purple_normalize(account, (char *)l->data))) + if (g_str_equal(name, l->data)) + /* This buddy already exists */ break; } if (l != NULL) { + /* This buddy already exists, so bail out */ g_free(name); return FALSE; } @@ -173,14 +179,16 @@ normalized = purple_normalize(account, who); for (l = account->deny; l != NULL; l = l->next) { - if (!purple_utf8_strcasecmp(normalized, (char *)l->data)) + if (g_str_equal(normalized, l->data)) + /* We found the buddy we were looking for */ break; } - buddy = purple_find_buddy(account, normalized); + if (l == NULL) + /* We didn't find the buddy we were looking for, so bail out */ + return FALSE; - if (l == NULL) - return FALSE; + buddy = purple_find_buddy(account, normalized); name = l->data; account->deny = g_slist_delete_link(account->deny, l); @@ -349,7 +357,7 @@ case PURPLE_PRIVACY_ALLOW_USERS: who = purple_normalize(account, who); for (list=account->permit; list!=NULL; list=list->next) { - if (!purple_utf8_strcasecmp(who, (char *)list->data)) + if (g_str_equal(who, list->data)) return TRUE; } return FALSE; @@ -357,7 +365,7 @@ case PURPLE_PRIVACY_DENY_USERS: who = purple_normalize(account, who); for (list=account->deny; list!=NULL; list=list->next) { - if (!purple_utf8_strcasecmp(who, (char *)list->data )) + if (g_str_equal(who, list->data)) return FALSE; } return TRUE;
--- a/libpurple/protocols/jabber/adhoccommands.c Sat Feb 21 05:15:14 2009 +0000 +++ b/libpurple/protocols/jabber/adhoccommands.c Sat Feb 21 05:15:28 2009 +0000 @@ -229,7 +229,7 @@ JabberAdHocCommands *cmd = js->commands->data; g_free(cmd->jid); g_free(cmd->node); - g_free(cmd->node); + g_free(cmd->name); g_free(cmd); js->commands = g_list_delete_link(js->commands, js->commands); }
--- a/libpurple/protocols/jabber/buddy.c Sat Feb 21 05:15:14 2009 +0000 +++ b/libpurple/protocols/jabber/buddy.c Sat Feb 21 05:15:28 2009 +0000 @@ -1786,7 +1786,7 @@ if (!jid) return; - if (jabber_chat_find(js, jid->node, jid->domain)) { + if (jid->node && jabber_chat_find(js, jid->node, jid->domain)) { /* For a conversation, include the resource (indicates the user). */ jabber_buddy_get_info_for_jid(js, who); } else {
--- a/libpurple/protocols/jabber/jabber.c Sat Feb 21 05:15:14 2009 +0000 +++ b/libpurple/protocols/jabber/jabber.c Sat Feb 21 05:15:28 2009 +0000 @@ -157,7 +157,8 @@ } static char *jabber_prep_resource(char *input) { - char hostname[256]; /* current hostname */ + char hostname[256], /* current hostname */ + *dot = NULL; /* Empty resource == don't send any */ if (input == NULL || *input == '\0') @@ -179,6 +180,12 @@ } hostname[sizeof(hostname) - 1] = '\0'; + /* We want only the short hostname, not the FQDN - this will prevent the + * resource string from being unreasonably long on systems which stuff the + * whole FQDN in the hostname */ + if((dot = strchr(hostname, '.'))) + dot = '\0'; + return purple_strreplace(input, "__HOSTNAME__", hostname); } @@ -818,10 +825,11 @@ js->user->node, js->user->domain); if(account->registration_cb) (account->registration_cb)(account, TRUE, account->registration_cb_user_data); - } - else + } else { + g_return_if_fail(to != NULL); buf = g_strdup_printf(_("Registration to %s successful"), to); + } purple_notify_info(NULL, _("Registration Successful"), _("Registration Successful"), buf); g_free(buf); @@ -848,7 +856,11 @@ const char *type = xmlnode_get_attrib(packet, "type"); char *buf; char *to = data; - + + /* This function is never called for unregistering our XMPP account from + * the server, so there should always be a 'to' address. */ + g_return_if_fail(to != NULL); + if(!strcmp(type, "result")) { buf = g_strdup_printf(_("Registration from %s successfully removed"), to); @@ -883,7 +895,8 @@ iq = jabber_iq_new_query(cbdata->js, JABBER_IQ_SET, "jabber:iq:register"); query = xmlnode_get_child(iq->node, "query"); - xmlnode_set_attrib(iq->node, "to", cbdata->who); + if (cbdata->who) + xmlnode_set_attrib(iq->node, "to", cbdata->who); for(groups = purple_request_fields_get_groups(fields); groups; groups = groups->next) { @@ -899,7 +912,8 @@ jabber_iq_free(iq); iq = jabber_iq_new_query(cbdata->js, JABBER_IQ_SET, "jabber:iq:register"); query = xmlnode_get_child(iq->node, "query"); - xmlnode_set_attrib(iq->node,"to",cbdata->who); + if (cbdata->who) + xmlnode_set_attrib(iq->node,"to",cbdata->who); xmlnode_new_child(query, "remove"); jabber_iq_set_callback(iq, jabber_unregistration_result_cb, cbdata->who); @@ -944,8 +958,7 @@ } xmlnode_insert_data(y, value, -1); if(cbdata->js->registration && !strcmp(id, "username")) { - if(cbdata->js->user->node) - g_free(cbdata->js->user->node); + g_free(cbdata->js->user->node); cbdata->js->user->node = g_strdup(value); } if(cbdata->js->registration && !strcmp(id, "password")) @@ -988,7 +1001,8 @@ iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:register"); query = xmlnode_get_child(iq->node, "query"); - xmlnode_set_attrib(iq->node,"to",to); + if (to) + xmlnode_set_attrib(iq->node,"to",to); xmlnode_insert_child(query, result); @@ -1013,10 +1027,7 @@ return; from = xmlnode_get_attrib(packet, "from"); - if (!from) - from = js->serverFQDN; - g_return_if_fail(from != NULL); - + if(js->registration) { /* get rid of the login thingy */ purple_connection_set_state(js->gc, PURPLE_CONNECTED); @@ -1037,11 +1048,11 @@ } } - if((x = xmlnode_get_child_with_namespace(packet, "x", "jabber:x:data"))) { + if((x = xmlnode_get_child_with_namespace(query, "x", "jabber:x:data"))) { jabber_x_data_request(js, x, jabber_register_x_data_cb, g_strdup(from)); return; - } else if((x = xmlnode_get_child_with_namespace(packet, "x", "jabber:x:oob"))) { + } else if((x = xmlnode_get_child_with_namespace(query, "x", "jabber:x:oob"))) { xmlnode *url; if((url = xmlnode_get_child(x, "url"))) { @@ -1161,7 +1172,9 @@ purple_connection_get_account(js->gc), NULL, NULL, cbdata); else { - char *title = registered?g_strdup_printf(_("Change Account Registration at %s"), from) + char *title; + g_return_if_fail(from != NULL); + title = registered ? g_strdup_printf(_("Change Account Registration at %s"), from) :g_strdup_printf(_("Register New Account at %s"), from); purple_request_fields(js->gc, title, title, instructions, fields, @@ -2591,11 +2604,11 @@ return jingle_rtp_initiate_media(gc->proto_data, who, type); } -gboolean jabber_can_do_media(PurpleConnection *gc, const char *who, - PurpleMediaSessionType type) +PurpleMediaCaps jabber_get_media_caps(PurpleConnection *gc, const char *who) { JabberStream *js = (JabberStream *) gc->proto_data; JabberBuddy *jb; + PurpleMediaCaps caps = PURPLE_MEDIA_CAPS_NONE; if (!js) { purple_debug_error("jabber", "jabber_can_do_media: NULL stream\n"); @@ -2609,34 +2622,30 @@ return FALSE; } - if (!jabber_buddy_has_capability(jb, JINGLE_TRANSPORT_ICEUDP) && - !jabber_buddy_has_capability(jb, - JINGLE_TRANSPORT_RAWUDP) && - !jabber_buddy_has_capability(jb, GTALK_CAP)) { - purple_debug_info("jingle-rtp", "Buddy doesn't support " - "the same transport types\n"); - return FALSE; + if (jabber_buddy_has_capability(jb, JINGLE_APP_RTP_SUPPORT_AUDIO)) + caps |= PURPLE_MEDIA_CAPS_AUDIO | + PURPLE_MEDIA_CAPS_AUDIO_SINGLE_DIRECTION; + if (jabber_buddy_has_capability(jb, JINGLE_APP_RTP_SUPPORT_VIDEO)) + caps |= PURPLE_MEDIA_CAPS_VIDEO | + PURPLE_MEDIA_CAPS_VIDEO_SINGLE_DIRECTION; + if (caps & PURPLE_MEDIA_CAPS_AUDIO && caps & PURPLE_MEDIA_CAPS_VIDEO) + caps |= PURPLE_MEDIA_CAPS_AUDIO_VIDEO; + if (caps != PURPLE_MEDIA_CAPS_NONE) { + if (!jabber_buddy_has_capability(jb, + JINGLE_TRANSPORT_ICEUDP) && + !jabber_buddy_has_capability(jb, + JINGLE_TRANSPORT_RAWUDP)) { + purple_debug_info("jingle-rtp", "Buddy doesn't " + "support the same transport types\n"); + caps = PURPLE_MEDIA_CAPS_NONE; + } else + caps |= PURPLE_MEDIA_CAPS_MODIFY_SESSION | + PURPLE_MEDIA_CAPS_CHANGE_DIRECTION; } - - /* XMPP will only support two-way media, AFAIK... */ - if (type == (PURPLE_MEDIA_AUDIO | PURPLE_MEDIA_VIDEO)) { - purple_debug_info("jabber", - "Checking audio/video XEP support for %s\n", who); - return (jabber_buddy_has_capability(jb, JINGLE_APP_RTP_SUPPORT_AUDIO) || - jabber_buddy_has_capability(jb, GTALK_CAP)) && - jabber_buddy_has_capability(jb, JINGLE_APP_RTP_SUPPORT_VIDEO); - } else if (type == (PURPLE_MEDIA_AUDIO)) { - purple_debug_info("jabber", - "Checking audio XEP support for %s\n", who); - return jabber_buddy_has_capability(jb, JINGLE_APP_RTP_SUPPORT_AUDIO) || - jabber_buddy_has_capability(jb, GTALK_CAP); - } else if (type == (PURPLE_MEDIA_VIDEO)) { - purple_debug_info("jabber", - "Checking video XEP support for %s\n", who); - return jabber_buddy_has_capability(jb, JINGLE_APP_RTP_SUPPORT_VIDEO); - } - - return FALSE; + if (jabber_buddy_has_capability(jb, GTALK_CAP)) + caps |= PURPLE_MEDIA_CAPS_AUDIO; + + return caps; } #endif
--- a/libpurple/protocols/jabber/jabber.h Sat Feb 21 05:15:14 2009 +0000 +++ b/libpurple/protocols/jabber/jabber.h Sat Feb 21 05:15:28 2009 +0000 @@ -329,7 +329,7 @@ #ifdef USE_VV PurpleMedia *jabber_initiate_media(PurpleConnection *gc, const char *who, PurpleMediaSessionType type); -gboolean jabber_can_do_media(PurpleConnection *gc, const char *who, PurpleMediaSessionType type); +PurpleMediaCaps jabber_get_media_caps(PurpleConnection *gc, const char *who); #endif #endif /* _PURPLE_JABBER_H_ */
--- a/libpurple/protocols/jabber/jingle/iceudp.c Sat Feb 21 05:15:14 2009 +0000 +++ b/libpurple/protocols/jabber/jingle/iceudp.c Sat Feb 21 05:15:28 2009 +0000 @@ -57,6 +57,7 @@ new_candidate->component = candidate->component; new_candidate->foundation = g_strdup(candidate->foundation); new_candidate->generation = candidate->generation; + new_candidate->id = g_strdup(candidate->id); new_candidate->ip = g_strdup(candidate->ip); new_candidate->network = candidate->network; new_candidate->port = candidate->port; @@ -74,6 +75,7 @@ jingle_iceudp_candidate_free(JingleIceUdpCandidate *candidate) { g_free(candidate->foundation); + g_free(candidate->id); g_free(candidate->ip); g_free(candidate->protocol); g_free(candidate->type); @@ -97,14 +99,16 @@ JingleIceUdpCandidate * jingle_iceudp_candidate_new(guint component, const gchar *foundation, - guint generation, const gchar *ip, guint network, - guint port, guint priority, const gchar *protocol, - const gchar *type, const gchar *username, const gchar *password) + guint generation, const gchar *id, const gchar *ip, + guint network, guint port, guint priority, + const gchar *protocol, const gchar *type, + const gchar *username, const gchar *password) { JingleIceUdpCandidate *candidate = g_new0(JingleIceUdpCandidate, 1); candidate->component = component; candidate->foundation = g_strdup(foundation); candidate->generation = generation; + candidate->id = g_strdup(id); candidate->ip = g_strdup(ip); candidate->network = network; candidate->port = port; @@ -233,8 +237,7 @@ for (; iter; iter = g_list_next(iter)) { JingleIceUdpCandidate *c = iter->data; - if ((c->component == candidate->component) && - !strcmp(c->foundation, candidate->foundation)) { + if (!strcmp(c->id, candidate->id)) { guint generation = c->generation + 1; g_boxed_free(JINGLE_TYPE_ICEUDP_CANDIDATE, c); @@ -261,13 +264,12 @@ static JingleIceUdpCandidate * jingle_iceudp_get_remote_candidate_by_id(JingleIceUdp *iceudp, - guint component, const gchar *foundation) + const gchar *id) { GList *iter = iceudp->priv->remote_candidates; for (; iter; iter = g_list_next(iter)) { JingleIceUdpCandidate *candidate = iter->data; - if ((candidate->component == component) && - !strcmp(candidate->foundation, foundation)) { + if (!strcmp(candidate->id, id)) { return candidate; } } @@ -280,7 +282,7 @@ JingleIceUdpPrivate *priv = JINGLE_ICEUDP_GET_PRIVATE(iceudp); JingleIceUdpCandidate *iceudp_candidate = jingle_iceudp_get_remote_candidate_by_id(iceudp, - candidate->component, candidate->foundation); + candidate->id); if (iceudp_candidate != NULL) { priv->remote_candidates = g_list_remove( priv->remote_candidates, iceudp_candidate); @@ -304,6 +306,7 @@ atoi(xmlnode_get_attrib(candidate, "component")), xmlnode_get_attrib(candidate, "foundation"), atoi(xmlnode_get_attrib(candidate, "generation")), + xmlnode_get_attrib(candidate, "id"), xmlnode_get_attrib(candidate, "ip"), atoi(xmlnode_get_attrib(candidate, "network")), atoi(xmlnode_get_attrib(candidate, "port")), @@ -347,6 +350,7 @@ xmlnode_set_attrib(xmltransport, "component", component); xmlnode_set_attrib(xmltransport, "foundation", candidate->foundation); xmlnode_set_attrib(xmltransport, "generation", generation); + xmlnode_set_attrib(xmltransport, "id", candidate->id); xmlnode_set_attrib(xmltransport, "ip", candidate->ip); xmlnode_set_attrib(xmltransport, "network", network); xmlnode_set_attrib(xmltransport, "port", port);
--- a/libpurple/protocols/jabber/jingle/iceudp.h Sat Feb 21 05:15:14 2009 +0000 +++ b/libpurple/protocols/jabber/jingle/iceudp.h Sat Feb 21 05:15:28 2009 +0000 @@ -66,6 +66,7 @@ guint component; gchar *foundation; guint generation; + gchar *id; gchar *ip; guint network; guint port; @@ -91,9 +92,10 @@ GType jingle_iceudp_get_type(void); JingleIceUdpCandidate *jingle_iceudp_candidate_new(guint component, - const gchar *foundation, guint generation, const gchar *ip, - guint network, guint port, guint priority, const gchar *protocol, - const gchar *type, const gchar *username, const gchar *password); + const gchar *foundation, guint generation, const gchar *id, + const gchar *ip, guint network, guint port, guint priority, + const gchar *protocol, const gchar *type, + const gchar *username, const gchar *password); void jingle_iceudp_add_local_candidate(JingleIceUdp *iceudp, JingleIceUdpCandidate *candidate); GList *jingle_iceudp_get_remote_candidates(JingleIceUdp *iceudp);
--- a/libpurple/protocols/jabber/jingle/jingle.h Sat Feb 21 05:15:14 2009 +0000 +++ b/libpurple/protocols/jabber/jingle/jingle.h Sat Feb 21 05:15:28 2009 +0000 @@ -32,7 +32,7 @@ #define JINGLE "urn:xmpp:jingle:0" #define JINGLE_ERROR "urn:xmpp:jingle:errors:0" -#define JINGLE_APP_FT "urn:xmpp:jingle:apps:file-transfer:0" +#define JINGLE_APP_FT "urn:xmpp:jingle:apps:file-transfer:1" #define JINGLE_APP_RTP "urn:xmpp:jingle:apps:rtp:1" #define JINGLE_APP_RTP_ERROR "urn:xmpp:jingle:apps:rtp:errors:1" #define JINGLE_APP_RTP_INFO "urn:xmpp:jingle:apps:rtp:info:1" @@ -40,7 +40,7 @@ #define JINGLE_APP_RTP_SUPPORT_VIDEO "urn:xmpp:jingle:apps:rtp:video" #define JINGLE_APP_XML "urn:xmpp:tmp:jingle:apps:xmlstream" #define JINGLE_DTMF "urn:xmpp:jingle:dtmf:0" -#define JINGLE_TRANSPORT_SOCKS "urn:xmpp:jingle:transports:bytestreams:0" +#define JINGLE_TRANSPORT_S5B "urn:xmpp:jingle:transports:s5b:0" #define JINGLE_TRANSPORT_IBB "urn:xmpp:jingle:transports:ibb:0" #define JINGLE_TRANSPORT_ICEUDP "urn:xmpp:jingle:transports:ice-udp:0" #define JINGLE_TRANSPORT_RAWUDP "urn:xmpp:jingle:transports:raw-udp:1"
--- a/libpurple/protocols/jabber/jingle/rtp.c Sat Feb 21 05:15:14 2009 +0000 +++ b/libpurple/protocols/jabber/jingle/rtp.c Sat Feb 21 05:15:28 2009 +0000 @@ -189,26 +189,28 @@ jingle_rtp_candidates_to_transport(JingleSession *session, GType type, guint generation, GList *candidates) { if (type == JINGLE_TYPE_RAWUDP) { - gchar *id = jabber_get_next_id(jingle_session_get_js(session)); JingleTransport *transport = jingle_transport_create(JINGLE_TRANSPORT_RAWUDP); JingleRawUdpCandidate *rawudp_candidate; for (; candidates; candidates = g_list_next(candidates)) { PurpleMediaCandidate *candidate = candidates->data; - id = jabber_get_next_id(jingle_session_get_js(session)); + gchar *id = jabber_get_next_id( + jingle_session_get_js(session)); rawudp_candidate = jingle_rawudp_candidate_new(id, generation, candidate->component_id, candidate->ip, candidate->port); jingle_rawudp_add_local_candidate(JINGLE_RAWUDP(transport), rawudp_candidate); + g_free(id); } - g_free(id); return transport; } else if (type == JINGLE_TYPE_ICEUDP) { JingleTransport *transport = jingle_transport_create(JINGLE_TRANSPORT_ICEUDP); JingleIceUdpCandidate *iceudp_candidate; for (; candidates; candidates = g_list_next(candidates)) { PurpleMediaCandidate *candidate = candidates->data; + gchar *id = jabber_get_next_id( + jingle_session_get_js(session)); iceudp_candidate = jingle_iceudp_candidate_new(candidate->component_id, - candidate->foundation, generation, candidate->ip, + candidate->foundation, generation, id, candidate->ip, 0, candidate->port, candidate->priority, "udp", candidate->type == PURPLE_MEDIA_CANDIDATE_TYPE_HOST ? "host" : candidate->type == PURPLE_MEDIA_CANDIDATE_TYPE_SRFLX ? "srflx" : @@ -216,6 +218,7 @@ candidate->type == PURPLE_MEDIA_CANDIDATE_TYPE_RELAY ? "relay" : "", candidate->username, candidate->password); jingle_iceudp_add_local_candidate(JINGLE_ICEUDP(transport), iceudp_candidate); + g_free(id); } return transport; } else { @@ -292,6 +295,26 @@ } static void +jingle_rtp_initiate_ack_cb(JabberStream *js, xmlnode *packet, gpointer data) +{ + JingleSession *session = data; + + if (!strcmp(xmlnode_get_attrib(packet, "type"), "error") || + xmlnode_get_child(packet, "error")) { + gchar *sid = jingle_session_get_sid(session); + purple_media_end(jingle_rtp_get_media(session), NULL, NULL); + g_hash_table_remove(jingle_session_get_js( + session)->medias, sid); + g_free(sid); + g_object_unref(session); + return; + } + + jabber_iq_send(jingle_session_to_packet(session, + JINGLE_TRANSPORT_INFO)); +} + +static void jingle_rtp_ready_cb(PurpleMedia *media, gchar *sid, gchar *name, JingleSession *session) { purple_debug_info("rtp", "ready-new: session: %s name: %s\n", sid, name); @@ -299,16 +322,18 @@ if (sid == NULL && name == NULL) { if (jingle_session_is_initiator(session) == TRUE) { GList *contents = jingle_session_get_contents(session); - - jabber_iq_send(jingle_session_to_packet(session, JINGLE_SESSION_INITIATE)); + JabberIq *iq = jingle_session_to_packet( + session, JINGLE_SESSION_INITIATE); - for (; contents; contents = g_list_next(contents)) { - JingleContent *content = (JingleContent *)contents->data; - JingleTransport *transport = jingle_content_get_transport(content); + if (contents->data) { + JingleTransport *transport = + jingle_content_get_transport(contents->data); if (JINGLE_IS_ICEUDP(transport)) - jabber_iq_send(jingle_session_to_packet(session, - JINGLE_TRANSPORT_INFO)); + jabber_iq_set_callback(iq, + jingle_rtp_initiate_ack_cb, session); } + + jabber_iq_send(iq); } else { jabber_iq_send(jingle_session_to_packet(session, JINGLE_TRANSPORT_INFO)); jabber_iq_send(jingle_session_to_packet(session, JINGLE_SESSION_ACCEPT));
--- a/libpurple/protocols/jabber/libxmpp.c Sat Feb 21 05:15:14 2009 +0000 +++ b/libpurple/protocols/jabber/libxmpp.c Sat Feb 21 05:15:28 2009 +0000 @@ -120,7 +120,7 @@ NULL, /* get_account_text_table */ #ifdef USE_VV jabber_initiate_media, /* initiate_media */ - jabber_can_do_media /* can_do_media */ + jabber_get_media_caps, /* get_media_caps */ #else NULL, /* initiate_media */ NULL /* can_do_media */
--- a/libpurple/protocols/jabber/parser.c Sat Feb 21 05:15:14 2009 +0000 +++ b/libpurple/protocols/jabber/parser.c Sat Feb 21 05:15:28 2009 +0000 @@ -86,15 +86,10 @@ } } for(i=0; i < nb_attributes * 5; i+=5) { - const char *prefix = (const char *)attributes[i + 1]; + const char *attrib_ns = (const char *)attributes[i+2]; char *txt; int attrib_len = attributes[i+4] - attributes[i+3]; char *attrib = g_malloc(attrib_len + 1); - char *attrib_ns = NULL; - - if (attributes[i+2]) { - attrib_ns = g_strdup((char*)attributes[i+2]); - } memcpy(attrib, attributes[i+3], attrib_len); attrib[attrib_len] = '\0'; @@ -103,11 +98,7 @@ attrib = purple_unescape_html(txt); g_free(txt); xmlnode_set_attrib_with_namespace(node, (const char*) attributes[i], attrib_ns, attrib); - if (prefix && *prefix) { - node->prefix = g_strdup(prefix); - } g_free(attrib); - g_free(attrib_ns); } js->current = node;
--- a/libpurple/protocols/msn/contact.c Sat Feb 21 05:15:14 2009 +0000 +++ b/libpurple/protocols/msn/contact.c Sat Feb 21 05:15:28 2009 +0000 @@ -198,20 +198,38 @@ MsnCallbackState *state = data; xmlnode *fault; char *faultcode_str; + xmlnode *cachekey; + char *changed; if (resp == NULL) { purple_debug_error("msn", "Operation {%s} failed. No response received from server.\n", msn_contact_operation_str(state->action)); + msn_session_set_error(state->session, MSN_ERROR_BAD_BLIST, NULL); return; } + /* Update CacheKey if necessary */ + cachekey = xmlnode_get_child(resp->xml, "Header/ServiceHeader/CacheKeyChanged"); + if (cachekey != NULL) { + changed = xmlnode_get_data(cachekey); + if (changed && !strcmp(changed, "true")) { + cachekey = xmlnode_get_child(resp->xml, "Header/ServiceHeader/CacheKey"); + g_free(state->session->abch_cachekey); + state->session->abch_cachekey = xmlnode_get_data(cachekey); + purple_debug_info("msn", "Updated CacheKey for %s to '%s'.\n", + purple_account_get_username(state->session->account), + state->session->abch_cachekey); + } + g_free(changed); + } + fault = xmlnode_get_child(resp->xml, "Body/Fault"); if (fault == NULL) { /* No errors */ if (state->cb) - ((MsnSoapCallback)state->cb)(req, resp, data); + state->cb(req, resp, data); msn_callback_state_free(state); return; } @@ -230,7 +248,7 @@ else { if (state->cb) { - ((MsnSoapCallback)state->cb)(req, resp, data); + state->cb(req, resp, data); } else { /* We don't know how to respond to this faultcode, so log it */ char *str = xmlnode_to_str(fault, NULL); @@ -247,6 +265,14 @@ static gboolean msn_contact_request(MsnCallbackState *state) { + xmlnode *cachekey = xmlnode_get_child(state->body, + "Header/ABApplicationHeader/CacheKey"); + if (cachekey != NULL) + xmlnode_free(cachekey); + if (state->session->abch_cachekey != NULL) { + cachekey = xmlnode_new_child(xmlnode_get_child(state->body, "Header/ABApplicationHeader"), "CacheKey"); + xmlnode_insert_data(cachekey, state->session->abch_cachekey, -1); + } if (state->token == NULL) state->token = xmlnode_get_child(state->body, "Header/ABAuthHeader/TicketToken"); @@ -891,8 +917,7 @@ /* msn_get_address_book(session, NULL, NULL); */ - msn_session_disconnect(session); - purple_connection_error_reason(session->account->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to retrieve MSN Address Book")); + msn_session_set_error(session, MSN_ERROR_BAD_BLIST, NULL); } }
--- a/libpurple/protocols/msn/msg.c Sat Feb 21 05:15:14 2009 +0000 +++ b/libpurple/protocols/msn/msg.c Sat Feb 21 05:15:28 2009 +0000 @@ -80,7 +80,7 @@ msg->ref_count++; #ifdef MSN_DEBUG_MSG - purple_debug_info("msn", "message ref (%p)[%d]\n", msg, msg->ref_count); + purple_debug_info("msn", "message ref (%p)[%" G_GSIZE_FORMAT "]\n", msg, msg->ref_count); #endif return msg; @@ -95,7 +95,7 @@ msg->ref_count--; #ifdef MSN_DEBUG_MSG - purple_debug_info("msn", "message unref (%p)[%d]\n", msg, msg->ref_count); + purple_debug_info("msn", "message unref (%p)[%" G_GSIZE_FORMAT "]\n", msg, msg->ref_count); #endif if (msg->ref_count == 0) @@ -352,6 +352,14 @@ memcpy(msg->body, tmp, msg->body_len); msg->body[msg->body_len] = '\0'; } + + if (msg->charset == NULL) { + char *body = g_convert(msg->body, msg->body_len, "UTF-8", + "ISO-8859-1", NULL, &msg->body_len, NULL); + g_free(msg->body); + msg->body = body; + msg->charset = g_strdup("UTF-8"); + } } g_free(tmp_base);
--- a/libpurple/protocols/msn/msnutils.c Sat Feb 21 05:15:14 2009 +0000 +++ b/libpurple/protocols/msn/msnutils.c Sat Feb 21 05:15:28 2009 +0000 @@ -446,7 +446,7 @@ } if (fontface == NULL) - fontface = g_strdup("MS Sans Serif"); + fontface = g_strdup("Segoe UI"); *attributes = g_strdup_printf("FN=%s; EF=%s; CO=%s; PF=0; RL=%c", encode_spaces(fontface),
--- a/libpurple/protocols/msn/nexus.c Sat Feb 21 05:15:14 2009 +0000 +++ b/libpurple/protocols/msn/nexus.c Sat Feb 21 05:15:28 2009 +0000 @@ -74,6 +74,7 @@ for (i = 0; i < nexus->token_len; i++) { g_hash_table_destroy(nexus->tokens[i].token); g_free(nexus->tokens[i].secret); + g_slist_free(nexus->tokens[i].updates); } g_free(nexus->tokens); @@ -235,6 +236,10 @@ struct _MsnNexusUpdateData { MsnNexus *nexus; int id; +}; + +typedef struct _MsnNexusUpdateCallback MsnNexusUpdateCallback; +struct _MsnNexusUpdateCallback { GSourceFunc cb; gpointer data; }; @@ -428,6 +433,7 @@ char *nonce; gsize len; char *key; + GSList *updates; #if 0 char *decrypted_pp; @@ -489,8 +495,15 @@ g_free(decrypted_data); } - if (ud->cb) - purple_timeout_add(0, ud->cb, ud->data); + updates = nexus->tokens[ud->id].updates; + nexus->tokens[ud->id].updates = NULL; + while (updates != NULL) { + MsnNexusUpdateCallback *update = updates->data; + if (update->cb) + purple_timeout_add(0, update->cb, update->data); + g_free(update); + updates = g_slist_delete_link(updates, updates); + } g_free(ud); } @@ -500,6 +513,7 @@ { MsnSession *session = nexus->session; MsnNexusUpdateData *ud; + MsnNexusUpdateCallback *update; PurpleCipherContext *sha1; PurpleCipherContext *hmac; @@ -526,16 +540,31 @@ char *request; MsnSoapMessage *soap; - purple_debug_info("msn", - "Updating ticket for user '%s' on domain '%s'\n", - purple_account_get_username(session->account), - ticket_domains[id][SSO_VALID_TICKET_DOMAIN]); + update = g_new0(MsnNexusUpdateCallback, 1); + update->cb = cb; + update->data = data; + + if (nexus->tokens[id].updates != NULL) { + /* Update already in progress. Just add to list and return. */ + purple_debug_info("msn", + "Ticket update for user '%s' on domain '%s' in progress. Adding request to queue.\n", + purple_account_get_username(session->account), + ticket_domains[id][SSO_VALID_TICKET_DOMAIN]); + nexus->tokens[id].updates = g_slist_prepend(nexus->tokens[id].updates, + update); + return; + } else { + purple_debug_info("msn", + "Updating ticket for user '%s' on domain '%s'\n", + purple_account_get_username(session->account), + ticket_domains[id][SSO_VALID_TICKET_DOMAIN]); + nexus->tokens[id].updates = g_slist_prepend(nexus->tokens[id].updates, + update); + } ud = g_new0(MsnNexusUpdateData, 1); ud->nexus = nexus; ud->id = id; - ud->cb = cb; - ud->data = data; sha1 = purple_cipher_context_new_by_name("sha1", NULL);
--- a/libpurple/protocols/msn/nexus.h Sat Feb 21 05:15:14 2009 +0000 +++ b/libpurple/protocols/msn/nexus.h Sat Feb 21 05:15:28 2009 +0000 @@ -204,6 +204,7 @@ GHashTable *token; char *secret; time_t expiry; + GSList *updates; }; typedef struct _MsnNexus MsnNexus;
--- a/libpurple/protocols/msn/notification.c Sat Feb 21 05:15:14 2009 +0000 +++ b/libpurple/protocols/msn/notification.c Sat Feb 21 05:15:28 2009 +0000 @@ -623,6 +623,18 @@ if (user->passport && !strcmp(user->passport, "messenger@microsoft.com")) continue; + if ((user->list_op & MSN_LIST_OP_MASK) == (MSN_LIST_AL_OP | MSN_LIST_BL_OP)) { + /* The server will complain if we send it a user on both the + Allow and Block lists. So assume they're on the Block list + and remove them from the Allow list in the membership lists to + stop this from happening again. */ + purple_debug_warning("msn", + "User %s is on both Allow and Block list," + "removing from Allow list.\n", + user->passport); + msn_userlist_rem_buddy_from_list(session->userlist, user->passport, MSN_LIST_AL); + } + msn_add_contact_xml(session, adl_node, user->passport, user->list_op & MSN_LIST_OP_MASK, user->networkid); @@ -1619,19 +1631,25 @@ return; } - psm_str = msn_get_psm(cmd->payload,len); - msn_user_set_statusline(user, psm_str); - g_free(psm_str); + if (len != 0) { + psm_str = msn_get_psm(cmd->payload,len); + msn_user_set_statusline(user, psm_str); + g_free(psm_str); - str = msn_get_currentmedia(cmd->payload, len); - if (msn_parse_currentmedia(str, &media)) - msn_user_set_currentmedia(user, &media); - else + str = msn_get_currentmedia(cmd->payload, len); + if (msn_parse_currentmedia(str, &media)) + msn_user_set_currentmedia(user, &media); + else + msn_user_set_currentmedia(user, NULL); + g_free(media.title); + g_free(media.album); + g_free(media.artist); + g_free(str); + + } else { + msn_user_set_statusline(user, NULL); msn_user_set_currentmedia(user, NULL); - g_free(media.title); - g_free(media.album); - g_free(media.artist); - g_free(str); + } msn_user_update(user); }
--- a/libpurple/protocols/msn/session.c Sat Feb 21 05:15:14 2009 +0000 +++ b/libpurple/protocols/msn/session.c Sat Feb 21 05:15:28 2009 +0000 @@ -90,8 +90,10 @@ msn_userlist_destroy(session->userlist); g_free(session->psm); - + g_free(session->abch_cachekey); +#if 0 g_free(session->blocked_text); +#endif g_free(session->passport_info.kv); g_free(session->passport_info.sid);
--- a/libpurple/protocols/msn/session.h Sat Feb 21 05:15:14 2009 +0000 +++ b/libpurple/protocols/msn/session.h Sat Feb 21 05:15:28 2009 +0000 @@ -94,11 +94,11 @@ gboolean http_method; MsnNotification *notification; - MsnNexus *nexus; - MsnOim *oim; - MsnSync *sync; - - MsnUserList *userlist; + MsnNexus *nexus; + MsnOim *oim; + MsnSync *sync; + MsnUserList *userlist; + char *abch_cachekey; int servconns_count; /**< The count of server connections. */ GList *switches; /**< The list of all the switchboards. */ @@ -107,7 +107,9 @@ /*psm info*/ char *psm; +#if 0 char *blocked_text; +#endif struct {
--- a/libpurple/protocols/msn/slpcall.c Sat Feb 21 05:15:14 2009 +0000 +++ b/libpurple/protocols/msn/slpcall.c Sat Feb 21 05:15:28 2009 +0000 @@ -47,6 +47,7 @@ if (!slpcall->pending && !slpcall->progress) { msn_slpcall_destroy(slpcall); + slpcall->timer = 0; return FALSE; } @@ -222,8 +223,10 @@ if (slpcall != NULL) { - if (slpcall->timer) + if (slpcall->timer) { purple_timeout_remove(slpcall->timer); + slpcall->timer = 0; + } slpcall->cb(slpcall, body, body_len);
--- a/libpurple/protocols/msn/state.c Sat Feb 21 05:15:14 2009 +0000 +++ b/libpurple/protocols/msn/state.c Sat Feb 21 05:15:28 2009 +0000 @@ -189,12 +189,12 @@ purple_debug_info("msn", "msn get PSM\n"); payloadNode = xmlnode_from_str(xml_str, len); - if (!payloadNode){ + if (!payloadNode) { purple_debug_error("msn", "PSM XML parse Error!\n"); return NULL; } psmNode = xmlnode_get_child(payloadNode, "PSM"); - if (psmNode == NULL){ + if (psmNode == NULL) { purple_debug_info("msn", "No PSM status Node"); xmlnode_free(payloadNode); return NULL; @@ -213,7 +213,7 @@ char *ret; PurpleStatus *status = purple_presence_get_status(presence, "tune"); if (!status || !purple_status_is_active(status)) - return g_strdup_printf("\\0Music\\00\\0\\0"); + return NULL; title = purple_status_get_attr_string(status, PURPLE_TUNE_TITLE); game = purple_status_get_attr_string(status, "game"); @@ -234,7 +234,7 @@ else if (office && *office) ret = g_strdup_printf("\\0Office\\01\\0Editing {0}\\0%s\\0", office); else - ret = g_strdup_printf("\\0Music\\00\\0\\0"); + ret = NULL; return ret; }
--- a/libpurple/protocols/msn/transaction.c Sat Feb 21 05:15:14 2009 +0000 +++ b/libpurple/protocols/msn/transaction.c Sat Feb 21 05:15:28 2009 +0000 @@ -199,6 +199,7 @@ if (trans->timeout_cb != NULL) trans->timeout_cb(trans->cmdproc, trans); + trans->timer = 0; return FALSE; }
--- a/libpurple/protocols/myspace/myspace.c Sat Feb 21 05:15:14 2009 +0000 +++ b/libpurple/protocols/myspace/myspace.c Sat Feb 21 05:15:28 2009 +0000 @@ -1146,7 +1146,11 @@ break; case MSIM_CONTACT_LIST_INITIAL_FRIENDS: - /* Nothing */ + /* The session is now set up, ready to be connected. This emits the + * signedOn signal, so clients can now do anything with msimprpl, and + * we're ready for it (session key, userid, username all setup). */ + purple_connection_update_progress(session->gc, _("Connected"), 3, 4); + purple_connection_set_state(session->gc, PURPLE_CONNECTED); break; } @@ -1185,12 +1189,6 @@ /* Set display name to username (otherwise will show email address) */ purple_connection_set_display_name(session->gc, session->username); - /* The session is now set up, ready to be connected. This emits the - * signedOn signal, so clients can now do anything with msimprpl, and - * we're ready for it (session key, userid, username all setup). */ - purple_connection_update_progress(session->gc, _("Connected"), 3, 4); - purple_connection_set_state(session->gc, PURPLE_CONNECTED); - body = msim_msg_new( "UserID", MSIM_TYPE_INTEGER, session->userid, NULL);
--- a/libpurple/protocols/oscar/family_icbm.c Sat Feb 21 05:15:14 2009 +0000 +++ b/libpurple/protocols/oscar/family_icbm.c Sat Feb 21 05:15:28 2009 +0000 @@ -1566,9 +1566,10 @@ static int incomingim_ch1(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, guint16 channel, aim_userinfo_t *userinfo, ByteStream *bs, guint8 *cookie) { - guint16 type, length; + guint16 type, length, magic1, msglen; aim_rxcallback_t userfunc; int ret = 0; + int rev = 0; struct aim_incomingim_ch1_args args; unsigned int endpos; @@ -1603,10 +1604,30 @@ * - 0101 -- Unknown * - Message * + * Slick and possible others reverse 'Features' and 'Messages' section. + * Thus, the TLV could have following layout: + * - 0101 -- Unknown (possibly magic for message section) + * - Message + * - 0501 -- Unknown (possibly magic for features section) + * - Features: Don't know how to interpret these */ - byte_stream_get8(bs); /* 05 */ - byte_stream_get8(bs); /* 01 */ + magic1 = byte_stream_get16(bs); /* 0501 or 0101 */ + if (magic1 == 0x101) /* Bad, message comes before attributes */ + { + /* Jump to the features section */ + msglen = byte_stream_get16(bs); + bs->offset += msglen; + rev = 1; + + magic1 = byte_stream_get16(bs); /* 0501 */ + } + + if (magic1 != 0x501) + { + purple_debug_misc("oscar", "Received an IM containing an invalid message part from %s. They are probably trying to do something malicious.\n", userinfo->sn); + break; + } args.featureslen = byte_stream_get16(bs); if (args.featureslen > byte_stream_empty(bs)) @@ -1624,11 +1645,25 @@ args.icbmflags |= AIM_IMFLAGS_CUSTOMFEATURES; } + if (rev) + { + /* Fix buffer back to message */ + bs->offset -= args.featureslen + 2 + 2 + msglen + 2 + 2; + } + + magic1 = byte_stream_get16(bs); /* 01 01 */ + if (magic1 != 0x101) /* Bad, message comes before attributes */ + { + purple_debug_misc("oscar", "Received an IM containing an invalid message part from %s. They are probably trying to do something malicious.\n", userinfo->sn); + break; + } + msglen = byte_stream_get16(bs); + /* * The rest of the TLV contains one or more message * blocks... */ - incomingim_ch1_parsemsgs(od, userinfo, bs->data + bs->offset /* XXX evil!!! */, length - 2 - 2 - args.featureslen, &args); + incomingim_ch1_parsemsgs(od, userinfo, bs->data + bs->offset - 2 - 2 /* XXX evil!!! */, msglen + 2 + 2, &args); } else if (type == 0x0003) { /* Server Ack Requested */
--- a/libpurple/protocols/qq/ChangeLog Sat Feb 21 05:15:14 2009 +0000 +++ b/libpurple/protocols/qq/ChangeLog Sat Feb 21 05:15:28 2009 +0000 @@ -1,3 +1,6 @@ +2009.02.08 - flos <lonicerae(at)gmail.com> + * Fixed showing message of chat room when message comes in + 2008.12.28 - flos <lonicerae(at)gmail.com> * Fixes #7908
--- a/libpurple/protocols/qq/buddy_info.c Sat Feb 21 05:15:14 2009 +0000 +++ b/libpurple/protocols/qq/buddy_info.c Sat Feb 21 05:15:28 2009 +0000 @@ -108,41 +108,41 @@ } 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_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_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_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, "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_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 } @@ -196,7 +196,9 @@ 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 (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;
--- a/libpurple/protocols/qq/buddy_info.h Sat Feb 21 05:15:14 2009 +0000 +++ b/libpurple/protocols/qq/buddy_info.h Sat Feb 21 05:15:28 2009 +0000 @@ -31,7 +31,7 @@ #include "buddy_opt.h" #include "qq.h" -/* use is openq2005 +/* use in qq2005 * ext_flag: (0-7) * bit1 => qq space * comm_flag: (0-7)
--- a/libpurple/protocols/qq/group_im.c Sat Feb 21 05:15:14 2009 +0000 +++ b/libpurple/protocols/qq/group_im.c Sat Feb 21 05:15:28 2009 +0000 @@ -165,6 +165,7 @@ guint32 room_id, guint32 uid_from, const gchar *msg, time_t in_time) { PurpleConversation *conv; + qq_data *qd; qq_buddy_data *bd; qq_room_data *rmd; gchar *from; @@ -172,15 +173,17 @@ 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); - if (conv == NULL && purple_prefs_get_bool("/plugins/prpl/qq/auto_popup_conversation")) { + 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 (conv == NULL) { + if (NULL == conv) { purple_debug_info("QQ", "Conversion of %u is not open, missing from %d:/n%s/v", room_id, uid_from, msg); return;
--- a/libpurple/protocols/qq/qq.c Sat Feb 21 05:15:14 2009 +0000 +++ b/libpurple/protocols/qq/qq.c Sat Feb 21 05:15:28 2009 +0000 @@ -173,6 +173,7 @@ 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); qd->resend_times = purple_prefs_get_int("/plugins/prpl/qq/resend_times"); if (qd->resend_times <= 1) qd->itv_config.resend = 4; @@ -1097,6 +1098,9 @@ 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_int_new(_("Keep alive interval (seconds)"), "keep_alive_interval", 60); prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); @@ -1106,7 +1110,6 @@ 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_popup_conversation", TRUE); 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);
--- a/libpurple/protocols/qq/qq.h Sat Feb 21 05:15:14 2009 +0000 +++ b/libpurple/protocols/qq/qq.h Sat Feb 21 05:15:28 2009 +0000 @@ -182,6 +182,7 @@ gboolean is_show_notice; gboolean is_show_news; + gboolean is_show_chat; guint16 send_im_id; /* send IM sequence number */ };
--- a/libpurple/protocols/qq/qq_network.c Sat Feb 21 05:15:14 2009 +0000 +++ b/libpurple/protocols/qq/qq_network.c Sat Feb 21 05:15:28 2009 +0000 @@ -214,7 +214,7 @@ qd->connect_retry = QQ_CONNECT_MAX; } - segments = g_strsplit(qd->curr_server, ":", 0); + segments = g_strsplit_set(qd->curr_server, ":", 0); tmp_server = g_strdup(segments[0]); if (NULL != segments[1]) { port = atoi(segments[1]);
--- a/libpurple/protocols/silc10/silc.c Sat Feb 21 05:15:14 2009 +0000 +++ b/libpurple/protocols/silc10/silc.c Sat Feb 21 05:15:28 2009 +0000 @@ -1957,4 +1957,4 @@ #endif } -PURPLE_INIT_PLUGIN(silc, init_plugin, info); +PURPLE_INIT_PLUGIN(silc10, init_plugin, info);
--- a/libpurple/protocols/simple/simple.c Sat Feb 21 05:15:14 2009 +0000 +++ b/libpurple/protocols/simple/simple.c Sat Feb 21 05:15:28 2009 +0000 @@ -196,7 +196,7 @@ { struct simple_account_data *sip = (struct simple_account_data *)gc->proto_data; struct simple_buddy *b; - if(strcmp("sip:", buddy->name)) { + if(strncmp(buddy->name, "sip:", 4)) { gchar *buf = g_strdup_printf("sip:%s", buddy->name); purple_blist_rename_buddy(buddy, buf); g_free(buf); @@ -834,10 +834,10 @@ "Event: presence\r\n", expiration); - if(strstr(buddy->name, "sip:")) + if(strncmp(buddy->name, "sip:", 4)) + to = g_strdup_printf("sip:%s", buddy->name); + else to = g_strdup(buddy->name); - else - to = g_strdup_printf("sip:%s", buddy->name); tmp = get_contact(sip); contact = g_strdup_printf("%sContact: %s\r\n", tmp2, tmp); @@ -881,7 +881,7 @@ tmp = sipmsg_find_header(msg, "Event"); - if(tmp && !strcmp(tmp, "vnd-microsoft-roaming-contacts")){ + if(tmp && !strncmp(tmp, "vnd-microsoft-roaming-contacts", 30)){ purple_debug_info("simple", "simple_add_lcs_contacts->%s-%d\n", msg->body, len); /*Convert the contact from XML to Purple Buddies*/ @@ -1013,11 +1013,11 @@ static void simple_send_message(struct simple_account_data *sip, const char *to, const char *msg, const char *type) { gchar *hdr; gchar *fullto; - if(strcmp("sip:", to)) { + if(strncmp(to, "sip:", 4)) fullto = g_strdup_printf("sip:%s", to); - } else { + else fullto = g_strdup(to); - } + if(type) { hdr = g_strdup_printf("Content-Type: %s\r\n", type); } else { @@ -1050,12 +1050,12 @@ purple_debug(PURPLE_DEBUG_MISC, "simple", "got message from %s: %s\n", from, msg->body); contenttype = sipmsg_find_header(msg, "Content-Type"); - if(!contenttype || !strcmp(contenttype, "text/plain") || !strcmp(contenttype, "text/html")) { + if(!contenttype || !strncmp(contenttype, "text/plain", 10) || !strncmp(contenttype, "text/html", 9)) { serv_got_im(sip->gc, from, msg->body, 0, time(NULL)); send_sip_response(sip->gc, msg, 200, "OK", NULL); found = TRUE; } - else if(!strcmp(contenttype, "application/im-iscomposing+xml")) { + else if(!strncmp(contenttype, "application/im-iscomposing+xml", 30)) { xmlnode *isc = xmlnode_from_str(msg->body, msg->bodylen); xmlnode *state; gchar *statedata;
--- a/libpurple/proxy.c Sat Feb 21 05:15:14 2009 +0000 +++ b/libpurple/proxy.c Sat Feb 21 05:15:28 2009 +0000 @@ -1177,56 +1177,47 @@ } static void -s4_canwrite(gpointer data, gint source, PurpleInputCondition cond) +s4_host_resolved(GSList *hosts, gpointer data, const char *error_message) { - unsigned char packet[9]; - struct hostent *hp; PurpleProxyConnectData *connect_data = data; - int error = ETIMEDOUT; - int ret; - - purple_debug_info("socks4 proxy", "Connected.\n"); + unsigned char packet[9]; + struct sockaddr *addr; - if (connect_data->inpa > 0) - { - purple_input_remove(connect_data->inpa); - connect_data->inpa = 0; - } + connect_data->query_data = NULL; - ret = purple_input_get_error(connect_data->fd, &error); - if ((ret != 0) || (error != 0)) - { - if (ret != 0) - error = errno; - purple_proxy_connect_data_disconnect(connect_data, g_strerror(error)); + if (error_message != NULL) { + purple_proxy_connect_data_disconnect(connect_data, error_message); return; } - /* - * The socks4 spec doesn't include support for doing host name - * lookups by the proxy. Some socks4 servers do this via - * extensions to the protocol. Since we don't know if a - * server supports this, it would need to be implemented - * with an option, or some detection mechanism - in the - * meantime, stick with plain old SOCKS4. - */ - /* TODO: Use purple_dnsquery_a() */ - hp = gethostbyname(connect_data->host); - if (hp == NULL) { + if (hosts == NULL) { purple_proxy_connect_data_disconnect_formatted(connect_data, _("Error resolving %s"), connect_data->host); return; } - packet[0] = 4; - packet[1] = 1; + /* Discard the length... */ + hosts = g_slist_delete_link(hosts, hosts); + addr = hosts->data; + hosts = g_slist_delete_link(hosts, hosts); + + packet[0] = 0x04; + packet[1] = 0x01; packet[2] = connect_data->port >> 8; packet[3] = connect_data->port & 0xff; - packet[4] = (unsigned char)(hp->h_addr_list[0])[0]; - packet[5] = (unsigned char)(hp->h_addr_list[0])[1]; - packet[6] = (unsigned char)(hp->h_addr_list[0])[2]; - packet[7] = (unsigned char)(hp->h_addr_list[0])[3]; - packet[8] = 0; + memcpy(packet + 4, &((struct sockaddr_in *)addr)->sin_addr.s_addr, 4); + packet[8] = 0x00; + + g_free(addr); + + /* We could try the other hosts, but hopefully that shouldn't be necessary */ + while (hosts != NULL) { + /* Discard the length... */ + hosts = g_slist_delete_link(hosts, hosts); + /* Free the address... */ + g_free(hosts->data); + hosts = g_slist_delete_link(hosts, hosts); + } connect_data->write_buffer = g_memdup(packet, sizeof(packet)); connect_data->write_buf_len = sizeof(packet); @@ -1235,7 +1226,74 @@ connect_data->inpa = purple_input_add(connect_data->fd, PURPLE_INPUT_WRITE, proxy_do_write, connect_data); - proxy_do_write(connect_data, connect_data->fd, cond); + proxy_do_write(connect_data, connect_data->fd, PURPLE_INPUT_WRITE); +} + +static void +s4_canwrite(gpointer data, gint source, PurpleInputCondition cond) +{ + PurpleProxyConnectData *connect_data = data; + int error = ETIMEDOUT; + int ret; + + purple_debug_info("socks4 proxy", "Connected.\n"); + + if (connect_data->inpa > 0) { + purple_input_remove(connect_data->inpa); + connect_data->inpa = 0; + } + + ret = purple_input_get_error(connect_data->fd, &error); + if ((ret != 0) || (error != 0)) { + if (ret != 0) + error = errno; + purple_proxy_connect_data_disconnect(connect_data, g_strerror(error)); + return; + } + + /* + * The socks4 spec doesn't include support for doing host name lookups by + * the proxy. Many socks4 servers do this via the "socks4a" extension to + * the protocol. There doesn't appear to be a way to detect if a server + * supports this, so we require that the user set a global option. + */ + if (purple_prefs_get_bool("/purple/proxy/socks4_remotedns")) { + unsigned char packet[9]; + int len; + + purple_debug_info("socks4 proxy", "Attempting to use remote DNS.\n"); + + packet[0] = 0x04; + packet[1] = 0x01; + packet[2] = connect_data->port >> 8; + packet[3] = connect_data->port & 0xff; + packet[4] = 0x00; + packet[5] = 0x00; + packet[6] = 0x00; + packet[7] = 0x01; + packet[8] = 0x00; + + len = sizeof(packet) + strlen(connect_data->host) + 1; + + connect_data->write_buffer = g_malloc0(len); + memcpy(connect_data->write_buffer, packet, sizeof(packet)); + memcpy(connect_data->write_buffer + sizeof(packet), connect_data->host, strlen(connect_data->host)); + connect_data->write_buf_len = len; + connect_data->written_len = 0; + connect_data->read_cb = s4_canread; + + connect_data->inpa = purple_input_add(connect_data->fd, PURPLE_INPUT_WRITE, proxy_do_write, connect_data); + + proxy_do_write(connect_data, connect_data->fd, PURPLE_INPUT_WRITE); + } else { + connect_data->query_data = purple_dnsquery_a(connect_data->host, + connect_data->port, s4_host_resolved, connect_data); + + if (connect_data->query_data == NULL) { + purple_debug_error("proxy", "dns query failed unexpectedly.\n"); + purple_proxy_connect_data_destroy(connect_data); + } + } } static void @@ -1396,7 +1454,7 @@ s5_sendconnect(gpointer data, int source) { PurpleProxyConnectData *connect_data = data; - int hlen = strlen(connect_data->host); + size_t hlen = strlen(connect_data->host); connect_data->write_buf_len = 5 + hlen + 2; connect_data->write_buffer = g_malloc(connect_data->write_buf_len); connect_data->written_len = 0; @@ -1479,7 +1537,7 @@ int i; unsigned char Kxoripad[65]; unsigned char Kxoropad[65]; - int pwlen; + size_t pwlen; cipher = purple_ciphers_find_cipher("md5"); ctx = purple_cipher_context_new(cipher, NULL); @@ -1697,7 +1755,7 @@ return; msg_ret = s5_parse_chap_msg(connect_data); - + if (msg_ret < 0) return; @@ -1777,7 +1835,7 @@ } if (connect_data->read_buffer[1] == 0x02) { - gsize i, j; + size_t i, j; const char *u, *p; u = purple_proxy_info_get_username(connect_data->gpi); @@ -1810,7 +1868,7 @@ return; } else if (connect_data->read_buffer[1] == 0x03) { - gsize userlen; + size_t userlen; userlen = strlen(purple_proxy_info_get_username(connect_data->gpi)); connect_data->write_buf_len = 7 + userlen; @@ -1957,7 +2015,7 @@ static void try_connect(PurpleProxyConnectData *connect_data) { - size_t addrlen; + socklen_t addrlen; struct sockaddr *addr; char ipaddr[INET6_ADDRSTRLEN]; @@ -1969,7 +2027,7 @@ inet_ntop(addr->sa_family, &((struct sockaddr_in *)addr)->sin_addr, ipaddr, sizeof(ipaddr)); #else - memcpy(ipaddr,inet_ntoa(((struct sockaddr_in *)addr)->sin_addr), + memcpy(ipaddr, inet_ntoa(((struct sockaddr_in *)addr)->sin_addr), sizeof(ipaddr)); #endif purple_debug_info("proxy", "Attempting connection to %s\n", ipaddr); @@ -2293,6 +2351,7 @@ purple_prefs_add_int("/purple/proxy/port", 0); purple_prefs_add_string("/purple/proxy/username", ""); purple_prefs_add_string("/purple/proxy/password", ""); + purple_prefs_add_bool("/purple/proxy/socks4_remotedns", FALSE); /* Setup callbacks for the preferences. */ handle = purple_proxy_get_handle();
--- a/libpurple/prpl.c Sat Feb 21 05:15:14 2009 +0000 +++ b/libpurple/prpl.c Sat Feb 21 05:15:28 2009 +0000 @@ -524,10 +524,8 @@ #endif } -gboolean -purple_prpl_can_do_media(PurpleAccount *account, - const char *who, - PurpleMediaSessionType type) +PurpleMediaCaps +purple_prpl_get_media_caps(PurpleAccount *account, const char *who) { #ifdef USE_VV PurpleConnection *gc = NULL; @@ -541,14 +539,12 @@ if (prpl) prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); - if (prpl_info && PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, can_do_media)) { - return prpl_info->can_do_media(gc, who, type); - } else { - return FALSE; + if (prpl_info && PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, + get_media_caps)) { + return prpl_info->get_media_caps(gc, who); } -#else - return FALSE; #endif + return PURPLE_MEDIA_CAPS_NONE; } /**************************************************************************
--- a/libpurple/prpl.h Sat Feb 21 05:15:14 2009 +0000 +++ b/libpurple/prpl.h Sat Feb 21 05:15:28 2009 +0000 @@ -466,11 +466,10 @@ * * @param conn The connection the contact is on. * @param who The remote user to check for media capability with. - * @param type The type of media session to check for. - * @return @c TRUE The contact supports the given media type, or @c FALSE otherwise. + * @return The media caps the contact supports. */ - gboolean (*can_do_media)(PurpleConnection *gc, const char *who, - PurpleMediaSessionType type); + PurpleMediaCaps (*get_media_caps)(PurpleConnection *gc, + const char *who); }; #define PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl, member) \ @@ -765,13 +764,11 @@ * * @param account The account the user is on. * @param who The name of the contact to check capabilities for. - * @param type The type of media session to check for. * - * @return @c TRUE if the contact supports the session type, else @c FALSE. + * @return The media caps the contact supports. */ -gboolean purple_prpl_can_do_media(PurpleAccount *account, - const char *who, - PurpleMediaSessionType type); +PurpleMediaCaps purple_prpl_get_media_caps(PurpleAccount *account, + const char *who); /** * Initiates a media session with the given contact.
--- a/libpurple/savedstatuses.c Sat Feb 21 05:15:14 2009 +0000 +++ b/libpurple/savedstatuses.c Sat Feb 21 05:15:28 2009 +0000 @@ -148,11 +148,11 @@ /* Avoid using 0 because it's an invalid hash key */ status->creation_time = creation_time != 0 ? creation_time : 1; - while (g_hash_table_lookup(creation_times, &status->creation_time) != NULL) + while (g_hash_table_lookup(creation_times, (gconstpointer)status->creation_time) != NULL) status->creation_time++; g_hash_table_insert(creation_times, - &status->creation_time, + (gpointer)status->creation_time, status); } @@ -217,7 +217,7 @@ { saved_statuses = g_list_remove(saved_statuses, saved_status); creation_time = purple_savedstatus_get_creation_time(saved_status); - g_hash_table_remove(creation_times, &creation_time); + g_hash_table_remove(creation_times, (gconstpointer)creation_time); free_saved_status(saved_status); } } @@ -713,7 +713,7 @@ saved_statuses = g_list_remove(saved_statuses, status); creation_time = purple_savedstatus_get_creation_time(status); - g_hash_table_remove(creation_times, &creation_time); + g_hash_table_remove(creation_times, (gconstpointer)creation_time); free_saved_status(status); schedule_save(); @@ -801,13 +801,13 @@ PurpleSavedStatus * purple_savedstatus_get_default() { - int creation_time; + time_t creation_time; PurpleSavedStatus *saved_status = NULL; creation_time = purple_prefs_get_int("/purple/savedstatus/default"); if (creation_time != 0) - saved_status = g_hash_table_lookup(creation_times, &creation_time); + saved_status = g_hash_table_lookup(creation_times, (gconstpointer)creation_time); if (saved_status == NULL) { @@ -828,13 +828,13 @@ PurpleSavedStatus * purple_savedstatus_get_idleaway() { - int creation_time; + time_t creation_time; PurpleSavedStatus *saved_status = NULL; creation_time = purple_prefs_get_int("/purple/savedstatus/idleaway"); if (creation_time != 0) - saved_status = g_hash_table_lookup(creation_times, &creation_time); + saved_status = g_hash_table_lookup(creation_times, (gconstpointer)creation_time); if (saved_status == NULL) { @@ -907,13 +907,13 @@ PurpleSavedStatus * purple_savedstatus_get_startup() { - int creation_time; + time_t creation_time; PurpleSavedStatus *saved_status = NULL; creation_time = purple_prefs_get_int("/purple/savedstatus/startup"); if (creation_time != 0) - saved_status = g_hash_table_lookup(creation_times, &creation_time); + saved_status = g_hash_table_lookup(creation_times, (gconstpointer)creation_time); if (saved_status == NULL) { @@ -1187,7 +1187,7 @@ { void *handle = purple_savedstatuses_get_handle(); - creation_times = g_hash_table_new(g_int_hash, g_int_equal); + creation_times = g_hash_table_new(g_direct_hash, g_direct_equal); /* * Using 0 as the creation_time is a special case.
--- a/libpurple/sslconn.h Sat Feb 21 05:15:14 2009 +0000 +++ b/libpurple/sslconn.h Sat Feb 21 05:15:28 2009 +0000 @@ -39,6 +39,7 @@ #define PURPLE_SSL_DEFAULT_PORT 443 +/** @copydoc _PurpleSslConnection */ typedef struct _PurpleSslConnection PurpleSslConnection; typedef void (*PurpleSslInputFunction)(gpointer, PurpleSslConnection *,
--- a/libpurple/upnp.c Sat Feb 21 05:15:14 2009 +0000 +++ b/libpurple/upnp.c Sat Feb 21 05:15:28 2009 +0000 @@ -567,7 +567,7 @@ purple_upnp_discover_send_broadcast(UPnPDiscoveryData *dd) { gchar *sendMessage = NULL; - gsize totalSize; + size_t totalSize; gboolean sentSuccess; /* because we are sending over UDP, if there is a failure @@ -693,6 +693,7 @@ /* XXX: This should probably be async */ if(cb) cb(NULL, cb_data, NULL, 0, NULL); + return NULL; } if(port == 0 || port == -1) { port = DEFAULT_HTTP_PORT; @@ -711,11 +712,11 @@ g_free(soapMessage); gfud = purple_util_fetch_url_request_len(control_info.control_url, FALSE, NULL, TRUE, - totalSendMessage, TRUE, MAX_UPNP_DOWNLOAD, cb, cb_data); + totalSendMessage, TRUE, MAX_UPNP_DOWNLOAD, cb, cb_data); g_free(totalSendMessage); g_free(addressOfControl); - + return gfud; }
--- a/libpurple/util.h Sat Feb 21 05:15:14 2009 +0000 +++ b/libpurple/util.h Sat Feb 21 05:15:28 2009 +0000 @@ -1207,7 +1207,7 @@ G_CONST_RETURN gchar *purple_gai_strerror(gint errnum); /** - * Compares two UTF-8 strings case-insensitively. This string is + * Compares two UTF-8 strings case-insensitively. This comparison is * more expensive than a simple g_utf8_collate() comparison because * it calls g_utf8_casefold() on each string, which allocates new * strings.
--- a/libpurple/version.h.in Sat Feb 21 05:15:14 2009 +0000 +++ b/libpurple/version.h.in Sat Feb 21 05:15:28 2009 +0000 @@ -24,8 +24,11 @@ #ifndef _PURPLE_VERSION_H_ #define _PURPLE_VERSION_H_ +/** The major version of the running libpurple. */ #define PURPLE_MAJOR_VERSION (@PURPLE_MAJOR_VERSION@) +/** The minor version of the running libpurple. */ #define PURPLE_MINOR_VERSION (@PURPLE_MINOR_VERSION@) +/** The micro version of the running libpurple. */ #define PURPLE_MICRO_VERSION (@PURPLE_MICRO_VERSION@) #define PURPLE_VERSION_CHECK(x,y,z) ((x) == PURPLE_MAJOR_VERSION && \
--- a/pidgin/gtkblist.c Sat Feb 21 05:15:14 2009 +0000 +++ b/pidgin/gtkblist.c Sat Feb 21 05:15:28 2009 +0000 @@ -66,7 +66,7 @@ #include <gtk/gtk.h> #include <gdk/gdk.h> -#define HEADLINE_CLOSE_SIZE 12 +#define HEADLINE_CLOSE_SIZE 11 typedef struct { @@ -348,8 +348,9 @@ { /* if the buddy supports both audio and video, start a combined call, otherwise start a pure video session */ - if (purple_prpl_can_do_media(purple_buddy_get_account(b), - purple_buddy_get_name(b), PURPLE_MEDIA_AUDIO)) { + if (purple_prpl_get_media_caps(purple_buddy_get_account(b), + purple_buddy_get_name(b)) & + PURPLE_MEDIA_CAPS_AUDIO_VIDEO) { purple_prpl_initiate_media(purple_buddy_get_account(b), purple_buddy_get_name(b), PURPLE_MEDIA_AUDIO | PURPLE_MEDIA_VIDEO); } else { @@ -1463,20 +1464,20 @@ G_CALLBACK(gtk_blist_menu_im_cb), buddy, 0, 0, NULL); #ifdef USE_VV - if (prpl_info && prpl_info->can_do_media) { - PurpleConnection *gc = - purple_account_get_connection(purple_buddy_get_account(buddy)); + if (prpl_info && prpl_info->get_media_caps) { + PurpleAccount *account = purple_buddy_get_account(buddy); const gchar *who = purple_buddy_get_name(buddy); - if (prpl_info->can_do_media(gc, who, PURPLE_MEDIA_AUDIO)) { + PurpleMediaCaps caps = purple_prpl_get_media_caps(account, who); + if (caps & PURPLE_MEDIA_CAPS_AUDIO) { pidgin_new_item_from_stock(menu, _("_Audio Call"), PIDGIN_STOCK_TOOLBAR_AUDIO_CALL, G_CALLBACK(gtk_blist_menu_audio_call_cb), buddy, 0, 0, NULL); } - if (prpl_info->can_do_media(gc, who, PURPLE_MEDIA_VIDEO | PURPLE_MEDIA_AUDIO)) { + if (caps & PURPLE_MEDIA_CAPS_AUDIO_VIDEO) { pidgin_new_item_from_stock(menu, _("Audio/_Video Call"), PIDGIN_STOCK_TOOLBAR_VIDEO_CALL, G_CALLBACK(gtk_blist_menu_video_call_cb), buddy, 0, 0, NULL); - } else if (prpl_info->can_do_media(gc, who, PURPLE_MEDIA_VIDEO)) { + } else if (caps & PURPLE_MEDIA_CAPS_VIDEO) { pidgin_new_item_from_stock(menu, _("_Video Call"), PIDGIN_STOCK_TOOLBAR_VIDEO_CALL, G_CALLBACK(gtk_blist_menu_video_call_cb), buddy, 0, 0, NULL); @@ -4601,6 +4602,9 @@ if (!gtkblist) return FALSE; + /* clear any tooltips */ + pidgin_blist_tooltip_destroy(); + widget = gtk_window_get_focus(GTK_WINDOW(gtkblist->window)); if (GTK_IS_IMHTML(widget) || GTK_IS_ENTRY(widget)) { @@ -5434,7 +5438,8 @@ NULL); gtk_widget_set_name(gtkblist->headline_hbox, "gtk-tooltips"); - gtkblist->headline_close = gtk_widget_render_icon(ebox, GTK_STOCK_CLOSE, HEADLINE_CLOSE_SIZE, NULL); + gtkblist->headline_close = gtk_widget_render_icon(ebox, GTK_STOCK_CLOSE, + gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_MICROSCOPIC), NULL); gtkblist->hand_cursor = gdk_cursor_new (GDK_HAND2); gtkblist->arrow_cursor = gdk_cursor_new (GDK_LEFT_PTR); @@ -7723,13 +7728,11 @@ if (!disabled_accounts) { menuitem = gtk_menu_item_new_with_label(_("Enable Account")); gtk_menu_shell_append(GTK_MENU_SHELL(accountmenu), menuitem); - gtk_widget_show(menuitem); submenu = gtk_menu_new(); gtk_menu_set_accel_group(GTK_MENU(submenu), accel_group); gtk_menu_set_accel_path(GTK_MENU(submenu), N_("<PurpleMain>/Accounts/Enable Account")); gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu); - gtk_widget_show(submenu); disabled_accounts = TRUE; } @@ -7751,7 +7754,6 @@ g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(enable_account_cb), account); gtk_menu_shell_append(GTK_MENU_SHELL(submenu), menuitem); - gtk_widget_show(menuitem); } else { enabled_accounts = TRUE; } @@ -7793,21 +7795,18 @@ gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), image); } gtk_menu_shell_append(GTK_MENU_SHELL(accountmenu), menuitem); - gtk_widget_show(menuitem); submenu = gtk_menu_new(); gtk_menu_set_accel_group(GTK_MENU(submenu), accel_group); gtk_menu_set_accel_path(GTK_MENU(submenu), accel_path_buf); g_free(accel_path_buf); gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu); - gtk_widget_show(submenu); menuitem = gtk_menu_item_new_with_mnemonic(_("_Edit Account")); g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(modify_account_cb), account); gtk_menu_shell_append(GTK_MENU_SHELL(submenu), menuitem); - gtk_widget_show(menuitem); pidgin_separator(submenu); @@ -7819,7 +7818,6 @@ menuitem = gtk_menu_item_new_with_label(_("No actions available")); gtk_menu_shell_append(GTK_MENU_SHELL(submenu), menuitem); gtk_widget_set_sensitive(menuitem, FALSE); - gtk_widget_show(menuitem); } pidgin_separator(submenu); @@ -7828,8 +7826,8 @@ g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(disable_account_cb), account); gtk_menu_shell_append(GTK_MENU_SHELL(submenu), menuitem); - gtk_widget_show(menuitem); - } + } + gtk_widget_show_all(accountmenu); } static GList *plugin_submenus = NULL; @@ -7868,13 +7866,11 @@ menuitem = gtk_image_menu_item_new_with_label(_(plugin->info->name)); gtk_menu_shell_append(GTK_MENU_SHELL(pluginmenu), menuitem); - gtk_widget_show(menuitem); plugin_submenus = g_list_append(plugin_submenus, menuitem); submenu = gtk_menu_new(); gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu); - gtk_widget_show(submenu); gtk_menu_set_accel_group(GTK_MENU(submenu), accel_group); path = g_strdup_printf("%s/Tools/%s", gtkblist->ift->path, plugin->info->name); @@ -7883,6 +7879,7 @@ build_plugin_actions(submenu, plugin, NULL); } + gtk_widget_show_all(pluginmenu); } static void
--- a/pidgin/gtkblist.h Sat Feb 21 05:15:14 2009 +0000 +++ b/pidgin/gtkblist.h Sat Feb 21 05:15:28 2009 +0000 @@ -27,6 +27,7 @@ #ifndef _PIDGINBLIST_H_ #define _PIDGINBLIST_H_ +/** @copydoc _PidginBuddyList */ typedef struct _PidginBuddyList PidginBuddyList; enum {
--- a/pidgin/gtkconv.c Sat Feb 21 05:15:14 2009 +0000 +++ b/pidgin/gtkconv.c Sat Feb 21 05:15:28 2009 +0000 @@ -1976,6 +1976,9 @@ win = gtkconv->win; curconv = gtk_notebook_get_current_page(GTK_NOTEBOOK(win->notebook)); + /* clear any tooltips */ + pidgin_tooltip_destroy(); + /* If CTRL was held down... */ if (event->state & GDK_CONTROL_MASK) { switch (event->keyval) { @@ -6446,19 +6449,19 @@ supports it */ if (account != NULL && purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { - gboolean audio = purple_prpl_can_do_media(account, - purple_conversation_get_name(conv), - PURPLE_MEDIA_AUDIO); - gboolean video = purple_prpl_can_do_media(account, - purple_conversation_get_name(conv), - PURPLE_MEDIA_VIDEO); - gboolean av = purple_prpl_can_do_media(account, - purple_conversation_get_name(conv), - PURPLE_MEDIA_AUDIO | PURPLE_MEDIA_VIDEO); - - gtk_widget_set_sensitive(win->menu.audio_call, audio ? TRUE : FALSE); - gtk_widget_set_sensitive(win->menu.video_call, video ? TRUE : FALSE); - gtk_widget_set_sensitive(win->menu.audio_video_call, av ? TRUE : FALSE); + PurpleMediaCaps caps = + purple_prpl_get_media_caps(account, + purple_conversation_get_name(conv)); + + gtk_widget_set_sensitive(win->menu.audio_call, + caps & PURPLE_MEDIA_CAPS_AUDIO + ? TRUE : FALSE); + gtk_widget_set_sensitive(win->menu.video_call, + caps & PURPLE_MEDIA_CAPS_VIDEO + ? TRUE : FALSE); + gtk_widget_set_sensitive(win->menu.audio_video_call, + caps & PURPLE_MEDIA_CAPS_AUDIO_VIDEO + ? TRUE : FALSE); } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { /* for now, don't care about chats... */ gtk_widget_set_sensitive(win->menu.audio_call, FALSE);
--- a/pidgin/gtkdialogs.c Sat Feb 21 05:15:14 2009 +0000 +++ b/pidgin/gtkdialogs.c Sat Feb 21 05:15:28 2009 +0000 @@ -457,12 +457,17 @@ "warranty for this program.<BR><BR>"), PIDGIN_NAME, PIDGIN_NAME, PIDGIN_NAME); g_string_append(str, "<FONT SIZE=\"4\">URL:</FONT> <A HREF=\"" - PURPLE_WEBSITE "\">" PURPLE_WEBSITE "</A><BR/><BR/>"); - g_string_append(str, "<FONT SIZE=\"4\">FAQ:</FONT> <A HREF=\"" - "http://developer.pidgin.im/wiki/FAQ\">" - "http://developer.pidgin.im/wiki/FAQ</A><BR/><BR/>"); - g_string_append_printf(str, _("<FONT SIZE=\"4\">IRC:</FONT> " - "#pidgin on irc.freenode.net<BR><BR>")); + PURPLE_WEBSITE "\">" PURPLE_WEBSITE "</A><BR/><BR/>"); + g_string_append_printf(str, _("<FONT SIZE=\"4\">FAQ:</FONT> <A HREF=\"" + "http://developer.pidgin.im/wiki/FAQ\">" + "http://developer.pidgin.im/wiki/FAQ</A><BR/><BR/>")); + g_string_append_printf(str, _("<FONT SIZE=\"4\">Help via e-mail:</FONT>" + " <A HREF=\"mailto:support@pidgin.im\">support@pidgin.im</A>" + "<BR/><BR/>")); + g_string_append_printf(str, _("<FONT SIZE=\"4\">IRC Channel:</FONT> " + "#pidgin on irc.freenode.net<BR><BR>")); + g_string_append_printf(str, _("<FONT SIZE=\"4\">XMPP MUC:</FONT> " + "devel@conference.pidgin.im<BR><BR>")); /* Current Developers */ g_string_append_printf(str, "<FONT SIZE=\"4\">%s:</FONT><BR/>",
--- a/pidgin/gtkdocklet.c Sat Feb 21 05:15:14 2009 +0000 +++ b/pidgin/gtkdocklet.c Sat Feb 21 05:15:28 2009 +0000 @@ -88,13 +88,16 @@ static GList * get_pending_list(guint max) { - GList *l_im = NULL; - GList *l_chat = NULL; + GList *l_im, *l_chat; l_im = pidgin_conversations_find_unseen_list(PURPLE_CONV_TYPE_IM, PIDGIN_UNSEEN_TEXT, FALSE, max); + /* Short circuit if we have our information already */ + if (max == 1 && l_im != NULL) + return l_im; + l_chat = pidgin_conversations_find_unseen_list(PURPLE_CONV_TYPE_CHAT, PIDGIN_UNSEEN_NICK, FALSE, max); @@ -344,7 +347,9 @@ docklet_menu_leave_enter(GtkWidget *menu, GdkEventCrossing *event, void *data) { static guint hide_docklet_timer = 0; - if (event->type == GDK_LEAVE_NOTIFY && event->detail == GDK_NOTIFY_ANCESTOR) { + + if (event->type == GDK_LEAVE_NOTIFY && (event->detail == GDK_NOTIFY_ANCESTOR || + event->detail == GDK_NOTIFY_UNKNOWN)) { purple_debug(PURPLE_DEBUG_INFO, "docklet", "menu leave-notify-event\n"); /* Add some slop so that the menu doesn't annoyingly disappear when mousing around */ if (hide_docklet_timer == 0) { @@ -652,11 +657,9 @@ menuitem = gtk_image_menu_item_new_with_label(_(plugin->info->name)); gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); - gtk_widget_show(menuitem); submenu = gtk_menu_new(); gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu); - gtk_widget_show(submenu); build_plugin_actions(submenu, plugin, NULL);
--- a/pidgin/gtkmedia.c Sat Feb 21 05:15:14 2009 +0000 +++ b/pidgin/gtkmedia.c Sat Feb 21 05:15:28 2009 +0000 @@ -62,10 +62,6 @@ GtkWidget *menubar; GtkWidget *statusbar; - GtkWidget *calling; - GtkWidget *accept; - GtkWidget *reject; - GtkWidget *hangup; GtkWidget *mute; GtkWidget *send_progress; @@ -287,7 +283,7 @@ gtk_box_pack_end(GTK_BOX(vbox), media->priv->statusbar, FALSE, FALSE, 0); gtk_statusbar_push(GTK_STATUSBAR(media->priv->statusbar), - 0, _("Connecting...")); + 0, _("Calling...")); gtk_widget_show(media->priv->statusbar); media->priv->menubar = setup_menubar(media); @@ -298,23 +294,12 @@ gtk_box_pack_end(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); gtk_widget_show(GTK_WIDGET(hbox)); - media->priv->calling = gtk_label_new("Calling..."); - media->priv->hangup = gtk_button_new_with_mnemonic("_Hangup"); - media->priv->accept = gtk_button_new_with_mnemonic("_Accept"); - media->priv->reject = gtk_button_new_with_mnemonic("_Reject"); media->priv->mute = gtk_toggle_button_new_with_mnemonic("_Mute"); g_signal_connect(media->priv->mute, "toggled", G_CALLBACK(pidgin_media_mute_toggled), media); - gtk_box_pack_end(GTK_BOX(hbox), media->priv->reject, FALSE, FALSE, 0); - gtk_box_pack_end(GTK_BOX(hbox), media->priv->accept, FALSE, FALSE, 0); - gtk_box_pack_end(GTK_BOX(hbox), media->priv->hangup, FALSE, FALSE, 0); gtk_box_pack_end(GTK_BOX(hbox), media->priv->mute, FALSE, FALSE, 0); - gtk_box_pack_end(GTK_BOX(hbox), media->priv->calling, FALSE, FALSE, 0); - - gtk_widget_show_all(media->priv->accept); - gtk_widget_show_all(media->priv->reject); media->priv->display = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); gtk_box_pack_start(GTK_BOX(vbox), media->priv->display, @@ -386,6 +371,7 @@ purple_debug_info("gtkmedia", "pidgin_media_dispose\n"); if (gtkmedia->priv->media) { + purple_request_close_with_handle(gtkmedia); purple_media_remove_output_windows(gtkmedia->priv->media); pidgin_media_disconnect_levels(gtkmedia->priv->media, gtkmedia); g_object_unref(gtkmedia->priv->media); @@ -620,14 +606,14 @@ if (type & PURPLE_MEDIA_RECV_AUDIO) { gtkmedia->priv->recv_progress = gtk_progress_bar_new(); - gtk_widget_set_size_request(gtkmedia->priv->recv_progress, 70, 10); + gtk_widget_set_size_request(gtkmedia->priv->recv_progress, 320, 10); gtk_box_pack_end(GTK_BOX(recv_widget), gtkmedia->priv->recv_progress, FALSE, FALSE, 0); gtk_widget_show(gtkmedia->priv->recv_progress); } if (type & PURPLE_MEDIA_SEND_AUDIO) { gtkmedia->priv->send_progress = gtk_progress_bar_new(); - gtk_widget_set_size_request(gtkmedia->priv->send_progress, 70, 10); + gtk_widget_set_size_request(gtkmedia->priv->send_progress, 320, 10); gtk_box_pack_end(GTK_BOX(send_widget), gtkmedia->priv->send_progress, FALSE, FALSE, 0); gtk_widget_show(gtkmedia->priv->send_progress); @@ -715,13 +701,6 @@ else pidgin_media_set_state(media, PIDGIN_MEDIA_REQUESTED); - g_signal_connect_swapped(G_OBJECT(media->priv->accept), "clicked", - G_CALLBACK(purple_media_accept), media->priv->media); - g_signal_connect_swapped(G_OBJECT(media->priv->reject), "clicked", - G_CALLBACK(purple_media_reject), media->priv->media); - g_signal_connect_swapped(G_OBJECT(media->priv->hangup), "clicked", - G_CALLBACK(purple_media_hangup), media->priv->media); - g_signal_connect(G_OBJECT(media->priv->media), "error", G_CALLBACK(pidgin_media_error_cb), media); g_signal_connect(G_OBJECT(media->priv->media), "accepted", @@ -793,28 +772,6 @@ pidgin_media_set_state(PidginMedia *gtkmedia, PidginMediaState state) { gtkmedia->priv->state = state; - switch (state) { - case PIDGIN_MEDIA_WAITING: - gtk_widget_show(gtkmedia->priv->calling); - gtk_widget_hide(gtkmedia->priv->accept); - gtk_widget_hide(gtkmedia->priv->reject); - gtk_widget_show(gtkmedia->priv->hangup); - break; - case PIDGIN_MEDIA_REQUESTED: - gtk_widget_hide(gtkmedia->priv->calling); - gtk_widget_show(gtkmedia->priv->accept); - gtk_widget_show(gtkmedia->priv->reject); - gtk_widget_hide(gtkmedia->priv->hangup); - break; - case PIDGIN_MEDIA_ACCEPTED: - gtk_widget_show(gtkmedia->priv->hangup); - gtk_widget_hide(gtkmedia->priv->calling); - gtk_widget_hide(gtkmedia->priv->accept); - gtk_widget_hide(gtkmedia->priv->reject); - break; - default: - break; - } } static gboolean @@ -835,10 +792,10 @@ if (initiator == FALSE) { gchar *message = g_strdup_printf("%s wishes to start a " "media session with you\n", alias); - purple_request_accept_cancel(media, "Media invitation", - message, NULL, 1, (void*)pc, screenname, - NULL, media, purple_media_accept, - purple_media_reject); + purple_request_accept_cancel(gtkmedia, "Media invitation", + message, NULL, PURPLE_DEFAULT_ACTION_NONE, + (void*)pc, screenname, NULL, media, + purple_media_accept, purple_media_reject); g_free(message); } else gtk_widget_show(GTK_WIDGET(gtkmedia));
--- a/pidgin/gtkprefs.c Sat Feb 21 05:15:14 2009 +0000 +++ b/pidgin/gtkprefs.c Sat Feb 21 05:15:28 2009 +0000 @@ -1439,6 +1439,10 @@ purple_prefs_connect_callback(prefs, "/purple/proxy/type", proxy_changed_cb, prefs_proxy_frame); + /* This is a global option that affects SOCKS4 usage even with account-specific proxy settings */ + pidgin_prefs_checkbox(_("Use remote DNS with SOCKS4 proxies"), + "/purple/proxy/socks4_remotedns", prefs_proxy_frame); + table = gtk_table_new(4, 2, FALSE); gtk_container_set_border_width(GTK_CONTAINER(table), 0); gtk_table_set_col_spacings(GTK_TABLE(table), 5);
--- a/pidgin/pidgintooltip.c Sat Feb 21 05:15:14 2009 +0000 +++ b/pidgin/pidgintooltip.c Sat Feb 21 05:15:28 2009 +0000 @@ -135,14 +135,14 @@ setup_tooltip_window_position(gpointer data, int w, int h) { int sig; - int scr_w, scr_h, x, y; + int scr_w, scr_h, x, y, dy; #if GTK_CHECK_VERSION(2,2,0) int mon_num; GdkScreen *screen = NULL; #endif GdkRectangle mon_size; GtkWidget *tipwindow = pidgin_tooltip.tipwindow; - + #if GTK_CHECK_VERSION(2,2,0) gdk_display_get_pointer(gdk_display_get_default(), &screen, &x, &y, NULL); mon_num = gdk_screen_get_monitor_at_point(screen, x, y); @@ -158,6 +158,12 @@ mon_size.y = 0; #endif +#if GTK_CHECK_VERSION(2,4,0) + dy = gdk_display_get_default_cursor_size(gdk_display_get_default()) / 2; +#else + dy = 0; +#endif + #if GTK_CHECK_VERSION(2,2,0) if (w > mon_size.width) w = mon_size.width - 10; @@ -168,9 +174,9 @@ x -= ((w >> 1) + 4); if ((y + h + 4) > scr_h) - y = y - h - 5; + y = y - h - dy - 5; else - y = y + 6; + y = y + dy + 6; if (y < mon_size.y) y = mon_size.y; @@ -353,6 +359,7 @@ g_signal_connect(G_OBJECT(tree), "motion-notify-event", G_CALLBACK(row_motion_cb), tdata); g_signal_connect(G_OBJECT(tree), "leave-notify-event", G_CALLBACK(widget_leave_cb), NULL); + g_signal_connect(G_OBJECT(tree), "scroll-event", G_CALLBACK(widget_leave_cb), NULL); g_signal_connect_swapped(G_OBJECT(tree), "destroy", G_CALLBACK(destroy_tooltip_data), tdata); return TRUE; } @@ -381,6 +388,7 @@ g_signal_connect(G_OBJECT(widget), "motion-notify-event", G_CALLBACK(widget_motion_cb), wdata); g_signal_connect(G_OBJECT(widget), "leave-notify-event", G_CALLBACK(widget_leave_cb), NULL); + g_signal_connect(G_OBJECT(widget), "scroll-event", G_CALLBACK(widget_leave_cb), NULL); g_signal_connect_swapped(G_OBJECT(widget), "destroy", G_CALLBACK(destroy_tooltip_data), wdata); return TRUE; }
--- a/pidgin/plugins/convcolors.c Sat Feb 21 05:15:14 2009 +0000 +++ b/pidgin/plugins/convcolors.c Sat Feb 21 05:15:28 2009 +0000 @@ -21,7 +21,7 @@ #define PLUGIN_ID "gtk-plugin_pack-convcolors" #define PLUGIN_NAME N_("Conversation Colors") -#define PLUGIN_STATIC_NAME "Conversation Colors" +#define PLUGIN_STATIC_NAME ConversationColors #define PLUGIN_SUMMARY N_("Customize colors in the conversation window") #define PLUGIN_DESCRIPTION N_("Customize colors in the conversation window") #define PLUGIN_AUTHOR "Sadrul H Chowdhury <sadrul@users.sourceforge.net>"
--- a/pidgin/plugins/markerline.c Sat Feb 21 05:15:14 2009 +0000 +++ b/pidgin/plugins/markerline.c Sat Feb 21 05:15:28 2009 +0000 @@ -21,7 +21,7 @@ #define PLUGIN_ID "gtk-plugin_pack-markerline" #define PLUGIN_NAME N_("Markerline") -#define PLUGIN_STATIC_NAME "Markerline" +#define PLUGIN_STATIC_NAME Markerline #define PLUGIN_SUMMARY N_("Draw a line to indicate new messages in a conversation.") #define PLUGIN_DESCRIPTION N_("Draw a line to indicate new messages in a conversation.") #define PLUGIN_AUTHOR "Sadrul H Chowdhury <sadrul@users.sourceforge.net>"
--- a/pidgin/plugins/pidgininc.c Sat Feb 21 05:15:14 2009 +0000 +++ b/pidgin/plugins/pidgininc.c Sat Feb 21 05:15:28 2009 +0000 @@ -6,7 +6,7 @@ #include "conversation.h" #include "version.h" -/* include UI for pidgindialogs_about() */ +/* include UI for pidgin_dialogs_about() */ #include "gtkplugin.h" #include "gtkdialogs.h" @@ -16,7 +16,7 @@ echo_hi(PurpleConnection *gc) { /* this doesn't do much, just lets you know who we are :) */ - pidgindialogs_about(); + pidgin_dialogs_about(); } static gboolean @@ -108,7 +108,12 @@ NULL, /**< ui_info */ NULL, /**< extra_info */ NULL, /**< prefs_info */ - NULL /**< actions */ + NULL, /**< actions */ + /* padding */ + NULL, + NULL, + NULL, + NULL }; static void
--- a/pidgin/plugins/timestamp.c Sat Feb 21 05:15:14 2009 +0000 +++ b/pidgin/plugins/timestamp.c Sat Feb 21 05:15:28 2009 +0000 @@ -229,4 +229,4 @@ purple_prefs_add_int("/plugins/gtk/timestamp/interval", interval * 1000); } -PURPLE_INIT_PLUGIN(interval, init_plugin, info) +PURPLE_INIT_PLUGIN(timestamp, init_plugin, info)
--- a/pidgin/plugins/xmppconsole.c Sat Feb 21 05:15:14 2009 +0000 +++ b/pidgin/plugins/xmppconsole.c Sat Feb 21 05:15:28 2009 +0000 @@ -890,4 +890,4 @@ { } -PURPLE_INIT_PLUGIN(interval, init_plugin, info) +PURPLE_INIT_PLUGIN(xmppconsole, init_plugin, info)
--- a/po/de.po Sat Feb 21 05:15:14 2009 +0000 +++ b/po/de.po Sat Feb 21 05:15:28 2009 +0000 @@ -11,15 +11,15 @@ msgstr "" "Project-Id-Version: de\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2009-01-09 00:39+0100\n" -"PO-Revision-Date: 2009-01-09 00:38+0100\n" -"Last-Translator: Bjoern Voigt <bjoern@cs.tu-berlin.de>\n" -"Language-Team: Deutsch <de@li.org>\n" +"POT-Creation-Date: 2009-02-18 21:09+0100\n" +"PO-Revision-Date: 2009-02-18 21:09+0100\n" +"Last-Translator: Jochen Kemnade <jochenkemnade@web.de>\n" +"Language-Team: German <de@li.org>\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-Generator: KBabel 1.11.4\n" +"X-Generator: Lokalize 0.2\n" #. Translators may want to transliterate the name. #. It is not to be translated. @@ -36,7 +36,7 @@ "Usage: %s [OPTION]...\n" "\n" " -c, --config=DIR use DIR for config files\n" -" -d, --debug print debugging messages to stdout\n" +" -d, --debug print debugging messages to stderr\n" " -h, --help display this help and exit\n" " -n, --nologin don't automatically login\n" " -v, --version display the current version and exit\n" @@ -45,7 +45,7 @@ "Benutzung: %s [OPTION]...\n" "\n" " -c, --config=VERZ benutze VERZ als Konfigurationsverzeichnis\n" -" -d, --debug drucke Debugging-Meldungen nach stdout\n" +" -d, --debug drucke Debugging-Meldungen nach stderr\n" " -h, --help zeigt diese Hilfe und beendet das Programm\n" " -n, --nologin nicht automatisch anmelden\n" " -v, --version zeigt aktuelle Version und beendet das Programm\n" @@ -1172,7 +1172,6 @@ msgid "Change status to" msgstr "Ändere Status zu" -#. Conversations msgid "Conversations" msgstr "Unterhaltungen" @@ -4033,7 +4032,7 @@ msgid "Nick changing not supported in non-MUC chatrooms" msgstr "" -"Die Änderung des Nick-Namens wird in nicht-MUC Chaträumen nicht unterstützt" +"Die Änderung des Nick-Namens wird in nicht-MUC-Chaträumen nicht unterstützt" msgid "Error retrieving room list" msgstr "Fehler beim Empfangen der Raumliste" @@ -6975,6 +6974,7 @@ msgid "Get AIM Info" msgstr "AIM-Info" +#. We only do this if the user is in our buddy list msgid "Edit Buddy Comment" msgstr "Buddy-Kommentar bearbeiten" @@ -7626,6 +7626,9 @@ msgid "Show server news" msgstr "Server-News anzeigen" +msgid "Show chat room when msg comes" +msgstr "Chatraum zeigen, wenn Nachricht empfangen wird" + msgid "Keep alive interval (seconds)" msgstr "Intervall zum Aufrechterhalten der Verbindung (Sekunden)" @@ -11365,6 +11368,9 @@ msgid "Macedonian" msgstr "Makedonisch" +msgid "Mongolian" +msgstr "Mongolisch" + msgid "Bokmål Norwegian" msgstr "Bokmål Norwegisch" @@ -11478,8 +11484,27 @@ "geschützt. Die Datei 'COPYRIGHT' enthält die komplette Liste der " "Mitwirkenden. Wir übernehmen keine Haftung für dieses Programm.<BR><BR>" -msgid "<FONT SIZE=\"4\">IRC:</FONT> #pidgin on irc.freenode.net<BR><BR>" -msgstr "<FONT SIZE=\"4\">IRC:</FONT> #pidgin auf irc.freenode.net<BR><BR>" +msgid "" +"<FONT SIZE=\"4\">FAQ:</FONT> <A HREF=\"http://developer.pidgin.im/wiki/FAQ" +"\">http://developer.pidgin.im/wiki/FAQ</A><BR/><BR/>" +msgstr "" +"<FONT SIZE=\"4\">FAQ:</FONT> <A HREF=\"http://developer.pidgin.im/wiki/FAQ" +"\">http://developer.pidgin.im/wiki/FAQ</A><BR/><BR/>" + +msgid "" +"<FONT SIZE=\"4\">Help via e-mail:</FONT> <A HREF=\"mailto:support@pidgin.im" +"\">support@pidgin.im</A><BR/><BR/>" +msgstr "" +"<FONT SIZE=\"4\">Hilfe per E-Mail:</FONT> <A HREF=\"mailto:support@pidgin.im" +"\">support@pidgin.im</A><BR/><BR/>" + +msgid "" +"<FONT SIZE=\"4\">IRC Channel:</FONT> #pidgin on irc.freenode.net<BR><BR>" +msgstr "" +"<FONT SIZE=\"4\">IRC-Kanal:</FONT> #pidgin auf irc.freenode.net<BR><BR>" + +msgid "<FONT SIZE=\"4\">XMPP MUC:</FONT> devel@conference.pidgin.im<BR><BR>" +msgstr "<FONT SIZE=\"4\">XMPP-MUC:</FONT> devel@conference.pidgin.im<BR><BR>" msgid "Current Developers" msgstr "Aktuelle Entwickler" @@ -11908,7 +11933,7 @@ msgstr "Dieses Thema verfügt über keine Smileys." msgid "_Font" -msgstr "_Schrift" +msgstr "S_chrift" msgid "Group Items" msgstr "Elemente gruppieren" @@ -12143,6 +12168,9 @@ msgid "Pidgin" msgstr "Pidgin" +msgid "Exiting because another libpurple client is already running.\n" +msgstr "Wird geschlossen, da bereits ein anderer libpurple-Client läuft\n" + msgid "Open All Messages" msgstr "Alle Nachrichten öffnen" @@ -12482,6 +12510,10 @@ msgid "No proxy" msgstr "Kein Proxy" +#. This is a global option that affects SOCKS4 usage even with account-specific proxy settings +msgid "Use remote DNS with SOCKS4 proxies" +msgstr "Remote-DNS mit SOCKS4-Proxys benuten" + msgid "_User:" msgstr "_Benutzer:" @@ -13938,9 +13970,6 @@ msgid "Only when docked" msgstr "Nur wenn angedockt" -msgid "_Flash window when chat messages are received" -msgstr "_Fenster blinkt, wenn Chat-Nachrichten empfangen werden" - msgid "Windows Pidgin Options" msgstr "Windows-Pidgin-Optionen"