# HG changeset patch # User Mike Ruprecht # Date 1238983660 0 # Node ID 2a34a32047ba8f702912739fa3bec49c3d671a8a # Parent 30c870ee4ec942f372c059a395fd71b4933bbfbf# Parent 7f92904b00d9ab8c6f516d542c3e18624caefab4 merge of '0f3cc5eaf6cb9aff180d63efb1dee828936078d1' and 'f917b4632a54553364f64ef2a02dfc4a6e015ea7' diff -r 30c870ee4ec9 -r 2a34a32047ba COPYRIGHT --- a/COPYRIGHT Mon Apr 06 02:06:39 2009 +0000 +++ b/COPYRIGHT Mon Apr 06 02:07:40 2009 +0000 @@ -19,6 +19,7 @@ Christopher Ayoup Alex Badea John Bailey +Arunan Balasubramaniam R. Tyler Ballance Chris Banal Luca Barbato @@ -332,10 +333,9 @@ Joao Luís Marques Pinto Aleksander Piotrowski Julien Pivotto +Robey Pointer Eric Polino Ari Pollak -Robey Pointer -Eric Polino Stephen Pope Nathan Poznick Jory A. Pratt diff -r 30c870ee4ec9 -r 2a34a32047ba ChangeLog --- a/ChangeLog Mon Apr 06 02:06:39 2009 +0000 +++ b/ChangeLog Mon Apr 06 02:07:40 2009 +0000 @@ -13,8 +13,10 @@ * Add voice & video support with Jingle (XEP-0166, 0167, 0176, & 0177), and voice support with GTalk and GMail. (Mike "Maiku" Ruprecht) * Add support for in-band bytestreams for file transfers (XEP-0047). - * Add support for sending attentions (equivalent to "buzz" and "nudge") - using the command /buzz (XEP-0224). + * Add support for sending and receiving attentions (equivalent to "buzz" + and "nudge") using the command /buzz (XEP-0224). + * A buddy's local time is displayed in the Get Info dialog if the remote + client supports it. IRC: * Correctly handle WHOIS for users who are joined to a large number of @@ -35,6 +37,10 @@ * The New Account dialog is now broken into three tabs. Proxy configuration has been moved from the Advanced tab to the new tab. + Finch: + * The hardware cursor is updated correctly. This will be useful + especially for users of braille terminals, screen readers etc. + version 2.5.5 (03/01/2009): libpurple: * Fix a crash when removing an account with an unknown protocol id. diff -r 30c870ee4ec9 -r 2a34a32047ba configure.ac --- a/configure.ac Mon Apr 06 02:06:39 2009 +0000 +++ b/configure.ac Mon Apr 06 02:07:40 2009 +0000 @@ -788,12 +788,19 @@ dnl ####################################################################### AC_ARG_ENABLE(vv, [AC_HELP_STRING([--disable-vv], [compile without voice and video support])], - enable_vv="$enableval", enable_vv="yes") + [enable_vv="$enableval" force_vv=$enableval], [enable_vv="yes" enable_vv=no]) if test "x$enable_vv" != "xno"; then if test "x$enable_farsight" != "xno" -a "x$enable_gstprops" != "xno"; then AC_DEFINE(USE_VV, 1, [Use voice and video]) else enable_vv="no" + if test "x$force_vv" = "xyes"; then + AC_MSG_ERROR([ + +Dependencies for voice/video were not met. Install the necessary gstreamer and farsight packages first. + + ]) + fi fi fi diff -r 30c870ee4ec9 -r 2a34a32047ba doc/finch.1.in --- a/doc/finch.1.in Mon Apr 06 02:06:39 2009 +0000 +++ b/doc/finch.1.in Mon Apr 06 02:07:40 2009 +0000 @@ -59,7 +59,7 @@ Display the version information window. .SH GNT Shortcuts -You can use the following shortcuts: +You can use the following shortcuts (see the "\*QWidget Actions\*U" section for a more complete list): .TP .B Alt \+ a Bring up a list of available actions. You can use this list to access the @@ -378,6 +378,8 @@ [GntWidget::binding] .br f11 = context-menu +.br +c-x = context-menu [GntWindow::binding] .br diff -r 30c870ee4ec9 -r 2a34a32047ba finch/gntblist.c --- a/finch/gntblist.c Mon Apr 06 02:06:39 2009 +0000 +++ b/finch/gntblist.c Mon Apr 06 02:07:40 2009 +0000 @@ -61,7 +61,7 @@ #include #define PREF_ROOT "/finch/blist" -#define TYPING_TIMEOUT 4000 +#define TYPING_TIMEOUT_S 4 #define SHOW_EMPTY_GROUP_TIMEOUT 60 @@ -2016,7 +2016,7 @@ } if (ggblist->typing) - g_source_remove(ggblist->typing); + purple_timeout_remove(ggblist->typing); remove_peripherals(ggblist); if (ggblist->tagged) g_list_free(ggblist->tagged); @@ -2253,7 +2253,7 @@ end: g_free(escnewmessage); if (ggblist->typing) - g_source_remove(ggblist->typing); + purple_timeout_remove(ggblist->typing); ggblist->typing = 0; return FALSE; } @@ -2272,7 +2272,7 @@ /* Move the focus to the entry box */ /* XXX: Make sure the selected status can have a message */ gnt_box_move_focus(GNT_BOX(ggblist->window), 1); - ggblist->typing = g_timeout_add(TYPING_TIMEOUT, (GSourceFunc)remove_typing_cb, NULL); + ggblist->typing = purple_timeout_add_seconds(TYPING_TIMEOUT_S, (GSourceFunc)remove_typing_cb, NULL); } else if (now->type == STATUS_SAVED_ALL) { @@ -2298,7 +2298,7 @@ return FALSE; if (ggblist->typing) - g_source_remove(ggblist->typing); + purple_timeout_remove(ggblist->typing); ggblist->typing = 0; if (text[0] == '\r' && text[1] == 0) @@ -2308,7 +2308,7 @@ return TRUE; } - ggblist->typing = g_timeout_add(TYPING_TIMEOUT, (GSourceFunc)remove_typing_cb, NULL); + ggblist->typing = purple_timeout_add_seconds(TYPING_TIMEOUT_S, (GSourceFunc)remove_typing_cb, NULL); return FALSE; } diff -r 30c870ee4ec9 -r 2a34a32047ba finch/gntmedia.c --- a/finch/gntmedia.c Mon Apr 06 02:06:39 2009 +0000 +++ b/finch/gntmedia.c Mon Apr 06 02:07:40 2009 +0000 @@ -272,7 +272,7 @@ alias); } else { message = g_strdup_printf( - _("%s is trying to start an unsuppoted media session type with you."), + _("%s is trying to start an unsupported media session type with you."), alias); } finch_media_emit_message(gntmedia, message); diff -r 30c870ee4ec9 -r 2a34a32047ba finch/libgnt/gnt.h --- a/finch/libgnt/gnt.h Mon Apr 06 02:06:39 2009 +0000 +++ b/finch/libgnt/gnt.h Mon Apr 06 02:07:40 2009 +0000 @@ -48,6 +48,10 @@ #define G_PARAM_STATIC_BLURB G_PARAM_PRIVATE #endif +#if !GLIB_CHECK_VERSION(2,14,0) + #define g_timeout_add_seconds(time, callback, data) g_timeout_add(time * 1000, callback, data) +#endif + /** * Initialize GNT. */ diff -r 30c870ee4ec9 -r 2a34a32047ba finch/libgnt/gntbox.c --- a/finch/libgnt/gntbox.c Mon Apr 06 02:06:39 2009 +0000 +++ b/finch/libgnt/gntbox.c Mon Apr 06 02:07:40 2009 +0000 @@ -78,13 +78,11 @@ g_list_foreach(box->list, (GFunc)gnt_widget_draw, NULL); - gnt_box_sync_children(box); - if (box->title && !GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_NO_BORDER)) { int pos, right; char *title = g_strdup(box->title); - + get_title_thingies(box, title, &pos, &right); if (gnt_widget_has_focus(widget)) @@ -96,8 +94,8 @@ mvwaddch(widget->window, 0, right, ACS_LTEE | gnt_color_pair(GNT_COLOR_NORMAL)); g_free(title); } - - GNTDEBUG; + + gnt_box_sync_children(box); } static void @@ -723,6 +721,9 @@ if (GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_NO_BORDER)) pos = 0; + if (!box->active) + find_focusable_widget(box); + for (iter = box->list; iter; iter = iter->next) { GntWidget *w = GNT_WIDGET(iter->data); @@ -764,6 +765,9 @@ copywin(w->window, widget->window, 0, 0, y, x, y + height - 1, x + width - 1, FALSE); gnt_widget_set_position(w, x + widget->priv.x, y + widget->priv.y); + if (w == box->active) { + wmove(widget->window, y + getcury(w->window), x + getcurx(w->window)); + } } } diff -r 30c870ee4ec9 -r 2a34a32047ba finch/libgnt/gntcheckbox.c --- a/finch/libgnt/gntcheckbox.c Mon Apr 06 02:06:39 2009 +0000 +++ b/finch/libgnt/gntcheckbox.c Mon Apr 06 02:07:40 2009 +0000 @@ -42,7 +42,7 @@ type = GNT_COLOR_HIGHLIGHT; else type = GNT_COLOR_NORMAL; - + wbkgdset(widget->window, '\0' | gnt_color_pair(type)); text = g_strdup_printf("[%c]", cb->checked ? 'X' : ' '); @@ -51,7 +51,8 @@ wbkgdset(widget->window, '\0' | gnt_color_pair(GNT_COLOR_NORMAL)); mvwaddstr(widget->window, 0, 4, GNT_BUTTON(cb)->priv->text); - + wmove(widget->window, 0, 1); + GNTDEBUG; } diff -r 30c870ee4ec9 -r 2a34a32047ba finch/libgnt/gntcombobox.c --- a/finch/libgnt/gntcombobox.c Mon Apr 06 02:06:39 2009 +0000 +++ b/finch/libgnt/gntcombobox.c Mon Apr 06 02:07:40 2009 +0000 @@ -73,7 +73,7 @@ char *text = NULL, *s; GntColorType type; int len; - + if (box->dropdown && box->selected) text = gnt_tree_get_selection_text(GNT_TREE(box->dropdown)); @@ -94,6 +94,7 @@ whline(widget->window, ' ' | gnt_color_pair(type), widget->priv.width - 4 - len); mvwaddch(widget->window, 1, widget->priv.width - 3, ACS_VLINE | gnt_color_pair(GNT_COLOR_NORMAL)); mvwaddch(widget->window, 1, widget->priv.width - 2, ACS_DARROW | gnt_color_pair(GNT_COLOR_NORMAL)); + wmove(widget->window, 1, 1); g_free(text); GNTDEBUG; diff -r 30c870ee4ec9 -r 2a34a32047ba finch/libgnt/gntentry.c --- a/finch/libgnt/gntentry.c Mon Apr 06 02:06:39 2009 +0000 +++ b/finch/libgnt/gntentry.c Mon Apr 06 02:07:40 2009 +0000 @@ -271,6 +271,7 @@ GntEntry *entry = GNT_ENTRY(widget); int stop; gboolean focus; + int curpos; if ((focus = gnt_widget_has_focus(widget))) wbkgdset(widget->window, '\0' | gnt_color_pair(GNT_COLOR_TEXT_NORMAL)); @@ -289,9 +290,10 @@ if (stop < widget->priv.width) mvwhline(widget->window, 0, stop, ENTRY_CHAR, widget->priv.width - stop); + curpos = gnt_util_onscreen_width(entry->scroll, entry->cursor); if (focus) - mvwchgat(widget->window, 0, gnt_util_onscreen_width(entry->scroll, entry->cursor), - 1, A_REVERSE, GNT_COLOR_TEXT_NORMAL, NULL); + mvwchgat(widget->window, 0, curpos, 1, A_REVERSE, GNT_COLOR_TEXT_NORMAL, NULL); + wmove(widget->window, 0, curpos); GNTDEBUG; } diff -r 30c870ee4ec9 -r 2a34a32047ba finch/libgnt/gnttextview.c --- a/finch/libgnt/gnttextview.c Mon Apr 06 02:06:39 2009 +0000 +++ b/finch/libgnt/gnttextview.c Mon Apr 06 02:07:40 2009 +0000 @@ -177,7 +177,7 @@ gnt_color_pair(GNT_COLOR_HIGHLIGHT_D)); } - GNTDEBUG; + wmove(widget->window, 0, 0); } static void diff -r 30c870ee4ec9 -r 2a34a32047ba finch/libgnt/gnttree.c --- a/finch/libgnt/gnttree.c Mon Apr 06 02:06:39 2009 +0000 +++ b/finch/libgnt/gnttree.c Mon Apr 06 02:07:40 2009 +0000 @@ -28,7 +28,7 @@ #include #include -#define SEARCH_TIMEOUT 4000 /* 4 secs */ +#define SEARCH_TIMEOUT_S 4 /* 4 secs */ #define SEARCHING(tree) (tree->priv->search && tree->priv->search->len > 0) #define COLUMN_INVISIBLE(tree, index) (tree->columns[index].flags & GNT_TREE_COLUMN_INVISIBLE) @@ -420,6 +420,7 @@ GntTreeRow *row; int pos, up, down = 0; int rows, scrcol; + int current = 0; if (!GNT_WIDGET_IS_FLAG_SET(GNT_WIDGET(tree), GNT_WIDGET_MAPPED)) return; @@ -518,6 +519,7 @@ if (row == tree->current) { + current = i; attr |= A_BOLD; if (gnt_widget_has_focus(widget)) attr |= gnt_color_pair(GNT_COLOR_HIGHLIGHT); @@ -606,6 +608,7 @@ mvwaddnstr(widget->window, widget->priv.height - pos - 1, pos, tree->priv->search->str, str - tree->priv->search->str); } + wmove(widget->window, current, pos); gnt_widget_queue_update(widget); } @@ -818,7 +821,7 @@ gnt_bindable_perform_action_key(GNT_BINDABLE(tree), text); } g_source_remove(tree->priv->search_timeout); - tree->priv->search_timeout = g_timeout_add(SEARCH_TIMEOUT, search_timeout, tree); + tree->priv->search_timeout = g_timeout_add_seconds(SEARCH_TIMEOUT_S, search_timeout, tree); return TRUE; } else if (text[0] == ' ' && text[1] == 0) { /* Space pressed */ @@ -930,7 +933,7 @@ return FALSE; GNT_WIDGET_SET_FLAGS(GNT_WIDGET(tree), GNT_WIDGET_DISABLE_ACTIONS); tree->priv->search = g_string_new(NULL); - tree->priv->search_timeout = g_timeout_add(SEARCH_TIMEOUT, search_timeout, tree); + tree->priv->search_timeout = g_timeout_add_seconds(SEARCH_TIMEOUT_S, search_timeout, tree); return TRUE; } diff -r 30c870ee4ec9 -r 2a34a32047ba finch/libgnt/gntwm.c --- a/finch/libgnt/gntwm.c Mon Apr 06 02:06:39 2009 +0000 +++ b/finch/libgnt/gntwm.c Mon Apr 06 02:07:40 2009 +0000 @@ -135,6 +135,17 @@ src = widget->window; dst = node->window; copywin(src, dst, node->scroll, 0, 0, 0, getmaxy(dst) - 1, getmaxx(dst) - 1, 0); + + /* Update the hardware cursor */ + if (GNT_IS_WINDOW(widget) || GNT_IS_BOX(widget)) { + GntWidget *active = GNT_BOX(widget)->active; + if (active) { + int curx = active->priv.x + getcurx(active->window); + int cury = active->priv.y + getcury(active->window); + if (wmove(node->window, cury - widget->priv.y, curx - widget->priv.x) != OK) + wmove(node->window, 0, 0); + } + } } /** @@ -397,7 +408,7 @@ wm->positions = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); if (gnt_style_get_bool(GNT_STYLE_REMPOS, TRUE)) read_window_positions(wm); - g_timeout_add(IDLE_CHECK_INTERVAL * 1000, check_idle, NULL); + g_timeout_add_seconds(IDLE_CHECK_INTERVAL, check_idle, NULL); time(&last_active_time); gnt_wm_switch_workspace(wm, 0); } @@ -1101,8 +1112,8 @@ g_hash_table_foreach(wm->nodes, (GHFunc)refresh_node, GINT_TO_POINTER(TRUE)); g_signal_emit(wm, signals[SIG_TERMINAL_REFRESH], 0); + gnt_ws_draw_taskbar(wm->cws, TRUE); update_screen(wm); - gnt_ws_draw_taskbar(wm->cws, TRUE); curs_set(0); /* endwin resets the cursor to normal */ return TRUE; @@ -1872,8 +1883,8 @@ } } + gnt_ws_draw_taskbar(wm->cws, FALSE); update_screen(wm); - gnt_ws_draw_taskbar(wm->cws, FALSE); } void gnt_wm_window_decorate(GntWM *wm, GntWidget *widget) @@ -1885,6 +1896,7 @@ { GntWS *s; int pos; + gboolean transient = !!GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_TRANSIENT); s = gnt_wm_widget_find_workspace(wm, widget); @@ -1908,10 +1920,12 @@ if (s->ordered && wm->cws == s) gnt_wm_raise_window(wm, s->ordered->data); } + } else if (transient && wm->cws && wm->cws->ordered) { + gnt_wm_update_window(wm, wm->cws->ordered->data); } + gnt_ws_draw_taskbar(wm->cws, FALSE); update_screen(wm); - gnt_ws_draw_taskbar(wm->cws, FALSE); } time_t gnt_wm_get_idle_time() @@ -2119,7 +2133,7 @@ if (write_timeout) { g_source_remove(write_timeout); } - write_timeout = g_timeout_add(10000, write_already, wm); + write_timeout = g_timeout_add_seconds(10, write_already, wm); } void gnt_wm_move_window(GntWM *wm, GntWidget *widget, int x, int y) @@ -2181,8 +2195,8 @@ GntNode *nd = g_hash_table_lookup(wm->nodes, wm->_list.window); top_panel(nd->panel); } + gnt_ws_draw_taskbar(wm->cws, FALSE); update_screen(wm); - gnt_ws_draw_taskbar(wm->cws, FALSE); } void gnt_wm_update_window(GntWM *wm, GntWidget *widget) @@ -2207,8 +2221,8 @@ if (ws == wm->cws || GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_TRANSIENT)) { gnt_wm_copy_win(widget, node); + gnt_ws_draw_taskbar(wm->cws, FALSE); update_screen(wm); - gnt_ws_draw_taskbar(wm->cws, FALSE); } else if (ws && ws != wm->cws && GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_URGENT)) { if (!act || (act && !g_list_find(act, ws))) act = g_list_prepend(act, ws); diff -r 30c870ee4ec9 -r 2a34a32047ba finch/plugins/gntgf.c --- a/finch/plugins/gntgf.c Mon Apr 06 02:06:39 2009 +0000 +++ b/finch/plugins/gntgf.c Mon Apr 06 02:07:40 2009 +0000 @@ -47,6 +47,7 @@ #include #include #include +#include #include #include @@ -75,7 +76,7 @@ { toasters = g_list_remove(toasters, toast); gnt_widget_destroy(toast->window); - g_source_remove(toast->timer); + purple_timeout_remove(toast->timer); g_free(toast); } @@ -220,7 +221,7 @@ } gnt_widget_draw(window); - toast->timer = g_timeout_add(4000, (GSourceFunc)remove_toaster, toast); + toast->timer = purple_timeout_add_seconds(4, (GSourceFunc)remove_toaster, toast); toasters = g_list_prepend(toasters, toast); } diff -r 30c870ee4ec9 -r 2a34a32047ba libpurple/media-gst.h --- a/libpurple/media-gst.h Mon Apr 06 02:06:39 2009 +0000 +++ b/libpurple/media-gst.h Mon Apr 06 02:07:40 2009 +0000 @@ -24,8 +24,8 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef __MEDIA_GST_H_ -#define __MEDIA_GST_H_ +#ifndef _PURPLE_MEDIA_GST_H_ +#define _PURPLE_MEDIA_GST_H_ #include "media.h" #include "mediamanager.h" @@ -81,6 +81,8 @@ * Gets the element type's GType. * * @return The element type's GType. + * + * @since 2.6.0 */ GType purple_media_element_type_get_type(void); @@ -88,6 +90,8 @@ * Gets the element info's GType. * * @return The element info's GType. + * + * @since 2.6.0 */ GType purple_media_element_info_get_type(void); @@ -98,6 +102,8 @@ * @param sess_id The session id of the session to get the source from. * * @return The source retrieved. + * + * @since 2.6.0 */ GstElement *purple_media_get_src(PurpleMedia *media, const gchar *sess_id); @@ -109,6 +115,8 @@ * @param participant Optionally, the participant of the stream to get the tee from. * * @return The GstTee element from the chosen session/stream. + * + * @since 2.6.0 */ GstElement *purple_media_get_tee(PurpleMedia *media, const gchar *session_id, const gchar *participant); @@ -120,6 +128,8 @@ * @param manager The media manager to get the pipeline from. * * @return The pipeline. + * + * @since 2.6.0 */ GstElement *purple_media_manager_get_pipeline(PurpleMediaManager *manager); @@ -128,6 +138,8 @@ * * @param manager The media manager to use to obtain the source/sink. * @param type The type of source/sink to get. + * + * @since 2.6.0 */ GstElement *purple_media_manager_get_element(PurpleMediaManager *manager, PurpleMediaSessionType type, PurpleMedia *media, @@ -158,4 +170,4 @@ G_END_DECLS -#endif /* __MEDIA_GST_H_ */ +#endif /* _PURPLE_MEDIA_GST_H_ */ diff -r 30c870ee4ec9 -r 2a34a32047ba libpurple/media.h --- a/libpurple/media.h Mon Apr 06 02:06:39 2009 +0000 +++ b/libpurple/media.h Mon Apr 06 02:07:40 2009 +0000 @@ -24,11 +24,8 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef __MEDIA_H_ -#define __MEDIA_H_ - -#include "signals.h" -#include "util.h" +#ifndef _PURPLE_MEDIA_H_ +#define _PURPLE_MEDIA_H_ #include #include @@ -129,6 +126,9 @@ PURPLE_MEDIA_NETWORK_PROTOCOL_TCP, } PurpleMediaNetworkProtocol; +#include "signals.h" +#include "util.h" + #ifdef __cplusplus extern "C" { #endif @@ -137,6 +137,8 @@ * Gets the media session type's GType * * @return The media session type's GType. + * + * @since 2.6.0 */ GType purple_media_session_type_get_type(void); @@ -144,6 +146,8 @@ * Gets the media candidate type's GType * * @return The media candidate type's GType. + * + * @since 2.6.0 */ GType purple_media_candidate_type_get_type(void); @@ -151,6 +155,8 @@ * Gets the media network protocol's GType * * @return The media network protocol's GType. + * + * @since 2.6.0 */ GType purple_media_network_protocol_get_type(void); @@ -158,6 +164,8 @@ * Gets the media class's GType * * @return The media class's GType. + * + * @since 2.6.0 */ GType purple_media_get_type(void); @@ -165,6 +173,8 @@ * Gets the type of the state-changed enum * * @return The state-changed enum's GType + * + * @since 2.6.0 */ GType purple_media_state_changed_get_type(void); @@ -172,6 +182,8 @@ * Gets the type of the info type enum * * @return The info type enum's GType + * + * @since 2.6.0 */ GType purple_media_info_type_get_type(void); @@ -179,6 +191,8 @@ * Gets the type of the media candidate structure. * * @return The media canditate's GType + * + * @since 2.6.0 */ GType purple_media_candidate_get_type(void); @@ -193,6 +207,8 @@ * @param port The network port. * * @return The newly created PurpleMediaCandidate instance. + * + * @since 2.6.0 */ PurpleMediaCandidate *purple_media_candidate_new( const gchar *foundation, guint component_id, @@ -206,6 +222,8 @@ * @param candidates The list of candidates to be copied. * * @return The copy of the GList. + * + * @since 2.6.0 */ GList *purple_media_candidate_list_copy(GList *candidates); @@ -213,6 +231,8 @@ * Frees a GList of PurpleMediaCandidate and its contents. * * @param candidates The list of candidates to be freed. + * + * @since 2.6.0 */ void purple_media_candidate_list_free(GList *candidates); @@ -235,6 +255,8 @@ * Gets the type of the media codec structure. * * @return The media codec's GType + * + * @since 2.6.0 */ GType purple_media_codec_get_type(void); @@ -247,6 +269,8 @@ * @param clock_rate The clock rate this codec encodes at, if applicable. * * @return The newly created PurpleMediaCodec. + * + * @since 2.6.0 */ PurpleMediaCodec *purple_media_codec_new(int id, const char *encoding_name, PurpleMediaSessionType media_type, guint clock_rate); @@ -263,6 +287,8 @@ * @param codec The codec to create the string of. * * @return The new string representation. + * + * @since 2.6.0 */ gchar *purple_media_codec_to_string(const PurpleMediaCodec *codec); @@ -272,6 +298,8 @@ * @param codec The codec to add the parameter to. * @param name The name of the parameter to add. * @param value The value of the parameter to add. + * + * @since 2.6.0 */ void purple_media_codec_add_optional_parameter(PurpleMediaCodec *codec, const gchar *name, const gchar *value); @@ -281,6 +309,8 @@ * * @param codec The codec to remove the parameter from. * @param param A pointer to the parameter to remove. + * + * @since 2.6.0 */ void purple_media_codec_remove_optional_parameter(PurpleMediaCodec *codec, PurpleKeyValuePair *param); @@ -293,6 +323,8 @@ * @param value The value to search for or NULL. * * @return The value found or NULL. + * + * @since 2.6.0 */ PurpleKeyValuePair *purple_media_codec_get_optional_parameter( PurpleMediaCodec *codec, const gchar *name, @@ -304,6 +336,8 @@ * @param codecs The list of codecs to be copied. * * @return The copy of the GList. + * + * @since 2.6.0 */ GList *purple_media_codec_list_copy(GList *codecs); @@ -311,6 +345,8 @@ * Frees a GList of PurpleMediaCodec and its contents. * * @param codecs The list of codecs to be freed. + * + * @since 2.6.0 */ void purple_media_codec_list_free(GList *codecs); @@ -320,6 +356,8 @@ * @param media The media session to retrieve session names from. * * @return GList of session names. + * + * @since 2.6.0 */ GList *purple_media_get_session_names(PurpleMedia *media); @@ -329,6 +367,8 @@ * @param media The media session to retrieve the connection from. * * @return The connection retrieved. + * + * @since 2.6.0 */ PurpleConnection *purple_media_get_connection(PurpleMedia *media); @@ -338,6 +378,8 @@ * @param media The media session to retrieve the prpl data from. * * @return The prpl data retrieved. + * + * @since 2.6.0 */ gpointer purple_media_get_prpl_data(PurpleMedia *media); @@ -346,6 +388,8 @@ * * @param media The media session to set the prpl data on. * @param prpl_data The data to set on the media session. + * + * @since 2.6.0 */ void purple_media_set_prpl_data(PurpleMedia *media, gpointer prpl_data); @@ -355,6 +399,8 @@ * @param media The media object to set the state on. * @param error The format of the error message to send in the signal. * @param ... The arguments to plug into the format. + * + * @since 2.6.0 */ void purple_media_error(PurpleMedia *media, const gchar *error, ...); @@ -364,6 +410,8 @@ * @param media The media object with which to end streams. * @param session_id The session to end streams on. * @param participant The participant to end streams with. + * + * @since 2.6.0 */ void purple_media_end(PurpleMedia *media, const gchar *session_id, const gchar *participant); @@ -376,6 +424,8 @@ * @param session_id The id of the session of the stream being signaled. * @param participant The participant of the stream being signaled. * @param local TRUE if the info originated locally, FALSE if on the remote end. + * + * @since 2.6.0 */ void purple_media_stream_info(PurpleMedia *media, PurpleMediaInfoType type, const gchar *session_id, const gchar *participant, @@ -397,6 +447,8 @@ * @param params The parameters to pass to Farsight. * * @return @c TRUE The stream was added successfully, @c FALSE otherwise. + * + * @since 2.6.0 */ gboolean purple_media_add_stream(PurpleMedia *media, const gchar *sess_id, const gchar *who, PurpleMediaSessionType type, @@ -410,6 +462,8 @@ * @param sess_id The session id of the session to get the type from. * * @return The retreived session type. + * + * @since 2.6.0 */ PurpleMediaSessionType purple_media_get_session_type(PurpleMedia *media, const gchar *sess_id); @@ -419,6 +473,8 @@ * @param media The media object to get the manager instance from. * * @return The PurpleMediaManager instance retrieved. + * + * @since 2.6.0 */ struct _PurpleMediaManager *purple_media_get_manager(PurpleMedia *media); @@ -429,6 +485,8 @@ * @param sess_id The session id of the session to get the codecs from. * * @return The retreieved codecs. + * + * @since 2.6.0 */ GList *purple_media_get_codecs(PurpleMedia *media, const gchar *sess_id); @@ -439,6 +497,8 @@ * @param sess_id The session id of the session find the stream in. * @param name The name of the remote user to add the candidates for. * @param remote_candidates The remote candidates to add. + * + * @since 2.6.0 */ void purple_media_add_remote_candidates(PurpleMedia *media, const gchar *sess_id, @@ -451,6 +511,8 @@ * @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 candidates from. + * + * @since 2.6.0 */ GList *purple_media_get_local_candidates(PurpleMedia *media, const gchar *sess_id, @@ -495,6 +557,8 @@ * @param name The name of the remote user to get the candidates from. * * @return @c TRUE The codecs were set successfully, or @c FALSE otherwise. + * + * @since 2.6.0 */ gboolean purple_media_set_remote_codecs(PurpleMedia *media, const gchar *sess_id, const gchar *name, GList *codecs); @@ -507,6 +571,8 @@ * @param participant The remote user to check for. * * @return @c TRUE All streams for the given session_id/participant combination have candidates prepared, @c FALSE otherwise. + * + * @since 2.6.0 */ gboolean purple_media_candidates_prepared(PurpleMedia *media, const gchar *session_id, const gchar *participant); @@ -519,6 +585,8 @@ * @param codec The codec to set the session to stream. * * @return @c TRUE The codec was successfully changed, or @c FALSE otherwise. + * + * @since 2.6.0 */ gboolean purple_media_set_send_codec(PurpleMedia *media, const gchar *sess_id, PurpleMediaCodec *codec); @@ -529,6 +597,8 @@ * @param sess_id The session id of the session to check. * * @return @c TRUE The codecs are ready, or @c FALSE otherwise. + * + * @since 2.6.0 */ gboolean purple_media_codecs_ready(PurpleMedia *media, const gchar *sess_id); @@ -540,6 +610,8 @@ * @param participant The participant of the stream to check. * * @return TRUE if the local user is the stream's initator, else FALSE. + * + * @since 2.6.0 */ gboolean purple_media_is_initiator(PurpleMedia *media, const gchar *sess_id, const gchar *participant); @@ -552,6 +624,8 @@ * @param participant The participant to check. * * @return @c TRUE The selected streams have been accepted, or @c FALSE otherwise. + * + * @since 2.6.0 */ gboolean purple_media_accepted(PurpleMedia *media, const gchar *sess_id, const gchar *participant); @@ -562,6 +636,8 @@ * @param media The media object the sessions are in. * @param session_id The session to select (if any). * @param level The level to set the volume to. + * + * @since 2.6.0 */ void purple_media_set_input_volume(PurpleMedia *media, const gchar *session_id, double level); @@ -572,6 +648,8 @@ * @param session_id The session to limit the streams to (if any). * @param participant The participant to limit the streams to (if any). * @param level The level to set the volume to. + * + * @since 2.6.0 */ void purple_media_set_output_volume(PurpleMedia *media, const gchar *session_id, const gchar *participant, double level); @@ -585,6 +663,8 @@ * @param window_id The window id use for embedding the video in. * * @return An id to reference the output window. + * + * @since 2.6.0 */ gulong purple_media_set_output_window(PurpleMedia *media, const gchar *session_id, const gchar *participant, @@ -594,6 +674,8 @@ * Removes all output windows from a given media session. * * @param media The instance to remove all output windows from. + * + * @since 2.6.0 */ void purple_media_remove_output_windows(PurpleMedia *media); @@ -603,4 +685,4 @@ G_END_DECLS -#endif /* __MEDIA_H_ */ +#endif /* _PURPLE_MEDIA_H_ */ diff -r 30c870ee4ec9 -r 2a34a32047ba libpurple/mediamanager.h --- a/libpurple/mediamanager.h Mon Apr 06 02:06:39 2009 +0000 +++ b/libpurple/mediamanager.h Mon Apr 06 02:07:40 2009 +0000 @@ -24,12 +24,17 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef __MEDIA_MANAGER_H_ -#define __MEDIA_MANAGER_H_ +#ifndef _PURPLE_MEDIA_MANAGER_H_ +#define _PURPLE_MEDIA_MANAGER_H_ #include #include +/** @copydoc _PurpleMediaManager */ +typedef struct _PurpleMediaManager PurpleMediaManager; +/** @copydoc _PurpleMediaManagerClass */ +typedef struct _PurpleMediaManagerClass PurpleMediaManagerClass; + #include "connection.h" #include "media.h" @@ -42,11 +47,6 @@ #define PURPLE_IS_MEDIA_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), PURPLE_TYPE_MEDIA_MANAGER)) #define PURPLE_MEDIA_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_MEDIA_MANAGER, PurpleMediaManagerClass)) -/** @copydoc _PurpleMediaManager */ -typedef struct _PurpleMediaManager PurpleMediaManager; -/** @copydoc _PurpleMediaManagerClass */ -typedef struct _PurpleMediaManagerClass PurpleMediaManagerClass; - #ifdef __cplusplus extern "C" { #endif @@ -60,6 +60,8 @@ * Gets the media manager's GType. * * @return The media manager's GType. + * + * @since 2.6.0 */ GType purple_media_manager_get_type(void); @@ -67,6 +69,8 @@ * Gets the "global" media manager object. It's created if it doesn't already exist. * * @return The "global" instance of the media manager object. + * + * @since 2.6.0 */ PurpleMediaManager *purple_media_manager_get(void); @@ -79,6 +83,8 @@ * @param remote_user The remote user to initiate the session with. * * @return A newly created media session. + * + * @since 2.6.0 */ PurpleMedia *purple_media_manager_create_media(PurpleMediaManager *manager, PurpleConnection *gc, @@ -92,6 +98,8 @@ * @param manager The media manager to get all of the sessions from. * * @return A list of all the media sessions. + * + * @since 2.6.0 */ GList *purple_media_manager_get_media(PurpleMediaManager *manager); @@ -102,6 +110,8 @@ * @param pc The connection the sessions are on. * * @return A list of the media sessions on the given connection. + * + * @since 2.6.0 */ GList *purple_media_manager_get_media_by_connection( PurpleMediaManager *manager, PurpleConnection *pc); @@ -111,6 +121,8 @@ * * @param manager The media manager to remove the media session from. * @param media The media session to remove. + * + * @since 2.6.0 */ void purple_media_manager_remove_media(PurpleMediaManager *manager, @@ -127,6 +139,8 @@ * @param participant The participant the output windows are registered with. * * @return TRUE if it succeeded, FALSE if it failed. + * + * @since 2.6.0 */ gboolean purple_media_manager_create_output_window( PurpleMediaManager *manager, PurpleMedia *media, @@ -142,6 +156,8 @@ * @param window_id The window ID to embed the video in. * * @return A unique ID to the registered output window, 0 if it failed. + * + * @since 2.6.0 */ gulong purple_media_manager_set_output_window(PurpleMediaManager *manager, PurpleMedia *media, const gchar *session_id, @@ -154,6 +170,8 @@ * @param output_window_id The ID of the output window. * * @return TRUE if it found the output window and was successful, else FALSE. + * + * @since 2.6.0 */ gboolean purple_media_manager_remove_output_window( PurpleMediaManager *manager, gulong output_window_id); @@ -165,6 +183,8 @@ * @param media The media instance the output windows were registered for. * @param session_id The session the output windows were registered for. * @param participant The participant the output windows were registered for. + * + * @since 2.6.0 */ void purple_media_manager_remove_output_windows( PurpleMediaManager *manager, PurpleMedia *media, @@ -175,6 +195,8 @@ * * @param manager The manager to set the caps on. * @param caps The caps to set. + * + * @since 2.6.0 */ void purple_media_manager_set_ui_caps(PurpleMediaManager *manager, PurpleMediaCaps caps); @@ -185,6 +207,8 @@ * @param manager The manager to get caps from. * * @return caps The caps retrieved. + * + * @since 2.6.0 */ PurpleMediaCaps purple_media_manager_get_ui_caps(PurpleMediaManager *manager); @@ -196,4 +220,4 @@ G_END_DECLS -#endif /* __MEDIA_MANAGER_H_ */ +#endif /* _PURPLE_MEDIA_MANAGER_H_ */ diff -r 30c870ee4ec9 -r 2a34a32047ba libpurple/protocols/jabber/adhoccommands.c --- a/libpurple/protocols/jabber/adhoccommands.c Mon Apr 06 02:06:39 2009 +0000 +++ b/libpurple/protocols/jabber/adhoccommands.c Mon Apr 06 02:07:40 2009 +0000 @@ -39,16 +39,17 @@ GList *actionslist; } JabberAdHocActionInfo; -void jabber_adhoc_disco_result_cb(JabberStream *js, xmlnode *packet, gpointer data) { - const char *from = xmlnode_get_attrib(packet, "from"); - const char *type = xmlnode_get_attrib(packet, "type"); +void jabber_adhoc_disco_result_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) +{ const char *node; xmlnode *query, *item; JabberID *jabberid; JabberBuddy *jb; JabberBuddyResource *jbr = NULL; - if(strcmp(type, "result")) + if (type == JABBER_IQ_ERROR) return; query = xmlnode_get_child_with_namespace(packet,"query","http://jabber.org/protocol/disco#items"); @@ -95,7 +96,10 @@ } } -static void jabber_adhoc_parse(JabberStream *js, xmlnode *packet, gpointer data); +static void jabber_adhoc_parse(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data); + static void do_adhoc_action_cb(JabberStream *js, xmlnode *result, const char *actionhandle, gpointer user_data) { xmlnode *command; @@ -131,13 +135,16 @@ jabber_iq_send(iq); } -static void jabber_adhoc_parse(JabberStream *js, xmlnode *packet, gpointer data) { +static void +jabber_adhoc_parse(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) +{ xmlnode *command = xmlnode_get_child_with_namespace(packet, "command", "http://jabber.org/protocol/commands"); const char *status = xmlnode_get_attrib(command,"status"); xmlnode *xdata = xmlnode_get_child_with_namespace(command,"x","jabber:x:data"); - const char *type = xmlnode_get_attrib(packet,"type"); - if(type && !strcmp(type,"error")) { + if (type == JABBER_IQ_ERROR) { char *msg = jabber_parse_error(js, packet, NULL); if(!msg) msg = g_strdup(_("Unknown Error")); @@ -147,8 +154,6 @@ g_free(msg); return; } - if(!type || strcmp(type,"result")) - return; if(!status) return; @@ -159,7 +164,7 @@ if(note) { char *data = xmlnode_get_data(note); - purple_notify_info(NULL, xmlnode_get_attrib(packet, "from"), data, NULL); + purple_notify_info(NULL, from, data, NULL); g_free(data); } @@ -199,7 +204,7 @@ actionInfo = g_new0(JabberAdHocActionInfo, 1); actionInfo->sessionid = g_strdup(xmlnode_get_attrib(command,"sessionid")); - actionInfo->who = g_strdup(xmlnode_get_attrib(packet,"from")); + actionInfo->who = g_strdup(from); actionInfo->node = g_strdup(xmlnode_get_attrib(command,"node")); actionInfo->actionslist = actionslist; @@ -218,7 +223,11 @@ } } -static void jabber_adhoc_server_got_list_cb(JabberStream *js, xmlnode *packet, gpointer data) { +static void +jabber_adhoc_server_got_list_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) +{ xmlnode *query = xmlnode_get_child_with_namespace(packet, "query", "http://jabber.org/protocol/disco#items"); xmlnode *item; diff -r 30c870ee4ec9 -r 2a34a32047ba libpurple/protocols/jabber/adhoccommands.h --- a/libpurple/protocols/jabber/adhoccommands.h Mon Apr 06 02:06:39 2009 +0000 +++ b/libpurple/protocols/jabber/adhoccommands.h Mon Apr 06 02:07:40 2009 +0000 @@ -19,14 +19,16 @@ * */ -#ifndef _PURPLE_JABBER_ADHOCCOMMANDS_H_ -#define _PURPLE_JABBER_ADHOCCOMMANDS_H_ +#ifndef PURPLE_JABBER_ADHOCCOMMANDS_H_ +#define PURPLE_JABBER_ADHOCCOMMANDS_H_ #include "jabber.h" /* Implementation of XEP-0050 */ -void jabber_adhoc_disco_result_cb(JabberStream *js, xmlnode *packet, gpointer data); +void jabber_adhoc_disco_result_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data); void jabber_adhoc_execute(JabberStream *js, JabberAdHocCommands *cmd); @@ -36,4 +38,4 @@ void jabber_adhoc_init_server_commands(JabberStream *js, GList **m); -#endif /* _PURPLE_JABBER_ADHOCCOMMANDS_H_ */ +#endif /* PURPLE_JABBER_ADHOCCOMMANDS_H_ */ diff -r 30c870ee4ec9 -r 2a34a32047ba libpurple/protocols/jabber/auth.c --- a/libpurple/protocols/jabber/auth.c Mon Apr 06 02:06:39 2009 +0000 +++ b/libpurple/protocols/jabber/auth.c Mon Apr 06 02:07:40 2009 +0000 @@ -36,8 +36,9 @@ #include "iq.h" #include "notify.h" -static void auth_old_result_cb(JabberStream *js, xmlnode *packet, - gpointer data); +static void auth_old_result_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data); gboolean jabber_process_starttls(JabberStream *js, xmlnode *packet) @@ -566,11 +567,11 @@ #endif } -static void auth_old_result_cb(JabberStream *js, xmlnode *packet, gpointer data) +static void auth_old_result_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) { - const char *type = xmlnode_get_attrib(packet, "type"); - - if(type && !strcmp(type, "result")) { + if (type == JABBER_IQ_RESULT) { jabber_stream_set_state(js, JABBER_STREAM_CONNECTED); } else { PurpleConnectionError reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR; @@ -593,24 +594,20 @@ } } -static void auth_old_cb(JabberStream *js, xmlnode *packet, gpointer data) +static void auth_old_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) { JabberIq *iq; xmlnode *query, *x; - const char *type = xmlnode_get_attrib(packet, "type"); const char *pw = purple_connection_get_password(js->gc); - if(!type) { - purple_connection_error_reason (js->gc, - PURPLE_CONNECTION_ERROR_NETWORK_ERROR, - _("Invalid response from server.")); - return; - } else if(!strcmp(type, "error")) { + if (type == JABBER_IQ_ERROR) { PurpleConnectionError reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR; char *msg = jabber_parse_error(js, packet, &reason); purple_connection_error_reason (js->gc, reason, msg); g_free(msg); - } else if(!strcmp(type, "result")) { + } else if (type == JABBER_IQ_RESULT) { query = xmlnode_get_child(packet, "query"); if(js->stream_id && xmlnode_get_child(query, "digest")) { char *s, *hash; diff -r 30c870ee4ec9 -r 2a34a32047ba libpurple/protocols/jabber/auth.h --- a/libpurple/protocols/jabber/auth.h Mon Apr 06 02:06:39 2009 +0000 +++ b/libpurple/protocols/jabber/auth.h Mon Apr 06 02:07:40 2009 +0000 @@ -19,8 +19,8 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ -#ifndef _PURPLE_JABBER_AUTH_H_ -#define _PURPLE_JABBER_AUTH_H_ +#ifndef PURPLE_JABBER_AUTH_H_ +#define PURPLE_JABBER_AUTH_H_ #include "jabber.h" #include "xmlnode.h" @@ -32,4 +32,4 @@ void jabber_auth_handle_success(JabberStream *js, xmlnode *packet); void jabber_auth_handle_failure(JabberStream *js, xmlnode *packet); -#endif /* _PURPLE_JABBER_AUTH_H_ */ +#endif /* PURPLE_JABBER_AUTH_H_ */ diff -r 30c870ee4ec9 -r 2a34a32047ba libpurple/protocols/jabber/buddy.c --- a/libpurple/protocols/jabber/buddy.c Mon Apr 06 02:06:39 2009 +0000 +++ b/libpurple/protocols/jabber/buddy.c Mon Apr 06 02:07:40 2009 +0000 @@ -155,6 +155,7 @@ jbr->jb = jb; jbr->name = g_strdup(resource); jbr->capabilities = JABBER_CAP_XHTML; + jbr->tz_off = PURPLE_NO_TZ_OFF; jb->resources = g_list_append(jb->resources, jbr); } jbr->priority = priority; @@ -797,6 +798,21 @@ purple_notify_user_info_prepend_pair(user_info, _("Operating System"), jbr->client.os); } } + if (jbr && jbr->tz_off != PURPLE_NO_TZ_OFF) { + time_t now_t; + struct tm *now; + char *timestamp; + time(&now_t); + now_t += jbr->tz_off; + now = gmtime(&now_t); + + timestamp = g_strdup_printf("%s %c%02d%02d", purple_time_format(now), + jbr->tz_off < 0 ? '-' : '+', + abs(jbr->tz_off / (60*60)), + abs((jbr->tz_off % (60*60)) / 60)); + purple_notify_user_info_prepend_pair(user_info, _("Local Time"), timestamp); + g_free(timestamp); + } if(jbir) { if(jbir->idle_seconds > 0) { char *idle = purple_str_seconds_to_string(jbir->idle_seconds); @@ -915,7 +931,7 @@ feature = _("User Gaming"); else if(!strcmp(feature, "http://jabber.org/protocol/viewing")) feature = _("User Viewing"); - else if(!strcmp(feature, "urn:xmpp:ping") || !strcmp(feature, "http://www.xmpp.org/extensions/xep-0199.html#ns")) + else if(!strcmp(feature, "urn:xmpp:ping")) feature = _("Ping"); else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0200.html#ns")) feature = _("Stanza Encryption"); @@ -967,6 +983,22 @@ } } + if (jbr->tz_off != PURPLE_NO_TZ_OFF) { + time_t now_t; + struct tm *now; + char *timestamp; + time(&now_t); + now_t += jbr->tz_off; + now = gmtime(&now_t); + + timestamp = g_strdup_printf("%s %c%02d%02d", purple_time_format(now), + jbr->tz_off < 0 ? '-' : '+', + abs(jbr->tz_off / (60*60)), + abs((jbr->tz_off % (60*60)) / 60)); + purple_notify_user_info_prepend_pair(user_info, _("Local Time"), timestamp); + g_free(timestamp); + } + if(jbr->name && (jbir = g_hash_table_lookup(jbi->resources, jbr->name))) { if(jbir->idle_seconds > 0) { char *idle = purple_str_seconds_to_string(jbir->idle_seconds); @@ -1085,7 +1117,7 @@ feature = _("User Gaming"); else if(!strcmp(feature, "http://jabber.org/protocol/viewing")) feature = _("User Viewing"); - else if(!strcmp(feature, "urn:xmpp:ping") || !strcmp(feature, "http://www.xmpp.org/extensions/xep-0199.html#ns")) + else if(!strcmp(feature, "urn:xmpp:ping")) feature = _("Ping"); else if(!strcmp(feature, "http://www.xmpp.org/extensions/xep-0200.html#ns")) feature = _("Stanza Encryption"); @@ -1151,12 +1183,19 @@ } } -static void jabber_vcard_save_mine(JabberStream *js, xmlnode *packet, gpointer data) +static void jabber_vcard_save_mine(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) { xmlnode *vcard; char *txt; PurpleStoredImage *img; + if (type == JABBER_IQ_ERROR) { + purple_debug_warning("jabber", "Server returned error while retrieving vCard"); + return; + } + if((vcard = xmlnode_get_child(packet, "vCard")) || (vcard = xmlnode_get_child_with_namespace(packet, "query", "vcard-temp"))) { @@ -1187,9 +1226,10 @@ jabber_iq_send(iq); } -static void jabber_vcard_parse(JabberStream *js, xmlnode *packet, gpointer data) +static void jabber_vcard_parse(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) { - const char *id, *from; char *bare_jid; char *text; char *serverside_alias = NULL; @@ -1198,9 +1238,6 @@ JabberBuddyInfo *jbi = data; PurpleNotifyUserInfo *user_info; - from = xmlnode_get_attrib(packet, "from"); - id = xmlnode_get_attrib(packet, "id"); - if(!jbi) return; @@ -1550,19 +1587,16 @@ g_free(jbri); } -static void jabber_version_parse(JabberStream *js, xmlnode *packet, gpointer data) +static void jabber_version_parse(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) { JabberBuddyInfo *jbi = data; - const char *type, *id, *from; xmlnode *query; char *resource_name; g_return_if_fail(jbi != NULL); - type = xmlnode_get_attrib(packet, "type"); - id = xmlnode_get_attrib(packet, "id"); - from = xmlnode_get_attrib(packet, "from"); - jabber_buddy_info_remove_id(jbi, id); if(!from) @@ -1571,7 +1605,7 @@ resource_name = jabber_get_resource(from); if(resource_name) { - if(type && !strcmp(type, "result")) { + if (type == JABBER_IQ_RESULT) { if((query = xmlnode_get_child(packet, "query"))) { JabberBuddyResource *jbr = jabber_buddy_find_resource(jbi->jb, resource_name); if(jbr) { @@ -1594,19 +1628,17 @@ jabber_buddy_info_show_if_ready(jbi); } -static void jabber_last_parse(JabberStream *js, xmlnode *packet, gpointer data) +static void jabber_last_parse(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) { JabberBuddyInfo *jbi = data; xmlnode *query; char *resource_name; - const char *type, *id, *from, *seconds; + const char *seconds; g_return_if_fail(jbi != NULL); - type = xmlnode_get_attrib(packet, "type"); - id = xmlnode_get_attrib(packet, "id"); - from = xmlnode_get_attrib(packet, "from"); - jabber_buddy_info_remove_id(jbi, id); if(!from) @@ -1615,7 +1647,7 @@ resource_name = jabber_get_resource(from); if(resource_name) { - if(type && !strcmp(type, "result")) { + if (type == JABBER_IQ_RESULT) { if((query = xmlnode_get_child(packet, "query"))) { seconds = xmlnode_get_attrib(query, "seconds"); if(seconds) { @@ -1636,6 +1668,56 @@ jabber_buddy_info_show_if_ready(jbi); } +static void jabber_time_parse(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) +{ + JabberBuddyInfo *jbi = data; + JabberBuddyResource *jbr; + char *resource_name; + + g_return_if_fail(jbi != NULL); + + jabber_buddy_info_remove_id(jbi, id); + + if (!from) + return; + + resource_name = jabber_get_resource(from); + jbr = resource_name ? jabber_buddy_find_resource(jbi->jb, resource_name) : NULL; + g_free(resource_name); + if (jbr) { + if (type == JABBER_IQ_RESULT) { + xmlnode *time = xmlnode_get_child(packet, "time"); + xmlnode *tzo = time ? xmlnode_get_child(time, "tzo") : NULL; + char *tzo_data = tzo ? xmlnode_get_data(tzo) : NULL; + if (tzo_data) { + char *c = tzo_data; + int hours, minutes; + if (tzo_data[0] == 'Z' && tzo_data[1] == '\0') { + jbr->tz_off = 0; + } else { + gboolean offset_positive = (tzo_data[0] == '+'); + /* [+-]HH:MM */ + if (((*c == '+' || *c == '-') && (c = c + 1)) && + sscanf(c, "%02d:%02d", &hours, &minutes) == 2) { + jbr->tz_off = 60*60*hours + 60*minutes; + if (!offset_positive) + jbr->tz_off *= -1; + } else { + purple_debug_info("jabber", "Ignoring malformed timezone %s", + tzo_data); + } + } + + g_free(tzo_data); + } + } + } + + jabber_buddy_info_show_if_ready(jbi); +} + void jabber_buddy_remove_all_pending_buddy_info_requests(JabberStream *js) { if (js->pending_buddy_info_requests) @@ -1767,6 +1849,19 @@ jabber_iq_send(iq); } + if (jbr->tz_off == PURPLE_NO_TZ_OFF && + (!jbr->caps || + jabber_resource_has_capability(jbr, "urn:xmpp:time"))) { + xmlnode *child; + iq = jabber_iq_new(js, JABBER_IQ_GET); + xmlnode_set_attrib(iq->node, "to", full_jid); + child = xmlnode_new_child(iq->node, "time"); + xmlnode_set_namespace(child, "urn:xmpp:time"); + jabber_iq_set_callback(iq, jabber_time_parse, jbi); + jbi->ids = g_slist_prepend(jbi->ids, g_strdup(iq->id)); + jabber_iq_send(iq); + } + g_free(full_jid); } @@ -2163,7 +2258,9 @@ g_list_nth_data(row, 0), NULL, NULL); } -static void user_search_result_cb(JabberStream *js, xmlnode *packet, gpointer data) +static void user_search_result_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) { PurpleNotifySearchResults *results; PurpleNotifySearchColumn *column; @@ -2359,15 +2456,16 @@ }; #endif -static void user_search_fields_result_cb(JabberStream *js, xmlnode *packet, gpointer data) +static void user_search_fields_result_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) { xmlnode *query, *x; - const char *from, *type; - if(!(from = xmlnode_get_attrib(packet, "from"))) + if (!from) return; - if(!(type = xmlnode_get_attrib(packet, "type")) || !strcmp(type, "error")) { + if (type == JABBER_IQ_ERROR) { char *msg = jabber_parse_error(js, packet, NULL); if(!msg) diff -r 30c870ee4ec9 -r 2a34a32047ba libpurple/protocols/jabber/buddy.h --- a/libpurple/protocols/jabber/buddy.h Mon Apr 06 02:06:39 2009 +0000 +++ b/libpurple/protocols/jabber/buddy.h Mon Apr 06 02:07:40 2009 +0000 @@ -19,8 +19,8 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ -#ifndef _PURPLE_JABBER_BUDDY_H_ -#define _PURPLE_JABBER_BUDDY_H_ +#ifndef PURPLE_JABBER_BUDDY_H_ +#define PURPLE_JABBER_BUDDY_H_ typedef enum { JABBER_BUDDY_STATE_UNKNOWN = -2, @@ -81,6 +81,8 @@ char *name; char *os; } client; + /* tz_off == PURPLE_NO_TZ_OFF when unset */ + long tz_off; JabberCapsClientInfo *caps; GList *commands; } JabberBuddyResource; @@ -121,4 +123,4 @@ const gchar *cap); gboolean jabber_buddy_has_capability(const JabberBuddy *jb, const gchar *cap); -#endif /* _PURPLE_JABBER_BUDDY_H_ */ +#endif /* PURPLE_JABBER_BUDDY_H_ */ diff -r 30c870ee4ec9 -r 2a34a32047ba libpurple/protocols/jabber/caps.c --- a/libpurple/protocols/jabber/caps.c Mon Apr 06 02:06:39 2009 +0000 +++ b/libpurple/protocols/jabber/caps.c Mon Apr 06 02:07:40 2009 +0000 @@ -369,7 +369,10 @@ } } -static void jabber_caps_ext_iqcb(JabberStream *js, xmlnode *packet, gpointer data) { +static void jabber_caps_ext_iqcb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) +{ /* collect data and fetch all exts */ xmlnode *query = xmlnode_get_child_with_namespace(packet, "query", "http://jabber.org/protocol/disco#info"); jabber_ext_userdata *extuserdata = data; @@ -433,7 +436,10 @@ jabber_caps_get_info_check_completion(userdata); } -static void jabber_caps_client_iqcb(JabberStream *js, xmlnode *packet, gpointer data) { +static void jabber_caps_client_iqcb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) +{ /* collect data and fetch all exts */ xmlnode *query = xmlnode_get_child_with_namespace(packet, "query", "http://jabber.org/protocol/disco#info"); diff -r 30c870ee4ec9 -r 2a34a32047ba libpurple/protocols/jabber/caps.h --- a/libpurple/protocols/jabber/caps.h Mon Apr 06 02:06:39 2009 +0000 +++ b/libpurple/protocols/jabber/caps.h Mon Apr 06 02:07:40 2009 +0000 @@ -19,8 +19,8 @@ * */ -#ifndef _PURPLE_JABBER_CAPS_H_ -#define _PURPLE_JABBER_CAPS_H_ +#ifndef PURPLE_JABBER_CAPS_H_ +#define PURPLE_JABBER_CAPS_H_ typedef struct _JabberCapsClientInfo JabberCapsClientInfo; @@ -46,4 +46,4 @@ void jabber_caps_get_info(JabberStream *js, const char *who, const char *node, const char *ver, const char *ext, jabber_caps_get_info_cb cb, gpointer user_data); void jabber_caps_free_clientinfo(JabberCapsClientInfo *clientinfo); -#endif /* _PURPLE_JABBER_CAPS_H_ */ +#endif /* PURPLE_JABBER_CAPS_H_ */ diff -r 30c870ee4ec9 -r 2a34a32047ba libpurple/protocols/jabber/chat.c --- a/libpurple/protocols/jabber/chat.c Mon Apr 06 02:06:39 2009 +0000 +++ b/libpurple/protocols/jabber/chat.c Mon Apr 06 02:07:40 2009 +0000 @@ -376,21 +376,19 @@ jabber_iq_send(iq); } -static void jabber_chat_room_configure_cb(JabberStream *js, xmlnode *packet, gpointer data) +static void jabber_chat_room_configure_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) { xmlnode *query, *x; - const char *type = xmlnode_get_attrib(packet, "type"); - const char *from = xmlnode_get_attrib(packet, "from"); char *msg; JabberChat *chat; JabberID *jid; - if(!type || !from) + if (!from) return; - - - if(!strcmp(type, "result")) { + if (type == JABBER_IQ_RESULT) { jid = jabber_id_new(from); if(!jid) @@ -416,7 +414,7 @@ return; } } - } else if(!strcmp(type, "error")) { + } else if (type == JABBER_IQ_ERROR) { char *msg = jabber_parse_error(js, packet, NULL); purple_notify_error(js->gc, _("Configuration error"), _("Configuration error"), msg); @@ -486,11 +484,12 @@ g_free(room_jid); } -static void jabber_chat_register_x_data_result_cb(JabberStream *js, xmlnode *packet, gpointer data) +static void +jabber_chat_register_x_data_result_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) { - const char *type = xmlnode_get_attrib(packet, "type"); - - if(type && !strcmp(type, "error")) { + if (type == JABBER_IQ_ERROR) { char *msg = jabber_parse_error(js, packet, NULL); purple_notify_error(js->gc, _("Registration error"), _("Registration error"), msg); @@ -521,19 +520,19 @@ jabber_iq_send(iq); } -static void jabber_chat_register_cb(JabberStream *js, xmlnode *packet, gpointer data) +static void jabber_chat_register_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) { xmlnode *query, *x; - const char *type = xmlnode_get_attrib(packet, "type"); - const char *from = xmlnode_get_attrib(packet, "from"); char *msg; JabberChat *chat; JabberID *jid; - if(!type || !from) + if (!from) return; - if(!strcmp(type, "result")) { + if (type == JABBER_IQ_RESULT) { jid = jabber_id_new(from); if(!jid) @@ -559,7 +558,7 @@ return; } } - } else if(!strcmp(type, "error")) { + } else if (type == JABBER_IQ_ERROR) { char *msg = jabber_parse_error(js, packet, NULL); purple_notify_error(js->gc, _("Registration error"), _("Registration error"), msg); @@ -690,16 +689,17 @@ g_free(room_jid); } -static void roomlist_disco_result_cb(JabberStream *js, xmlnode *packet, gpointer data) +static void roomlist_disco_result_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) { xmlnode *query; xmlnode *item; - const char *type; if(!js->roomlist) return; - if(!(type = xmlnode_get_attrib(packet, "type")) || strcmp(type, "result")) { + if (type == JABBER_IQ_ERROR) { char *err = jabber_parse_error(js, packet, NULL); purple_notify_error(js->gc, _("Error"), _("Error retrieving room list"), err); @@ -988,13 +988,17 @@ return TRUE; } -static void jabber_chat_disco_traffic_cb(JabberStream *js, xmlnode *packet, gpointer data) +static void jabber_chat_disco_traffic_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) { JabberChat *chat; - /*xmlnode *query;*/ - int id = GPOINTER_TO_INT(data); +#if 0 + xmlnode *query, *x; +#endif + int chat_id = GPOINTER_TO_INT(data); - if(!(chat = jabber_chat_find_by_id(js, id))) + if(!(chat = jabber_chat_find_by_id(js, chat_id))) return; /* defaults, in case the conference server doesn't @@ -1002,8 +1006,9 @@ chat->xhtml = TRUE; /* disabling this until more MUC servers support - * announcing this - if(xmlnode_get_child(packet, "error")) { + * announcing this */ +#if 0 + if (type == JABBER_IQ_ERROR) { return; } @@ -1019,7 +1024,7 @@ chat->xhtml = TRUE; } } - */ +#endif } void jabber_chat_disco_traffic(JabberChat *chat) diff -r 30c870ee4ec9 -r 2a34a32047ba libpurple/protocols/jabber/chat.h --- a/libpurple/protocols/jabber/chat.h Mon Apr 06 02:06:39 2009 +0000 +++ b/libpurple/protocols/jabber/chat.h Mon Apr 06 02:07:40 2009 +0000 @@ -19,8 +19,8 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ -#ifndef _PURPLE_JABBER_CHAT_H_ -#define _PURPLE_JABBER_CHAT_H_ +#ifndef PURPLE_JABBER_CHAT_H_ +#define PURPLE_JABBER_CHAT_H_ #include "internal.h" #include "connection.h" @@ -94,4 +94,4 @@ char *jabber_roomlist_room_serialize(PurpleRoomlistRoom *room); -#endif /* _PURPLE_JABBER_CHAT_H_ */ +#endif /* PURPLE_JABBER_CHAT_H_ */ diff -r 30c870ee4ec9 -r 2a34a32047ba libpurple/protocols/jabber/data.c --- a/libpurple/protocols/jabber/data.c Mon Apr 06 02:06:39 2009 +0000 +++ b/libpurple/protocols/jabber/data.c Mon Apr 06 02:07:40 2009 +0000 @@ -200,25 +200,26 @@ } void -jabber_data_parse(JabberStream *js, xmlnode *packet) +jabber_data_parse(JabberStream *js, const char *who, JabberIqType type, + const char *id, xmlnode *data_node) { JabberIq *result = NULL; - const char *who = xmlnode_get_attrib(packet, "from"); - xmlnode *data_node = xmlnode_get_child(packet, "data"); - const JabberData *data = - jabber_data_find_local_by_cid(xmlnode_get_attrib(data_node, "cid")); + const char *cid = xmlnode_get_attrib(data_node, "cid"); + const JabberData *data = cid ? jabber_data_find_local_by_cid(cid) : NULL; if (!data) { xmlnode *item_not_found = xmlnode_new("item-not-found"); result = jabber_iq_new(js, JABBER_IQ_ERROR); - xmlnode_set_attrib(result->node, "to", who); - xmlnode_set_attrib(result->node, "id", xmlnode_get_attrib(packet, "id")); + if (who) + xmlnode_set_attrib(result->node, "to", who); + xmlnode_set_attrib(result->node, "id", id); xmlnode_insert_child(result->node, item_not_found); } else { result = jabber_iq_new(js, JABBER_IQ_RESULT); - xmlnode_set_attrib(result->node, "to", who); - xmlnode_set_attrib(result->node, "id", xmlnode_get_attrib(packet, "id")); + if (who) + xmlnode_set_attrib(result->node, "to", who); + xmlnode_set_attrib(result->node, "id", id); xmlnode_insert_child(result->node, jabber_data_get_xml_definition(data)); } @@ -235,6 +236,8 @@ g_free, jabber_data_delete); remote_data_by_cid = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, jabber_data_delete); + + jabber_iq_register_handler("data", XEP_0231_NAMESPACE, jabber_data_parse); } void diff -r 30c870ee4ec9 -r 2a34a32047ba libpurple/protocols/jabber/data.h --- a/libpurple/protocols/jabber/data.h Mon Apr 06 02:06:39 2009 +0000 +++ b/libpurple/protocols/jabber/data.h Mon Apr 06 02:07:40 2009 +0000 @@ -14,8 +14,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor Boston, MA 02110-1301, USA */ -#ifndef JABBER_DATA_H -#define JABBER_DATA_H +#ifndef PURPLE_JABBER_DATA_H +#define PURPLE_JABBER_DATA_H #include "xmlnode.h" #include "jabber.h" @@ -65,9 +65,10 @@ void jabber_data_associate_remote(JabberData *data); /* handles iq requests */ -void jabber_data_parse(JabberStream *js, xmlnode *packet); +void jabber_data_parse(JabberStream *js, const char *who, JabberIqType type, + const char *id, xmlnode *data_node); void jabber_data_init(void); void jabber_data_uninit(void); -#endif /* JABBER_DATA_H */ +#endif /* PURPLE_JABBER_DATA_H */ diff -r 30c870ee4ec9 -r 2a34a32047ba libpurple/protocols/jabber/disco.c --- a/libpurple/protocols/jabber/disco.c Mon Apr 06 02:06:39 2009 +0000 +++ b/libpurple/protocols/jabber/disco.c Mon Apr 06 02:07:40 2009 +0000 @@ -46,9 +46,11 @@ } static void -jabber_disco_bytestream_server_cb(JabberStream *js, xmlnode *packet, gpointer data) { +jabber_disco_bytestream_server_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) +{ JabberBytestreamsStreamhost *sh = data; - const char *from = xmlnode_get_attrib(packet, "from"); xmlnode *query = xmlnode_get_child_with_namespace(packet, "query", "http://jabber.org/protocol/bytestreams"); @@ -86,29 +88,22 @@ } -void jabber_disco_info_parse(JabberStream *js, xmlnode *packet) { - const char *from = xmlnode_get_attrib(packet, "from"); - const char *type = xmlnode_get_attrib(packet, "type"); +void jabber_disco_info_parse(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *in_query) { - if(!from || !type) + if(!from) return; - if(!strcmp(type, "get")) { + if(type == JABBER_IQ_GET) { xmlnode *query, *identity, *feature; JabberIq *iq; - - xmlnode *in_query; - const char *node = NULL; - - if((in_query = xmlnode_get_child(packet, "query"))) { - node = xmlnode_get_attrib(in_query, "node"); - } - + const char *node = xmlnode_get_attrib(in_query, "node"); iq = jabber_iq_new_query(js, JABBER_IQ_RESULT, "http://jabber.org/protocol/disco#info"); - jabber_iq_set_id(iq, xmlnode_get_attrib(packet, "id")); + jabber_iq_set_id(iq, id); xmlnode_set_attrib(iq->node, "to", from); query = xmlnode_get_child(iq->node, "query"); @@ -127,7 +122,7 @@ SUPPORT_FEATURE("jabber:iq:last") SUPPORT_FEATURE("jabber:iq:oob") SUPPORT_FEATURE("jabber:iq:time") - SUPPORT_FEATURE("xmpp:urn:time") + SUPPORT_FEATURE("urn:xmpp:time") SUPPORT_FEATURE("jabber:iq:version") SUPPORT_FEATURE("jabber:x:conference") SUPPORT_FEATURE("http://jabber.org/protocol/bytestreams") @@ -140,7 +135,6 @@ SUPPORT_FEATURE("http://jabber.org/protocol/si/profile/file-transfer") SUPPORT_FEATURE("http://jabber.org/protocol/xhtml-im") SUPPORT_FEATURE("urn:xmpp:ping") - SUPPORT_FEATURE("http://www.xmpp.org/extensions/xep-0199.html#ns") if(!node) { /* non-caps disco#info, add all enabled extensions */ GList *features; @@ -209,8 +203,7 @@ } jabber_iq_send(iq); - } else if(!strcmp(type, "result")) { - xmlnode *query = xmlnode_get_child(packet, "query"); + } else if(type == JABBER_IQ_RESULT) { xmlnode *child; JabberID *jid; JabberBuddy *jb; @@ -227,7 +220,7 @@ if(jbr) capabilities = jbr->capabilities; - for(child = query->child; child; child = child->next) { + for(child = in_query->child; child; child = child->next) { if(child->type != XMLNODE_TYPE_TAG) continue; @@ -277,7 +270,7 @@ capabilities |= JABBER_CAP_IQ_SEARCH; else if(!strcmp(var, "jabber:iq:register")) capabilities |= JABBER_CAP_IQ_REGISTER; - else if(!strcmp(var, "http://www.xmpp.org/extensions/xep-0199.html#ns")) + else if(!strcmp(var, "urn:xmpp:ping")) capabilities |= JABBER_CAP_PING; else if(!strcmp(var, "http://jabber.org/protocol/commands")) { capabilities |= JABBER_CAP_ADHOC; @@ -298,7 +291,7 @@ jdicd->callback(js, from, capabilities, jdicd->data); g_hash_table_remove(js->disco_callbacks, from); } - } else if(!strcmp(type, "error")) { + } else if(type == JABBER_IQ_ERROR) { JabberID *jid; JabberBuddy *jb; JabberBuddyResource *jbr = NULL; @@ -322,28 +315,23 @@ } } -void jabber_disco_items_parse(JabberStream *js, xmlnode *packet) { - const char *from = xmlnode_get_attrib(packet, "from"); - const char *type = xmlnode_get_attrib(packet, "type"); - - if(type && !strcmp(type, "get")) { +void jabber_disco_items_parse(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *query) { + if(type == JABBER_IQ_GET) { JabberIq *iq = jabber_iq_new_query(js, JABBER_IQ_RESULT, "http://jabber.org/protocol/disco#items"); /* preserve node */ - xmlnode *iq_query = xmlnode_get_child_with_namespace(iq->node,"query","http://jabber.org/protocol/disco#items"); - if(iq_query) { - xmlnode *query = xmlnode_get_child_with_namespace(packet,"query","http://jabber.org/protocol/disco#items"); - if(query) { - const char *node = xmlnode_get_attrib(query,"node"); - if(node) - xmlnode_set_attrib(iq_query,"node",node); - } - } + xmlnode *iq_query = xmlnode_get_child(iq->node, "query"); + const char *node = xmlnode_get_attrib(query, "node"); + if(node) + xmlnode_set_attrib(iq_query,"node",node); - jabber_iq_set_id(iq, xmlnode_get_attrib(packet, "id")); + jabber_iq_set_id(iq, id); - xmlnode_set_attrib(iq->node, "to", from); + if (from) + xmlnode_set_attrib(iq->node, "to", from); jabber_iq_send(iq); } } @@ -408,19 +396,18 @@ } static void -jabber_disco_server_info_result_cb(JabberStream *js, xmlnode *packet, gpointer data) +jabber_disco_server_info_result_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) { xmlnode *query, *child; - const char *from = xmlnode_get_attrib(packet, "from"); - const char *type = xmlnode_get_attrib(packet, "type"); - if((!from || !type) || - (strcmp(from, js->user->domain))) { + if (!from || strcmp(from, js->user->domain)) { jabber_disco_finish_server_info_result_cb(js); return; } - if(strcmp(type, "result")) { + if (type == JABBER_IQ_ERROR) { /* A common way to get here is for the server not to support xmlns http://jabber.org/protocol/disco#info */ jabber_disco_finish_server_info_result_cb(js); return; @@ -486,19 +473,16 @@ } static void -jabber_disco_server_items_result_cb(JabberStream *js, xmlnode *packet, gpointer data) +jabber_disco_server_items_result_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) { xmlnode *query, *child; - const char *from = xmlnode_get_attrib(packet, "from"); - const char *type = xmlnode_get_attrib(packet, "type"); - if(!from || !type) + if (!from || strcmp(from, js->user->domain) != 0) return; - if(strcmp(from, js->user->domain)) - return; - - if(strcmp(type, "result")) + if (type == JABBER_IQ_ERROR) return; while(js->chat_servers) { diff -r 30c870ee4ec9 -r 2a34a32047ba libpurple/protocols/jabber/disco.h --- a/libpurple/protocols/jabber/disco.h Mon Apr 06 02:06:39 2009 +0000 +++ b/libpurple/protocols/jabber/disco.h Mon Apr 06 02:07:40 2009 +0000 @@ -19,20 +19,22 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ -#ifndef _PURPLE_JABBER_DISCO_H_ -#define _PURPLE_JABBER_DISCO_H_ +#ifndef PURPLE_JABBER_DISCO_H_ +#define PURPLE_JABBER_DISCO_H_ #include "jabber.h" typedef void (JabberDiscoInfoCallback)(JabberStream *js, const char *who, JabberCapabilities capabilities, gpointer data); -void jabber_disco_info_parse(JabberStream *js, xmlnode *packet); -void jabber_disco_items_parse(JabberStream *js, xmlnode *packet); +void jabber_disco_info_parse(JabberStream *js, const char *from, + JabberIqType type, const char *id, xmlnode *in_query); +void jabber_disco_items_parse(JabberStream *js, const char *from, + JabberIqType type, const char *id, xmlnode *query); void jabber_disco_items_server(JabberStream *js); void jabber_disco_info_do(JabberStream *js, const char *who, JabberDiscoInfoCallback *callback, gpointer data); -#endif /* _PURPLE_JABBER_DISCO_H_ */ +#endif /* PURPLE_JABBER_DISCO_H_ */ diff -r 30c870ee4ec9 -r 2a34a32047ba libpurple/protocols/jabber/google.c --- a/libpurple/protocols/jabber/google.c Mon Apr 06 02:06:39 2009 +0000 +++ b/libpurple/protocols/jabber/google.c Mon Apr 06 02:07:40 2009 +0000 @@ -374,7 +374,7 @@ } static void -google_session_handle_initiate(JabberStream *js, GoogleSession *session, xmlnode *packet, xmlnode *sess) +google_session_handle_initiate(JabberStream *js, GoogleSession *session, xmlnode *sess, const char *iq_id) { JabberIq *result; GList *codecs = NULL; @@ -440,13 +440,13 @@ purple_media_codec_list_free(codecs); result = jabber_iq_new(js, JABBER_IQ_RESULT); - jabber_iq_set_id(result, xmlnode_get_attrib(packet, "id")); + jabber_iq_set_id(result, iq_id); xmlnode_set_attrib(result->node, "to", session->remote_jid); jabber_iq_send(result); } static void -google_session_handle_candidates(JabberStream *js, GoogleSession *session, xmlnode *packet, xmlnode *sess) +google_session_handle_candidates(JabberStream *js, GoogleSession *session, xmlnode *sess, const char *iq_id) { JabberIq *result; GList *list = NULL; @@ -480,13 +480,13 @@ purple_media_candidate_list_free(list); result = jabber_iq_new(js, JABBER_IQ_RESULT); - jabber_iq_set_id(result, xmlnode_get_attrib(packet, "id")); + jabber_iq_set_id(result, iq_id); xmlnode_set_attrib(result->node, "to", session->remote_jid); jabber_iq_send(result); } static void -google_session_handle_accept(JabberStream *js, GoogleSession *session, xmlnode *packet, xmlnode *sess) +google_session_handle_accept(JabberStream *js, GoogleSession *session, xmlnode *sess, const char *iq_id) { xmlnode *desc_element = xmlnode_get_child(sess, "description"); xmlnode *codec_element = xmlnode_get_child(desc_element, "payload-type"); @@ -514,58 +514,54 @@ NULL, NULL, FALSE); result = jabber_iq_new(js, JABBER_IQ_RESULT); - jabber_iq_set_id(result, xmlnode_get_attrib(packet, "id")); + jabber_iq_set_id(result, iq_id); xmlnode_set_attrib(result->node, "to", session->remote_jid); jabber_iq_send(result); } static void -google_session_handle_reject(JabberStream *js, GoogleSession *session, xmlnode *packet, xmlnode *sess) +google_session_handle_reject(JabberStream *js, GoogleSession *session, xmlnode *sess) { purple_media_end(session->media, NULL, NULL); } static void -google_session_handle_terminate(JabberStream *js, GoogleSession *session, xmlnode *packet, xmlnode *sess) +google_session_handle_terminate(JabberStream *js, GoogleSession *session, xmlnode *sess) { purple_media_end(session->media, NULL, NULL); } static void -google_session_parse_iq(JabberStream *js, GoogleSession *session, xmlnode *packet) +google_session_parse_iq(JabberStream *js, GoogleSession *session, xmlnode *sess, const char *iq_id) { - xmlnode *sess = xmlnode_get_child(packet, "session"); const char *type = xmlnode_get_attrib(sess, "type"); if (!strcmp(type, "initiate")) { - google_session_handle_initiate(js, session, packet, sess); + google_session_handle_initiate(js, session, sess, iq_id); } else if (!strcmp(type, "accept")) { - google_session_handle_accept(js, session, packet, sess); + google_session_handle_accept(js, session, sess, iq_id); } else if (!strcmp(type, "reject")) { - google_session_handle_reject(js, session, packet, sess); + google_session_handle_reject(js, session, sess); } else if (!strcmp(type, "terminate")) { - google_session_handle_terminate(js, session, packet, sess); + google_session_handle_terminate(js, session, sess); } else if (!strcmp(type, "candidates")) { - google_session_handle_candidates(js, session, packet, sess); + google_session_handle_candidates(js, session, sess, iq_id); } } void -jabber_google_session_parse(JabberStream *js, xmlnode *packet) +jabber_google_session_parse(JabberStream *js, const char *from, + JabberIqType type, const char *iq_id, + xmlnode *session_node) { GoogleSession *session = NULL; GoogleSessionId id; - xmlnode *session_node; xmlnode *desc_node; GList *iter = NULL; - if (strcmp(xmlnode_get_attrib(packet, "type"), "set")) - return; - - session_node = xmlnode_get_child(packet, "session"); - if (!session_node) + if (type != JABBER_IQ_SET) return; id.id = (gchar*)xmlnode_get_attrib(session_node, "id"); @@ -591,7 +587,7 @@ } if (session) { - google_session_parse_iq(js, session, packet); + google_session_parse_iq(js, session, session_node, iq_id); return; } @@ -608,18 +604,18 @@ session->js = js; session->remote_jid = g_strdup(session->id.initiator); - google_session_parse_iq(js, session, packet); + google_session_parse_iq(js, session, session_node, iq_id); } #endif /* USE_VV */ static void -jabber_gmail_parse(JabberStream *js, xmlnode *packet, gpointer nul) +jabber_gmail_parse(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer nul) { - const char *type = xmlnode_get_attrib(packet, "type"); xmlnode *child; - xmlnode *message, *sender_node, *subject_node; - const char *from, *to, *url, *tid; - char *subject; + xmlnode *message; + const char *to, *url; const char *in_str; char *to_name; char *default_tos[1]; @@ -629,7 +625,7 @@ const char **tos, **froms, **urls; char **subjects; - if (strcmp(type, "result")) + if (type == JABBER_IQ_ERROR) return; child = xmlnode_get_child(packet, "mailbox"); @@ -670,6 +666,10 @@ message= xmlnode_get_child(child, "mail-thread-info"); for (i=0; message; message = xmlnode_get_next_twin(message), i++) { + xmlnode *sender_node, *subject_node; + const char *from, *tid; + char *subject; + subject_node = xmlnode_get_child(message, "subject"); sender_node = xmlnode_get_child(message, "senders"); sender_node = xmlnode_get_child(sender_node, "sender"); @@ -727,9 +727,9 @@ } void -jabber_gmail_poke(JabberStream *js, xmlnode *packet) +jabber_gmail_poke(JabberStream *js, const char *from, JabberIqType type, + const char *id, xmlnode *new_mail) { - const char *type; xmlnode *query; JabberIq *iq; @@ -737,11 +737,8 @@ if (!purple_account_get_check_mail(js->gc->account)) return; - type = xmlnode_get_attrib(packet, "type"); - - /* Is this an initial incoming mail notification? If so, send a request for more info */ - if (strcmp(type, "set") || !xmlnode_get_child(packet, "new-mail")) + if (type != JABBER_IQ_SET) return; purple_debug(PURPLE_DEBUG_MISC, "jabber", @@ -1159,48 +1156,77 @@ } static void -jabber_google_jingle_info_cb(JabberStream *js, xmlnode *result, - gpointer nullus) -{ - if (result) { - const xmlnode *query = - xmlnode_get_child_with_namespace(result, "query", - GOOGLE_JINGLE_INFO_NAMESPACE); +jabber_google_jingle_info_common(JabberStream *js, const char *from, + JabberIqType type, xmlnode *query) +{ + const xmlnode *stun = xmlnode_get_child(query, "stun"); + gchar *my_bare_jid; - if (query) { - const xmlnode *stun = xmlnode_get_child(query, "stun"); + /* + * Make sure that random people aren't sending us STUN servers. Per + * http://code.google.com/apis/talk/jep_extensions/jingleinfo.html, these + * stanzas are stamped from our bare JID. + */ + if (from) { + my_bare_jid = g_strdup_printf("%s@%s", js->user->node, js->user->domain); + if (!purple_strequal(from, my_bare_jid)) { + purple_debug_warning("jabber", "got google:jingleinfo with invalid from (%s)\n", + from); + g_free(my_bare_jid); + return; + } - purple_debug_info("jabber", "got google:jingleinfo\n"); - - if (stun) { - xmlnode *server = xmlnode_get_child(stun, "server"); + g_free(my_bare_jid); + } - if (server) { - const gchar *host = xmlnode_get_attrib(server, "host"); - const gchar *udp = xmlnode_get_attrib(server, "udp"); + if (type == JABBER_IQ_ERROR || type == JABBER_IQ_GET) + return; + + purple_debug_info("jabber", "got google:jingleinfo\n"); + + if (stun) { + xmlnode *server = xmlnode_get_child(stun, "server"); - if (host && udp) { - int port = atoi(udp); - /* if there, would already be an ongoing query, - cancel it */ - if (js->stun_query) - purple_dnsquery_destroy(js->stun_query); + if (server) { + const gchar *host = xmlnode_get_attrib(server, "host"); + const gchar *udp = xmlnode_get_attrib(server, "udp"); - js->stun_query = purple_dnsquery_a(host, port, - jabber_google_stun_lookup_cb, js); - } - } + if (host && udp) { + int port = atoi(udp); + /* if there, would already be an ongoing query, + cancel it */ + if (js->stun_query) + purple_dnsquery_destroy(js->stun_query); + + js->stun_query = purple_dnsquery_a(host, port, + jabber_google_stun_lookup_cb, js); } - /* should perhaps handle relays later on, or maybe wait until - Google supports a common standard... */ } } + /* should perhaps handle relays later on, or maybe wait until + Google supports a common standard... */ +} + +static void +jabber_google_jingle_info_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) +{ + xmlnode *query = xmlnode_get_child_with_namespace(packet, "query", + GOOGLE_JINGLE_INFO_NAMESPACE); + + if (query) + jabber_google_jingle_info_common(js, from, type, query); + else + purple_debug_warning("jabber", "Got invalid google:jingleinfo\n"); } void -jabber_google_handle_jingle_info(JabberStream *js, xmlnode *packet) +jabber_google_handle_jingle_info(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *child) { - jabber_google_jingle_info_cb(js, packet, NULL); + jabber_google_jingle_info_common(js, from, type, child); } void diff -r 30c870ee4ec9 -r 2a34a32047ba libpurple/protocols/jabber/google.h --- a/libpurple/protocols/jabber/google.h Mon Apr 06 02:06:39 2009 +0000 +++ b/libpurple/protocols/jabber/google.h Mon Apr 06 02:07:40 2009 +0000 @@ -18,8 +18,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ -#ifndef _PURPLE_GOOGLE_H_ -#define _PURPLE_GOOGLE_H_ +#ifndef PURPLE_JABBER_GOOGLE_H_ +#define PURPLE_JABBER_GOOGLE_H_ /* This is a place for Google Talk-specific XMPP extensions to live * such that they don't intermingle with code for the XMPP RFCs and XEPs :) */ @@ -31,7 +31,8 @@ #define GOOGLE_JINGLE_INFO_NAMESPACE "google:jingleinfo" void jabber_gmail_init(JabberStream *js); -void jabber_gmail_poke(JabberStream *js, xmlnode *node); +void jabber_gmail_poke(JabberStream *js, const char *from, JabberIqType type, + const char *id, xmlnode *new_mail); void jabber_google_roster_init(JabberStream *js); void jabber_google_roster_outgoing(JabberStream *js, xmlnode *query, xmlnode *item); @@ -50,9 +51,11 @@ char *jabber_google_format_to_html(const char *text); gboolean jabber_google_session_initiate(JabberStream *js, const gchar *who, PurpleMediaSessionType type); -void jabber_google_session_parse(JabberStream *js, xmlnode *node); +void jabber_google_session_parse(JabberStream *js, const char *from, JabberIqType type, const char *iq, xmlnode *session); -void jabber_google_handle_jingle_info(JabberStream *js, xmlnode *packet); +void jabber_google_handle_jingle_info(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *child); void jabber_google_send_jingle_info(JabberStream *js); -#endif /* _PURPLE_GOOGLE_H_ */ +#endif /* PURPLE_JABBER_GOOGLE_H_ */ diff -r 30c870ee4ec9 -r 2a34a32047ba libpurple/protocols/jabber/ibb.c --- a/libpurple/protocols/jabber/ibb.c Mon Apr 06 02:06:39 2009 +0000 +++ b/libpurple/protocols/jabber/ibb.c Mon Apr 06 02:07:40 2009 +0000 @@ -46,12 +46,10 @@ } JabberIBBSession * -jabber_ibb_session_create_from_xmlnode(JabberStream *js, xmlnode *packet, - gpointer user_data) +jabber_ibb_session_create_from_xmlnode(JabberStream *js, const char *from, + const char *id, xmlnode *open, gpointer user_data) { JabberIBBSession *sess = NULL; - xmlnode *open = xmlnode_get_child_with_namespace(packet, "open", - XEP_0047_NAMESPACE); const gchar *sid = xmlnode_get_attrib(open, "sid"); const gchar *block_size = xmlnode_get_attrib(open, "block-size"); @@ -66,9 +64,8 @@ return NULL; } - sess = jabber_ibb_session_create(js, sid, - xmlnode_get_attrib(packet, "from"), user_data); - sess->id = g_strdup(xmlnode_get_attrib(packet, "id")); + sess = jabber_ibb_session_create(js, sid, from, user_data); + sess->id = g_strdup(id); sess->block_size = atoi(block_size); /* if we create a session from an incoming request, it means the session is immediatly open... */ @@ -198,11 +195,13 @@ } static void -jabber_ibb_session_opened_cb(JabberStream *js, xmlnode *packet, gpointer data) +jabber_ibb_session_opened_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) { JabberIBBSession *sess = (JabberIBBSession *) data; - if (strcmp(xmlnode_get_attrib(packet, "type"), "error") == 0) { + if (type == JABBER_IQ_ERROR) { sess->state = JABBER_IBB_SESSION_ERROR; } else { sess->state = JABBER_IBB_SESSION_OPENED; @@ -274,10 +273,11 @@ } static void -jabber_ibb_session_send_acknowledge_cb(JabberStream *js, xmlnode *packet, gpointer data) +jabber_ibb_session_send_acknowledge_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) { JabberIBBSession *sess = (JabberIBBSession *) data; - xmlnode *error = xmlnode_get_child(packet, "error"); if (sess) { /* reset callback */ @@ -286,7 +286,7 @@ sess->last_iq_id = NULL; } - if (error) { + if (type == JABBER_IQ_ERROR) { jabber_ibb_session_close(sess); sess->state = JABBER_IBB_SESSION_ERROR; @@ -351,7 +351,7 @@ } static void -jabber_ibb_send_error_response(JabberStream *js, xmlnode *packet) +jabber_ibb_send_error_response(JabberStream *js, const char *to, const char *id) { JabberIq *result = jabber_iq_new(js, JABBER_IQ_ERROR); xmlnode *error = xmlnode_new("error"); @@ -361,9 +361,8 @@ "urn:ietf:params:xml:ns:xmpp-stanzas"); xmlnode_set_attrib(error, "code", "440"); xmlnode_set_attrib(error, "type", "cancel"); - jabber_iq_set_id(result, xmlnode_get_attrib(packet, "id")); - xmlnode_set_attrib(result->node, "to", - xmlnode_get_attrib(packet, "from")); + jabber_iq_set_id(result, id); + xmlnode_set_attrib(result->node, "to", to); xmlnode_insert_child(error, item_not_found); xmlnode_insert_child(result->node, error); @@ -371,20 +370,17 @@ } void -jabber_ibb_parse(JabberStream *js, xmlnode *packet) +jabber_ibb_parse(JabberStream *js, const char *who, JabberIqType type, + const char *id, xmlnode *child) { - xmlnode *data = xmlnode_get_child_with_namespace(packet, "data", - XEP_0047_NAMESPACE); - xmlnode *close = xmlnode_get_child_with_namespace(packet, "close", - XEP_0047_NAMESPACE); - xmlnode *open = xmlnode_get_child_with_namespace(packet, "open", - XEP_0047_NAMESPACE); - const gchar *sid = - data ? xmlnode_get_attrib(data, "sid") : - close ? xmlnode_get_attrib(close, "sid") : NULL; + const char *name = child->name; + gboolean data = g_str_equal(name, "data"); + gboolean close = g_str_equal(name, "close"); + gboolean open = g_str_equal(name, "open"); + const gchar *sid = (data || close) ? + xmlnode_get_attrib(child, "sid") : NULL; JabberIBBSession *sess = sid ? g_hash_table_lookup(jabber_ibb_sessions, sid) : NULL; - const gchar *who = xmlnode_get_attrib(packet, "from"); if (sess) { @@ -394,7 +390,7 @@ purple_debug_error("jabber", "Got IBB iq from wrong JID, ignoring\n"); } else if (data) { - const gchar *seq_attr = xmlnode_get_attrib(data, "seq"); + const gchar *seq_attr = xmlnode_get_attrib(child, "seq"); guint16 seq = (seq_attr ? atoi(seq_attr) : 0); /* reject the data, and set the session in error if we get an @@ -403,12 +399,11 @@ /* sequence # is the expected... */ JabberIq *result = jabber_iq_new(js, JABBER_IQ_RESULT); - jabber_iq_set_id(result, xmlnode_get_attrib(packet, "id")); - xmlnode_set_attrib(result->node, "to", - xmlnode_get_attrib(packet, "from")); + jabber_iq_set_id(result, id); + xmlnode_set_attrib(result->node, "to", who); if (sess->data_received_cb) { - gchar *base64 = xmlnode_get_data(data); + gchar *base64 = xmlnode_get_data(child); gsize size; gpointer rawdata = purple_base64_decode(base64, &size); @@ -475,20 +470,19 @@ iterator = g_list_next(iterator)) { JabberIBBOpenHandler *handler = iterator->data; - if (handler(js, packet)) { + if (handler(js, who, id, child)) { result = jabber_iq_new(js, JABBER_IQ_RESULT); - xmlnode_set_attrib(result->node, "to", - xmlnode_get_attrib(packet, "from")); - jabber_iq_set_id(result, xmlnode_get_attrib(packet, "id")); + xmlnode_set_attrib(result->node, "to", who); + jabber_iq_set_id(result, id); jabber_iq_send(result); return; } } /* no open callback returned success, reject */ - jabber_ibb_send_error_response(js, packet); + jabber_ibb_send_error_response(js, who, id); } else { /* send error reply */ - jabber_ibb_send_error_response(js, packet); + jabber_ibb_send_error_response(js, who, id); } } @@ -508,6 +502,10 @@ jabber_ibb_init(void) { jabber_ibb_sessions = g_hash_table_new(g_str_hash, g_str_equal); + + jabber_iq_register_handler("close", XEP_0047_NAMESPACE, jabber_ibb_parse); + jabber_iq_register_handler("data", XEP_0047_NAMESPACE, jabber_ibb_parse); + jabber_iq_register_handler("open", XEP_0047_NAMESPACE, jabber_ibb_parse); } void diff -r 30c870ee4ec9 -r 2a34a32047ba libpurple/protocols/jabber/ibb.h --- a/libpurple/protocols/jabber/ibb.h Mon Apr 06 02:06:39 2009 +0000 +++ b/libpurple/protocols/jabber/ibb.h Mon Apr 06 02:07:40 2009 +0000 @@ -14,8 +14,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor Boston, MA 02110-1301, USA */ -#ifndef _PURPLE_JABBER_IBB_H_ -#define _PURPLE_JABBER_IBB_H_ +#ifndef PURPLE_JABBER_IBB_H_ +#define PURPLE_JABBER_IBB_H_ #include "jabber.h" #include "iq.h" @@ -32,7 +32,8 @@ typedef void (JabberIBBErrorCallback)(JabberIBBSession *); typedef void (JabberIBBSentCallback)(JabberIBBSession *); -typedef gboolean (JabberIBBOpenHandler)(JabberStream *js, xmlnode *packet); +typedef gboolean (JabberIBBOpenHandler)(JabberStream *js, const char *from, + const char *id, xmlnode *open); typedef enum { JABBER_IBB_SESSION_NOT_OPENED, @@ -71,7 +72,7 @@ JabberIBBSession *jabber_ibb_session_create(JabberStream *js, const gchar *sid, const gchar *who, gpointer user_data); JabberIBBSession *jabber_ibb_session_create_from_xmlnode(JabberStream *js, - xmlnode *packet, gpointer user_data); + const gchar *from, const gchar *id, xmlnode *open, gpointer user_data); void jabber_ibb_session_destroy(JabberIBBSession *sess); @@ -107,7 +108,8 @@ gpointer jabber_ibb_session_get_user_data(JabberIBBSession *sess); /* handle incoming packet */ -void jabber_ibb_parse(JabberStream *js, xmlnode *packet); +void jabber_ibb_parse(JabberStream *js, const char *who, JabberIqType type, + const char *id, xmlnode *child); /* add a handler for open session */ void jabber_ibb_register_open_handler(JabberIBBOpenHandler *cb); @@ -116,4 +118,4 @@ void jabber_ibb_init(void); void jabber_ibb_uninit(void); -#endif /* _PURPLE_JABBER_IBB_H_ */ +#endif /* PURPLE_JABBER_IBB_H_ */ diff -r 30c870ee4ec9 -r 2a34a32047ba libpurple/protocols/jabber/iq.c --- a/libpurple/protocols/jabber/iq.c Mon Apr 06 02:06:39 2009 +0000 +++ b/libpurple/protocols/jabber/iq.c Mon Apr 06 02:07:40 2009 +0000 @@ -144,23 +144,19 @@ g_free(iq); } -static void jabber_iq_last_parse(JabberStream *js, xmlnode *packet) +static void jabber_iq_last_parse(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet) { JabberIq *iq; - const char *type; - const char *from; - const char *id; xmlnode *query; char *idle_time; - type = xmlnode_get_attrib(packet, "type"); - from = xmlnode_get_attrib(packet, "from"); - id = xmlnode_get_attrib(packet, "id"); - - if(type && !strcmp(type, "get")) { + if(type == JABBER_IQ_GET) { iq = jabber_iq_new_query(js, JABBER_IQ_RESULT, "jabber:iq:last"); jabber_iq_set_id(iq, id); - xmlnode_set_attrib(iq->node, "to", from); + if (from) + xmlnode_set_attrib(iq->node, "to", from); query = xmlnode_get_child(iq->node, "query"); @@ -172,88 +168,67 @@ } } -static void jabber_iq_time_parse(JabberStream *js, xmlnode *packet) +static void jabber_iq_time_parse(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *child) { - const char *type, *from, *id, *xmlns; + const char *xmlns; JabberIq *iq; - xmlnode *query; time_t now_t; + struct tm now_local; + struct tm now_utc; struct tm *now; time(&now_t); now = localtime(&now_t); - - type = xmlnode_get_attrib(packet, "type"); - from = xmlnode_get_attrib(packet, "from"); - id = xmlnode_get_attrib(packet, "id"); + memcpy(&now_local, now, sizeof(struct tm)); + now = gmtime(&now_t); + memcpy(&now_utc, now, sizeof(struct tm)); - /* we're gonna throw this away in a moment, but we need it - * to get the xmlns, so we can figure out if this is - * jabber:iq:time or urn:xmpp:time */ - query = xmlnode_get_child(packet, "query"); - xmlns = xmlnode_get_namespace(query); + xmlns = xmlnode_get_namespace(child); - if(type && !strcmp(type, "get")) { + if(type == JABBER_IQ_GET) { xmlnode *utc; - const char *date; + const char *date, *tz, *display; - iq = jabber_iq_new_query(js, JABBER_IQ_RESULT, xmlns); + iq = jabber_iq_new(js, JABBER_IQ_RESULT); jabber_iq_set_id(iq, id); - xmlnode_set_attrib(iq->node, "to", from); - - query = xmlnode_get_child(iq->node, "query"); + if (from) + xmlnode_set_attrib(iq->node, "to", from); - date = purple_utf8_strftime("%Y%m%dT%T", now); - utc = xmlnode_new_child(query, "utc"); - xmlnode_insert_data(utc, date, -1); + child = xmlnode_new_child(iq->node, child->name); + xmlnode_set_namespace(child, xmlns); + utc = xmlnode_new_child(child, "utc"); if(!strcmp("urn:xmpp:time", xmlns)) { - xmlnode_insert_data(utc, "Z", 1); /* of COURSE the thing that is the same is different */ + tz = purple_get_tzoff_str(&now_local, TRUE); + xmlnode_insert_data(xmlnode_new_child(child, "tzo"), tz, -1); - date = purple_get_tzoff_str(now, TRUE); - xmlnode_insert_data(xmlnode_new_child(query, "tzo"), date, -1); + date = purple_utf8_strftime("%FT%TZ", &now_utc); + xmlnode_insert_data(utc, date, -1); } else { /* jabber:iq:time */ - date = purple_utf8_strftime("%Z", now); - xmlnode_insert_data(xmlnode_new_child(query, "tz"), date, -1); + tz = purple_utf8_strftime("%Z", &now_local); + xmlnode_insert_data(xmlnode_new_child(child, "tz"), tz, -1); - date = purple_utf8_strftime("%d %b %Y %T", now); - xmlnode_insert_data(xmlnode_new_child(query, "display"), date, -1); + date = purple_utf8_strftime("%Y%m%dT%T", &now_utc); + xmlnode_insert_data(utc, date, -1); + + display = purple_utf8_strftime("%d %b %Y %T", &now_local); + xmlnode_insert_data(xmlnode_new_child(child, "display"), display, -1); } jabber_iq_send(iq); } } -static void urn_xmpp_ping_parse(JabberStream *js, xmlnode *packet) -{ - const char *type, *id, *from; - JabberIq *iq; - - type = xmlnode_get_attrib(packet, "type"); - from = xmlnode_get_attrib(packet, "from"); - id = xmlnode_get_attrib(packet, "id"); - - if(type && !strcmp(type, "get")) { - iq = jabber_iq_new_query(js, JABBER_IQ_RESULT, "urn:xmpp:ping"); - - jabber_iq_set_id(iq, id); - xmlnode_set_attrib(iq->node, "to", from); - - jabber_iq_send(iq); - } else { - /* XXX: error */ - } -} - -static void jabber_iq_version_parse(JabberStream *js, xmlnode *packet) +static void jabber_iq_version_parse(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet) { JabberIq *iq; - const char *type, *from, *id; xmlnode *query; - type = xmlnode_get_attrib(packet, "type"); - - if(type && !strcmp(type, "get")) { + if(type == JABBER_IQ_GET) { GHashTable *ui_info; const char *ui_name = NULL, *ui_version = NULL; #if 0 @@ -266,11 +241,10 @@ osinfo.machine); } #endif - from = xmlnode_get_attrib(packet, "from"); - id = xmlnode_get_attrib(packet, "id"); iq = jabber_iq_new_query(js, JABBER_IQ_RESULT, "jabber:iq:version"); - xmlnode_set_attrib(iq->node, "to", from); + if (from) + xmlnode_set_attrib(iq->node, "to", from); jabber_iq_set_id(iq, id); query = xmlnode_get_child(iq->node, "query"); @@ -311,33 +285,56 @@ void jabber_iq_parse(JabberStream *js, xmlnode *packet) { JabberCallbackData *jcd; - xmlnode *query, *error, *x; + xmlnode *child, *error, *x; const char *xmlns; - const char *type, *id, *from; - JabberIqHandler *jih; + const char *iq_type, *id, *from; + JabberIqType type = JABBER_IQ_NONE; - query = xmlnode_get_child(packet, "query"); - type = xmlnode_get_attrib(packet, "type"); + /* + * child will be either the first tag child or NULL if there is no child. + * Historically, we used just the 'query' subchild, but newer XEPs use + * differently named children. Grabbing the first child is (for the time + * being) sufficient. + */ + for (child = packet->child; child; child = child->next) { + if (child->type == XMLNODE_TYPE_TAG) + break; + } + + iq_type = xmlnode_get_attrib(packet, "type"); from = xmlnode_get_attrib(packet, "from"); id = xmlnode_get_attrib(packet, "id"); - if(type == NULL || !(!strcmp(type, "get") || !strcmp(type, "set") - || !strcmp(type, "result") || !strcmp(type, "error"))) { + if (iq_type) { + if (!strcmp(iq_type, "get")) + type = JABBER_IQ_GET; + else if (!strcmp(iq_type, "set")) + type = JABBER_IQ_SET; + else if (!strcmp(iq_type, "result")) + type = JABBER_IQ_RESULT; + else if (!strcmp(iq_type, "error")) + type = JABBER_IQ_ERROR; + } + + if (type == JABBER_IQ_NONE) { purple_debug_error("jabber", "IQ with invalid type ('%s') - ignoring.\n", - type ? type : "(null)"); + iq_type ? iq_type : "(null)"); return; } /* All IQs must have an ID, so send an error for a set/get that doesn't */ if(!id || !*id) { - if(!strcmp(type, "set") || !strcmp(type, "get")) { + if(type == JABBER_IQ_SET || type == JABBER_IQ_GET) { JabberIq *iq = jabber_iq_new(js, JABBER_IQ_ERROR); xmlnode_free(iq->node); iq->node = xmlnode_copy(packet); - xmlnode_set_attrib(iq->node, "to", from); - xmlnode_remove_attrib(iq->node, "from"); + if (from) { + xmlnode_set_attrib(iq->node, "to", from); + xmlnode_remove_attrib(iq->node, "from"); + } + xmlnode_set_attrib(iq->node, "type", "error"); /* This id is clearly not useful, but we must put something there for a valid stanza */ iq->id = jabber_get_next_id(js); @@ -349,79 +346,46 @@ jabber_iq_send(iq); } else - purple_debug_error("jabber", "IQ of type '%s' missing id - ignoring.\n", type); + purple_debug_error("jabber", "IQ of type '%s' missing id - ignoring.\n", + iq_type); return; } /* First, lets see if a special callback got registered */ - - if(!strcmp(type, "result") || !strcmp(type, "error")) { - if(id && *id && (jcd = g_hash_table_lookup(js->iq_callbacks, id))) { - jcd->callback(js, packet, jcd->data); + if(type == JABBER_IQ_RESULT || type == JABBER_IQ_ERROR) { + if((jcd = g_hash_table_lookup(js->iq_callbacks, id))) { + jcd->callback(js, from, type, id, packet, jcd->data); jabber_iq_remove_callback_by_id(js, id); return; } } /* Apparently not, so lets see if we have a pre-defined handler */ + if(child && (xmlns = xmlnode_get_namespace(child))) { + char *key = g_strdup_printf("%s %s", child->name, xmlns); + JabberIqHandler *jih = g_hash_table_lookup(iq_handlers, key); + g_free(key); - if(query && (xmlns = xmlnode_get_namespace(query))) { - if((jih = g_hash_table_lookup(iq_handlers, xmlns))) { - jih(js, packet); + if(jih) { + jih(js, from, type, id, child); return; } } -#ifdef USE_VV - if (xmlnode_get_child_with_namespace(packet, "session", "http://www.google.com/session")) { - jabber_google_session_parse(js, packet); - return; - } -#endif - - if(xmlnode_get_child_with_namespace(packet, "si", "http://jabber.org/protocol/si")) { - jabber_si_parse(js, packet); - return; - } - - if(xmlnode_get_child_with_namespace(packet, "new-mail", "google:mail:notify")) { - jabber_gmail_poke(js, packet); - return; - } - purple_debug_info("jabber", "jabber_iq_parse\n"); - if(xmlnode_get_child_with_namespace(packet, "ping", "urn:xmpp:ping")) { - jabber_ping_parse(js, packet); - return; - } - - if (xmlnode_get_child_with_namespace(packet, "data", XEP_0231_NAMESPACE)) { - jabber_data_parse(js, packet); - return; - } - - if (xmlnode_get_child_with_namespace(packet, "data", XEP_0047_NAMESPACE) - || xmlnode_get_child_with_namespace(packet, "close", XEP_0047_NAMESPACE) - || xmlnode_get_child_with_namespace(packet, "open", XEP_0047_NAMESPACE)) { - jabber_ibb_parse(js, packet); - return; - } - - if (xmlnode_get_child_with_namespace(packet, "jingle", JINGLE)) { - jingle_parse(js, packet); - return; - } - /* If we get here, send the default error reply mandated by XMPP-CORE */ - if(!strcmp(type, "set") || !strcmp(type, "get")) { + if(type == JABBER_IQ_SET || type == JABBER_IQ_GET) { JabberIq *iq = jabber_iq_new(js, JABBER_IQ_ERROR); xmlnode_free(iq->node); iq->node = xmlnode_copy(packet); - xmlnode_set_attrib(iq->node, "to", from); - xmlnode_remove_attrib(iq->node, "from"); + if (from) { + xmlnode_set_attrib(iq->node, "to", from); + xmlnode_remove_attrib(iq->node, "from"); + } + xmlnode_set_attrib(iq->node, "type", "error"); error = xmlnode_new_child(iq->node, "error"); xmlnode_set_attrib(error, "type", "cancel"); @@ -433,31 +397,50 @@ } } -void jabber_iq_register_handler(const char *xmlns, JabberIqHandler *handlerfunc) +void jabber_iq_register_handler(const char *node, const char *xmlns, JabberIqHandler *handlerfunc) { - g_hash_table_replace(iq_handlers, g_strdup(xmlns), handlerfunc); + /* + * This is valid because nodes nor namespaces cannot have spaces in them + * (see http://www.w3.org/TR/2006/REC-xml-20060816/ and + * http://www.w3.org/TR/REC-xml-names/) + */ + char *key = g_strdup_printf("%s %s", node, xmlns); + g_hash_table_replace(iq_handlers, key, handlerfunc); } void jabber_iq_init(void) { iq_handlers = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); - jabber_iq_register_handler("jabber:iq:roster", jabber_roster_parse); - jabber_iq_register_handler("jabber:iq:oob", jabber_oob_parse); - jabber_iq_register_handler("http://jabber.org/protocol/bytestreams", jabber_bytestreams_parse); - jabber_iq_register_handler("jabber:iq:last", jabber_iq_last_parse); - jabber_iq_register_handler("jabber:iq:time", jabber_iq_time_parse); - jabber_iq_register_handler("urn:xmpp:time", jabber_iq_time_parse); - jabber_iq_register_handler("jabber:iq:version", jabber_iq_version_parse); - jabber_iq_register_handler("http://jabber.org/protocol/disco#info", jabber_disco_info_parse); - jabber_iq_register_handler("http://jabber.org/protocol/disco#items", jabber_disco_items_parse); - jabber_iq_register_handler("jabber:iq:register", jabber_register_parse); - jabber_iq_register_handler("urn:xmpp:ping", urn_xmpp_ping_parse); - jabber_iq_register_handler(JINGLE, jingle_parse); + jabber_iq_register_handler("jingle", JINGLE, jingle_parse); + jabber_iq_register_handler("mailbox", "google:mail:notify", + jabber_gmail_poke); + jabber_iq_register_handler("new-mail", "google:mail:notify", + jabber_gmail_poke); + jabber_iq_register_handler("ping", "urn:xmpp:ping", jabber_ping_parse); + jabber_iq_register_handler("query", GOOGLE_JINGLE_INFO_NAMESPACE, + jabber_google_handle_jingle_info); + jabber_iq_register_handler("query", "http://jabber.org/protocol/bytestreams", + jabber_bytestreams_parse); + jabber_iq_register_handler("query", "http://jabber.org/protocol/disco#info", + jabber_disco_info_parse); + jabber_iq_register_handler("query", "http://jabber.org/protocol/disco#items", + jabber_disco_items_parse); + jabber_iq_register_handler("query", "jabber:iq:last", jabber_iq_last_parse); + jabber_iq_register_handler("query", "jabber:iq:oob", jabber_oob_parse); + jabber_iq_register_handler("query", "jabber:iq:register", + jabber_register_parse); + jabber_iq_register_handler("query", "jabber:iq:roster", + jabber_roster_parse); + jabber_iq_register_handler("query", "jabber:iq:time", jabber_iq_time_parse); + jabber_iq_register_handler("query", "jabber:iq:version", + jabber_iq_version_parse); +#ifdef USE_VV + jabber_iq_register_handler("session", "http://www.google.com/session", + jabber_google_session_parse); +#endif + jabber_iq_register_handler("time", "urn:xmpp:time", jabber_iq_time_parse); - /* handle Google jingleinfo */ - jabber_iq_register_handler(GOOGLE_JINGLE_INFO_NAMESPACE, - jabber_google_handle_jingle_info); } void jabber_iq_uninit(void) @@ -465,4 +448,3 @@ g_hash_table_destroy(iq_handlers); iq_handlers = NULL; } - diff -r 30c870ee4ec9 -r 2a34a32047ba libpurple/protocols/jabber/iq.h --- a/libpurple/protocols/jabber/iq.h Mon Apr 06 02:06:39 2009 +0000 +++ b/libpurple/protocols/jabber/iq.h Mon Apr 06 02:07:40 2009 +0000 @@ -19,12 +19,8 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ -#ifndef _PURPLE_JABBER_IQ_H_ -#define _PURPLE_JABBER_IQ_H_ - -#include "jabber.h" - -typedef struct _JabberIq JabberIq; +#ifndef PURPLE_JABBER_IQ_H_ +#define PURPLE_JABBER_IQ_H_ typedef enum { JABBER_IQ_SET, @@ -34,9 +30,51 @@ JABBER_IQ_NONE } JabberIqType; -typedef void (JabberIqHandler)(JabberStream *js, xmlnode *packet); +#include "jabber.h" + +typedef struct _JabberIq JabberIq; -typedef void (JabberIqCallback)(JabberStream *js, xmlnode *packet, gpointer data); +/** + * A JabberIqHandler is called to process an incoming IQ stanza. + * Handlers typically process unsolicited incoming GETs or SETs for their + * registered namespace, but may be called to handle the results of a + * GET or SET that we generated if no JabberIqCallback was generated + * The handler may be called for the results of a GET or SET (RESULT or ERROR) + * that we generated + * if the generating function did not register a JabberIqCallback. + * + * @param js The JabberStream object. + * @param from The remote entity (the from attribute on the stanza) + * @param type The IQ type. + * @param id The IQ id (the id attribute on the stanza) + * @param child The child element of the stanza that matches the name + * and namespace registered with jabber_iq_register_handler. + * + * @see jabber_iq_register_handler() + * @see JabberIqCallback + */ +typedef void (JabberIqHandler)(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *child); + +/** + * A JabberIqCallback is called to process the results of a GET or SET that + * we send to a remote entity. The callback is matched based on the id + * of the incoming stanza (which matches the one on the initial stanza). + * + * @param js The JabberStream object. + * @param from The remote entity (the from attribute on the stanza) + * @param type The IQ type. The only possible values are JABBER_IQ_RESULT + * and JABBER_IQ_ERROR. + * @param id The IQ id (the id attribute on the stanza) + * @param packet The stanza + * @param data The callback data passed to jabber_iq_set_callback() + * + * @see jabber_iq_set_callback() + */ +typedef void (JabberIqCallback)(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data); struct _JabberIq { JabberIqType type; @@ -65,6 +103,7 @@ void jabber_iq_init(void); void jabber_iq_uninit(void); -void jabber_iq_register_handler(const char *xmlns, JabberIqHandler *func); +void jabber_iq_register_handler(const char *node, const char *xmlns, + JabberIqHandler *func); -#endif /* _PURPLE_JABBER_IQ_H_ */ +#endif /* PURPLE_JABBER_IQ_H_ */ diff -r 30c870ee4ec9 -r 2a34a32047ba libpurple/protocols/jabber/jabber.c --- a/libpurple/protocols/jabber/jabber.c Mon Apr 06 02:06:39 2009 +0000 +++ b/libpurple/protocols/jabber/jabber.c Mon Apr 06 02:07:40 2009 +0000 @@ -87,10 +87,11 @@ } static void -jabber_session_initialized_cb(JabberStream *js, xmlnode *packet, gpointer data) +jabber_session_initialized_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) { - const char *type = xmlnode_get_attrib(packet, "type"); - if(type && !strcmp(type, "result")) { + if (type == JABBER_IQ_RESULT) { jabber_stream_set_state(js, JABBER_STREAM_CONNECTED); if(js->unregistration) jabber_unregister_account_cb(js); @@ -114,13 +115,13 @@ jabber_iq_send(iq); } -static void jabber_bind_result_cb(JabberStream *js, xmlnode *packet, - gpointer data) +static void jabber_bind_result_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) { - const char *type = xmlnode_get_attrib(packet, "type"); xmlnode *bind; - if(type && !strcmp(type, "result") && + if (type == JABBER_IQ_RESULT && (bind = xmlnode_get_child_with_namespace(packet, "bind", "urn:ietf:params:xml:ns:xmpp-bind"))) { xmlnode *jid; char *full_jid; @@ -448,13 +449,7 @@ g_free(txt); } -static void jabber_pong_cb(JabberStream *js, xmlnode *packet, gpointer unused) -{ - purple_timeout_remove(js->keepalive_timeout); - js->keepalive_timeout = -1; -} - -static gboolean jabber_pong_timeout(PurpleConnection *gc) +static gboolean jabber_keepalive_timeout(PurpleConnection *gc) { JabberStream *js = gc->proto_data; purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, @@ -468,14 +463,9 @@ JabberStream *js = gc->proto_data; if (js->keepalive_timeout == -1) { - JabberIq *iq = jabber_iq_new(js, JABBER_IQ_GET); - - xmlnode *ping = xmlnode_new_child(iq->node, "ping"); - xmlnode_set_namespace(ping, "urn:xmpp:ping"); - - js->keepalive_timeout = purple_timeout_add_seconds(120, (GSourceFunc)(jabber_pong_timeout), gc); - jabber_iq_set_callback(iq, jabber_pong_cb, NULL); - jabber_iq_send(iq); + jabber_ping_jid(js, NULL); + js->keepalive_timeout = purple_timeout_add_seconds(120, + (GSourceFunc)(jabber_keepalive_timeout), gc); } } @@ -802,14 +792,15 @@ } static void -jabber_registration_result_cb(JabberStream *js, xmlnode *packet, gpointer data) +jabber_registration_result_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) { PurpleAccount *account = purple_connection_get_account(js->gc); - const char *type = xmlnode_get_attrib(packet, "type"); char *buf; char *to = data; - if(!strcmp(type, "result")) { + if (type == JABBER_IQ_RESULT) { if(js->registration) { buf = g_strdup_printf(_("Registration of %s@%s successful"), js->user->node, js->user->domain); @@ -837,13 +828,14 @@ } g_free(to); if(js->registration) - jabber_connection_schedule_close(js); + jabber_connection_schedule_close(js); } static void -jabber_unregistration_result_cb(JabberStream *js, xmlnode *packet, gpointer data) +jabber_unregistration_result_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) { - const char *type = xmlnode_get_attrib(packet, "type"); char *buf; char *to = data; @@ -851,7 +843,7 @@ * the server, so there should always be a 'to' address. */ g_return_if_fail(to != NULL); - if(!strcmp(type, "result")) { + if (type == JABBER_IQ_RESULT) { buf = g_strdup_printf(_("Registration from %s successfully removed"), to); purple_notify_info(NULL, _("Unregistration Successful"), @@ -1000,31 +992,30 @@ jabber_iq_send(iq); } -void jabber_register_parse(JabberStream *js, xmlnode *packet) +void jabber_register_parse(JabberStream *js, const char *from, JabberIqType type, + const char *id, xmlnode *query) { PurpleAccount *account = purple_connection_get_account(js->gc); - const char *type; - const char *from; PurpleRequestFields *fields; PurpleRequestFieldGroup *group; PurpleRequestField *field; - xmlnode *query, *x, *y; + xmlnode *x, *y; char *instructions; JabberRegisterCBData *cbdata; gboolean registered = FALSE; - if(!(type = xmlnode_get_attrib(packet, "type")) || strcmp(type, "result")) + if (type != JABBER_IQ_RESULT) 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); } - query = xmlnode_get_child(packet, "query"); - if(xmlnode_get_child(query, "registered")) { registered = TRUE; @@ -1262,10 +1253,14 @@ } } -static void jabber_unregister_account_iq_cb(JabberStream *js, xmlnode *packet, gpointer data) { +static void +jabber_unregister_account_iq_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) +{ PurpleAccount *account = purple_connection_get_account(js->gc); - const char *type = xmlnode_get_attrib(packet,"type"); - if(!strcmp(type,"error")) { + + if (type == JABBER_IQ_ERROR) { char *msg = jabber_parse_error(js, packet, NULL); purple_notify_error(js->gc, _("Error unregistering account"), @@ -1273,7 +1268,7 @@ g_free(msg); if(js->unregistration_cb) js->unregistration_cb(account, FALSE, js->unregistration_user_data); - } else if(!strcmp(type,"result")) { + } else { purple_notify_info(js->gc, _("Account successfully unregistered"), _("Account successfully unregistered"), NULL); if(js->unregistration_cb) @@ -1514,7 +1509,9 @@ js->idle = idle ? time(NULL) - idle : idle; } -static void jabber_blocklist_parse(JabberStream *js, xmlnode *packet, gpointer data) +static void jabber_blocklist_parse(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) { xmlnode *blocklist, *item; PurpleAccount *account; @@ -1938,14 +1935,11 @@ } static void -jabber_password_change_result_cb(JabberStream *js, xmlnode *packet, - gpointer data) +jabber_password_change_result_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) { - const char *type; - - type = xmlnode_get_attrib(packet, "type"); - - if(type && !strcmp(type, "result")) { + if (type == JABBER_IQ_RESULT) { purple_notify_info(js->gc, _("Password Changed"), _("Password Changed"), _("Your password has been changed.")); @@ -2477,10 +2471,16 @@ static PurpleCmdRet jabber_cmd_ping(PurpleConversation *conv, const char *cmd, char **args, char **error, void *data) { + PurpleAccount *account; + PurpleConnection *pc; + if(!args || !args[0]) return PURPLE_CMD_RET_FAILED; - if(!jabber_ping_jid(conv, args[0])) { + account = purple_conversation_get_account(conv); + pc = purple_account_get_connection(account); + + if(!jabber_ping_jid(purple_connection_get_protocol_data(pc), args[0])) { *error = g_strdup_printf(_("Unable to ping user %s"), args[0]); return PURPLE_CMD_RET_FAILED; } @@ -2691,11 +2691,11 @@ char *msg; if(!jb) { - msg = g_strdup_printf(_("Unable to initiate media with %s, invalid JID"), who); + msg = g_strdup_printf(_("Unable to initiate media with %s: invalid JID"), who); } else if(jb->subscription & JABBER_SUB_TO) { - msg = g_strdup_printf(_("Unable to initiate media with %s, user is not online"), who); + msg = g_strdup_printf(_("Unable to initiate media with %s: user is not online"), who); } else { - msg = g_strdup_printf(_("Unable to initiate media with %s, not subscribed to user presence"), who); + msg = g_strdup_printf(_("Unable to initiate media with %s: not subscribed to user presence"), who); } purple_notify_error(js->gc, _("Media Initiation Failed"), @@ -2769,7 +2769,7 @@ return result; } - msg = g_strdup_printf(_("Please select the resource of %s to which you would like to start a media session with."), who); + msg = g_strdup_printf(_("Please select the resource of %s with which you would like to start a media session."), who); fields = purple_request_fields_new(); group = purple_request_field_group_new(NULL); request = g_new0(JabberMediaRequest, 1); diff -r 30c870ee4ec9 -r 2a34a32047ba libpurple/protocols/jabber/jabber.h --- a/libpurple/protocols/jabber/jabber.h Mon Apr 06 02:06:39 2009 +0000 +++ b/libpurple/protocols/jabber/jabber.h Mon Apr 06 02:07:40 2009 +0000 @@ -19,8 +19,8 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ -#ifndef _PURPLE_JABBER_H_ -#define _PURPLE_JABBER_H_ +#ifndef PURPLE_JABBER_H_ +#define PURPLE_JABBER_H_ typedef enum { JABBER_CAP_NONE = 0, @@ -60,6 +60,7 @@ #include "sslconn.h" #include "dnsquery.h" +#include "iq.h" #include "jutil.h" #include "xmlnode.h" #include "buddy.h" @@ -281,7 +282,8 @@ void jabber_stream_set_state(JabberStream *js, JabberStreamState state); -void jabber_register_parse(JabberStream *js, xmlnode *packet); +void jabber_register_parse(JabberStream *js, const char *from, + JabberIqType type, const char *id, xmlnode *query); void jabber_register_start(JabberStream *js); char *jabber_get_next_id(JabberStream *js); @@ -327,4 +329,4 @@ void jabber_register_commands(void); void jabber_init_plugin(PurplePlugin *plugin); -#endif /* _PURPLE_JABBER_H_ */ +#endif /* PURPLE_JABBER_H_ */ diff -r 30c870ee4ec9 -r 2a34a32047ba libpurple/protocols/jabber/jingle/content.h --- a/libpurple/protocols/jabber/jingle/content.h Mon Apr 06 02:06:39 2009 +0000 +++ b/libpurple/protocols/jabber/jingle/content.h Mon Apr 06 02:07:40 2009 +0000 @@ -18,8 +18,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ -#ifndef JINGLE_CONTENT_H -#define JINGLE_CONTENT_H +#ifndef PURPLE_JABBER_JINGLE_CONTENT_H +#define PURPLE_JABBER_JINGLE_CONTENT_H #include "jabber.h" @@ -113,5 +113,5 @@ G_END_DECLS -#endif /* JINGLE_CONTENT_H */ +#endif /* PURPLE_JABBER_JINGLE_CONTENT_H */ diff -r 30c870ee4ec9 -r 2a34a32047ba libpurple/protocols/jabber/jingle/iceudp.h --- a/libpurple/protocols/jabber/jingle/iceudp.h Mon Apr 06 02:06:39 2009 +0000 +++ b/libpurple/protocols/jabber/jingle/iceudp.h Mon Apr 06 02:07:40 2009 +0000 @@ -18,8 +18,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ -#ifndef JINGLE_ICEUDP_H -#define JINGLE_ICEUDP_H +#ifndef PURPLE_JABBER_JINGLE_ICEUDP_H +#define PURPLE_JABBER_JINGLE_ICEUDP_H #include #include @@ -110,5 +110,5 @@ G_END_DECLS -#endif /* JINGLE_ICEUDP_H */ +#endif /* PURPLE_JABBER_JINGLE_ICEUDP_H */ diff -r 30c870ee4ec9 -r 2a34a32047ba libpurple/protocols/jabber/jingle/jingle.c --- a/libpurple/protocols/jabber/jingle/jingle.c Mon Apr 06 02:06:39 2009 +0000 +++ b/libpurple/protocols/jabber/jingle/jingle.c Mon Apr 06 02:07:40 2009 +0000 @@ -359,28 +359,21 @@ } void -jingle_parse(JabberStream *js, xmlnode *packet) +jingle_parse(JabberStream *js, const char *from, JabberIqType type, + const char *id, xmlnode *jingle) { - const gchar *type = xmlnode_get_attrib(packet, "type"); - xmlnode *jingle; const gchar *action; const gchar *sid; JingleActionType action_type; JingleSession *session; - if (!type || strcmp(type, "set")) { - /* send iq error here */ - return; - } - - /* is this a Jingle package? */ - if (!(jingle = xmlnode_get_child(packet, "jingle"))) { - /* send iq error here */ + if (type != JABBER_IQ_SET) { + /* TODO: send iq error here */ return; } if (!(action = xmlnode_get_attrib(jingle, "action"))) { - /* send iq error here */ + /* TODO: send iq error here */ return; } @@ -409,9 +402,10 @@ /* send iq error */ return; } else { - session = jingle_session_create(js, sid, - xmlnode_get_attrib(packet, "to"), - xmlnode_get_attrib(packet, "from"), FALSE); + char *own_jid = g_strdup_printf("%s@%s/%s", js->user->node, + js->user->domain, js->user->resource); + session = jingle_session_create(js, sid, own_jid, from, FALSE); + g_free(own_jid); } } diff -r 30c870ee4ec9 -r 2a34a32047ba libpurple/protocols/jabber/jingle/jingle.h --- a/libpurple/protocols/jabber/jingle/jingle.h Mon Apr 06 02:06:39 2009 +0000 +++ b/libpurple/protocols/jabber/jingle/jingle.h Mon Apr 06 02:07:40 2009 +0000 @@ -16,8 +16,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor Boston, MA 02110-1301, USA */ -#ifndef JINGLE_H -#define JINGLE_H +#ifndef PURPLE_JABBER_JINGLE_H +#define PURPLE_JABBER_JINGLE_H #include "jabber.h" @@ -69,7 +69,8 @@ GType jingle_get_type(const gchar *type); -void jingle_parse(JabberStream *js, xmlnode *packet); +void jingle_parse(JabberStream *js, const char *from, JabberIqType type, + const char *id, xmlnode *child); void jingle_terminate_sessions(JabberStream *js); @@ -83,4 +84,4 @@ G_END_DECLS -#endif /* JINGLE_H */ +#endif /* PURPLE_JABBER_JINGLE_H */ diff -r 30c870ee4ec9 -r 2a34a32047ba libpurple/protocols/jabber/jingle/rawudp.h --- a/libpurple/protocols/jabber/jingle/rawudp.h Mon Apr 06 02:06:39 2009 +0000 +++ b/libpurple/protocols/jabber/jingle/rawudp.h Mon Apr 06 02:07:40 2009 +0000 @@ -18,8 +18,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ -#ifndef JINGLE_RAWUDP_H -#define JINGLE_RAWUDP_H +#ifndef PURPLE_JABBER_JINGLE_RAWUDP_H +#define PURPLE_JABBER_JINGLE_RAWUDP_H #include #include @@ -97,5 +97,5 @@ G_END_DECLS -#endif /* JINGLE_RAWUDP_H */ +#endif /* PURPLE_JABBER_JINGLE_RAWUDP_H */ diff -r 30c870ee4ec9 -r 2a34a32047ba libpurple/protocols/jabber/jingle/rtp.c --- a/libpurple/protocols/jabber/jingle/rtp.c Mon Apr 06 02:06:39 2009 +0000 +++ b/libpurple/protocols/jabber/jingle/rtp.c Mon Apr 06 02:07:40 2009 +0000 @@ -438,12 +438,13 @@ } static void -jingle_rtp_initiate_ack_cb(JabberStream *js, xmlnode *packet, gpointer data) +jingle_rtp_initiate_ack_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) { JingleSession *session = data; - if (!strcmp(xmlnode_get_attrib(packet, "type"), "error") || - xmlnode_get_child(packet, "error")) { + if (type == JABBER_IQ_ERROR || xmlnode_get_child(packet, "error")) { purple_media_end(jingle_rtp_get_media(session), NULL, NULL); g_object_unref(session); return; diff -r 30c870ee4ec9 -r 2a34a32047ba libpurple/protocols/jabber/jingle/rtp.h --- a/libpurple/protocols/jabber/jingle/rtp.h Mon Apr 06 02:06:39 2009 +0000 +++ b/libpurple/protocols/jabber/jingle/rtp.h Mon Apr 06 02:07:40 2009 +0000 @@ -18,8 +18,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ -#ifndef JINGLE_RTP_H -#define JINGLE_RTP_H +#ifndef PURPLE_JABBER_JINGLE_RTP_H +#define PURPLE_JABBER_JINGLE_RTP_H #include "config.h" @@ -88,5 +88,5 @@ #endif /* USE_VV */ -#endif /* JINGLE_RTP_H */ +#endif /* PURPLE_JABBER_JINGLE_RTP_H */ diff -r 30c870ee4ec9 -r 2a34a32047ba libpurple/protocols/jabber/jingle/session.h --- a/libpurple/protocols/jabber/jingle/session.h Mon Apr 06 02:06:39 2009 +0000 +++ b/libpurple/protocols/jabber/jingle/session.h Mon Apr 06 02:07:40 2009 +0000 @@ -18,8 +18,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ -#ifndef JINGLE_SESSION_H -#define JINGLE_SESSION_H +#ifndef PURPLE_JABBER_JINGLE_SESSION_H +#define PURPLE_JABBER_JINGLE_SESSION_H #include "iq.h" #include "jabber.h" @@ -111,5 +111,5 @@ G_END_DECLS -#endif /* JINGLE_SESSION_H */ +#endif /* PURPLE_JABBER_JINGLE_SESSION_H */ diff -r 30c870ee4ec9 -r 2a34a32047ba libpurple/protocols/jabber/jingle/transport.h --- a/libpurple/protocols/jabber/jingle/transport.h Mon Apr 06 02:06:39 2009 +0000 +++ b/libpurple/protocols/jabber/jingle/transport.h Mon Apr 06 02:07:40 2009 +0000 @@ -18,8 +18,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ -#ifndef JINGLE_TRANSPORT_H -#define JINGLE_TRANSPORT_H +#ifndef PURPLE_JABBER_JINGLE_TRANSPORT_H +#define PURPLE_JABBER_JINGLE_TRANSPORT_H #include #include @@ -84,5 +84,5 @@ G_END_DECLS -#endif /* JINGLE_TRANSPORT_H */ +#endif /* PURPLE_JABBER_JINGLE_TRANSPORT_H */ diff -r 30c870ee4ec9 -r 2a34a32047ba libpurple/protocols/jabber/jutil.h --- a/libpurple/protocols/jabber/jutil.h Mon Apr 06 02:06:39 2009 +0000 +++ b/libpurple/protocols/jabber/jutil.h Mon Apr 06 02:07:40 2009 +0000 @@ -19,8 +19,8 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ -#ifndef _PURPLE_JABBER_JUTIL_H_ -#define _PURPLE_JABBER_JUTIL_H_ +#ifndef PURPLE_JABBER_JUTIL_H_ +#define PURPLE_JABBER_JUTIL_H_ typedef struct _JabberID { char *node; @@ -43,4 +43,4 @@ PurpleConversation *jabber_find_unnormalized_conv(const char *name, PurpleAccount *account); char *jabber_calculate_data_sha1sum(gconstpointer data, size_t len); -#endif /* _PURPLE_JABBER_JUTIL_H_ */ +#endif /* PURPLE_JABBER_JUTIL_H_ */ diff -r 30c870ee4ec9 -r 2a34a32047ba libpurple/protocols/jabber/message.c --- a/libpurple/protocols/jabber/message.c Mon Apr 06 02:06:39 2009 +0000 +++ b/libpurple/protocols/jabber/message.c Mon Apr 06 02:07:40 2009 +0000 @@ -477,7 +477,9 @@ } JabberDataRef; static void -jabber_message_get_data_cb(JabberStream *js, xmlnode *packet, gpointer data) +jabber_message_get_data_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) { JabberDataRef *ref = (JabberDataRef *) data; PurpleConversation *conv = ref->conv; diff -r 30c870ee4ec9 -r 2a34a32047ba libpurple/protocols/jabber/message.h --- a/libpurple/protocols/jabber/message.h Mon Apr 06 02:06:39 2009 +0000 +++ b/libpurple/protocols/jabber/message.h Mon Apr 06 02:07:40 2009 +0000 @@ -19,8 +19,8 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ -#ifndef _PURPLE_JABBER_MESSAGE_H_ -#define _PURPLE_JABBER_MESSAGE_H_ +#ifndef PURPLE_JABBER_MESSAGE_H_ +#define PURPLE_JABBER_MESSAGE_H_ #include "buddy.h" #include "jabber.h" @@ -85,4 +85,4 @@ gboolean jabber_custom_smileys_isenabled(JabberStream *js, const gchar *shortname, const gchar *namespace); -#endif /* _PURPLE_JABBER_MESSAGE_H_ */ +#endif /* PURPLE_JABBER_MESSAGE_H_ */ diff -r 30c870ee4ec9 -r 2a34a32047ba libpurple/protocols/jabber/oob.c --- a/libpurple/protocols/jabber/oob.c Mon Apr 06 02:06:39 2009 +0000 +++ b/libpurple/protocols/jabber/oob.c Mon Apr 06 02:07:40 2009 +0000 @@ -187,18 +187,18 @@ jabber_oob_xfer_recv_error(xfer, "404"); } -void jabber_oob_parse(JabberStream *js, xmlnode *packet) { +void jabber_oob_parse(JabberStream *js, const char *from, JabberIqType type, + const char *id, xmlnode *querynode) { JabberOOBXfer *jox; PurpleXfer *xfer; char *filename; char *url; - const char *type; - xmlnode *querynode, *urlnode; + xmlnode *urlnode; - if(!(type = xmlnode_get_attrib(packet, "type")) || strcmp(type, "set")) + if(type != JABBER_IQ_SET) return; - if(!(querynode = xmlnode_get_child(packet, "query"))) + if(!from) return; if(!(urlnode = xmlnode_get_child(querynode, "url"))) @@ -211,10 +211,9 @@ g_free(url); jox->js = js; jox->headers = g_string_new(""); - jox->iq_id = g_strdup(xmlnode_get_attrib(packet, "id")); + jox->iq_id = g_strdup(id); - xfer = purple_xfer_new(js->gc->account, PURPLE_XFER_RECEIVE, - xmlnode_get_attrib(packet, "from")); + xfer = purple_xfer_new(js->gc->account, PURPLE_XFER_RECEIVE, from); if (xfer) { xfer->data = jox; diff -r 30c870ee4ec9 -r 2a34a32047ba libpurple/protocols/jabber/oob.h --- a/libpurple/protocols/jabber/oob.h Mon Apr 06 02:06:39 2009 +0000 +++ b/libpurple/protocols/jabber/oob.h Mon Apr 06 02:07:40 2009 +0000 @@ -19,9 +19,12 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ -#ifndef _PURPLE_JABBER_OOB_H_ -#define _PURPLE_JABBER_OOB_H_ +#ifndef PURPLE_JABBER_OOB_H_ +#define PURPLE_JABBER_OOB_H_ + +#include "jabber.h" -void jabber_oob_parse(JabberStream *js, xmlnode *packet); +void jabber_oob_parse(JabberStream *js, const char *from, JabberIqType type, + const char *id, xmlnode *querynode); -#endif /* _PURPLE_JABBER_OOB_H_ */ +#endif /* PURPLE_JABBER_OOB_H_ */ diff -r 30c870ee4ec9 -r 2a34a32047ba libpurple/protocols/jabber/parser.h --- a/libpurple/protocols/jabber/parser.h Mon Apr 06 02:06:39 2009 +0000 +++ b/libpurple/protocols/jabber/parser.h Mon Apr 06 02:07:40 2009 +0000 @@ -19,8 +19,8 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ -#ifndef _PURPLE_JABBER_PARSER_H_ -#define _PURPLE_JABBER_PARSER_H_ +#ifndef PURPLE_JABBER_PARSER_H_ +#define PURPLE_JABBER_PARSER_H_ #include "jabber.h" @@ -28,4 +28,4 @@ void jabber_parser_free(JabberStream *js); void jabber_parser_process(JabberStream *js, const char *buf, int len); -#endif /* _PURPLE_JABBER_PARSER_H_ */ +#endif /* PURPLE_JABBER_PARSER_H_ */ diff -r 30c870ee4ec9 -r 2a34a32047ba libpurple/protocols/jabber/pep.c --- a/libpurple/protocols/jabber/pep.c Mon Apr 06 02:06:39 2009 +0000 +++ b/libpurple/protocols/jabber/pep.c Mon Apr 06 02:07:40 2009 +0000 @@ -52,8 +52,11 @@ g_hash_table_replace(pep_handlers, g_strdup(xmlns), handlerfunc); } -static void do_pep_iq_request_item_callback(JabberStream *js, xmlnode *packet, gpointer data) { - const char *from = xmlnode_get_attrib(packet,"from"); +static void +do_pep_iq_request_item_callback(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) +{ xmlnode *pubsub = xmlnode_get_child_with_namespace(packet,"pubsub","http://jabber.org/protocol/pubsub"); xmlnode *items = NULL; JabberPEPHandler *cb = data; diff -r 30c870ee4ec9 -r 2a34a32047ba libpurple/protocols/jabber/pep.h --- a/libpurple/protocols/jabber/pep.h Mon Apr 06 02:06:39 2009 +0000 +++ b/libpurple/protocols/jabber/pep.h Mon Apr 06 02:07:40 2009 +0000 @@ -19,8 +19,8 @@ * */ -#ifndef _PURPLE_JABBER_PEP_H_ -#define _PURPLE_JABBER_PEP_H_ +#ifndef PURPLE_JABBER_PEP_H_ +#define PURPLE_JABBER_PEP_H_ #include "jabber.h" #include "message.h" @@ -82,4 +82,4 @@ */ void jabber_pep_publish(JabberStream *js, xmlnode *publish); -#endif /* _PURPLE_JABBER_PEP_H_ */ +#endif /* PURPLE_JABBER_PEP_H_ */ diff -r 30c870ee4ec9 -r 2a34a32047ba libpurple/protocols/jabber/ping.c --- a/libpurple/protocols/jabber/ping.c Mon Apr 06 02:06:39 2009 +0000 +++ b/libpurple/protocols/jabber/ping.c Mon Apr 06 02:07:40 2009 +0000 @@ -23,50 +23,63 @@ #include "internal.h" #include "debug.h" -#include "xmlnode.h" #include "jabber.h" #include "ping.h" #include "iq.h" -void -jabber_ping_parse(JabberStream *js, xmlnode *packet) +static void jabber_keepalive_pong_cb(JabberStream *js) { - JabberIq *iq; - - purple_debug_info("jabber", "jabber_ping_parse\n"); - - iq = jabber_iq_new(js, JABBER_IQ_RESULT); - - xmlnode_set_attrib(iq->node, "to", xmlnode_get_attrib(packet, "from") ); - - jabber_iq_set_id(iq, xmlnode_get_attrib(packet, "id")); - - jabber_iq_send(iq); + purple_timeout_remove(js->keepalive_timeout); + js->keepalive_timeout = -1; } -static void jabber_ping_result_cb(JabberStream *js, xmlnode *packet, - gpointer data) +void +jabber_ping_parse(JabberStream *js, const char *from, + JabberIqType type, const char *id, xmlnode *ping) { - const char *type = xmlnode_get_attrib(packet, "type"); + if (type == JABBER_IQ_GET) { + JabberIq *iq = jabber_iq_new(js, JABBER_IQ_RESULT); + + if (from) + xmlnode_set_attrib(iq->node, "to", from); + xmlnode_set_attrib(iq->node, "id", id); + + jabber_iq_send(iq); + } else if (type == JABBER_IQ_SET) { + /* XXX: error */ + } +} - purple_debug_info("jabber", "jabber_ping_result_cb\n"); - if(type && !strcmp(type, "result")) { +static void jabber_ping_result_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) +{ + char *own_bare_jid = g_strdup_printf("%s@%s", js->user->node, + js->user->domain); + + if (!from || !strcmp(from, own_bare_jid)) { + /* If the pong is from our bare JID, treat it as a return from the + * keepalive functions */ + jabber_keepalive_pong_cb(js); + } + g_free(own_bare_jid); + + if (type == JABBER_IQ_RESULT) { purple_debug_info("jabber", "PONG!\n"); } else { purple_debug_info("jabber", "(not supported)\n"); } } -gboolean jabber_ping_jid(PurpleConversation *conv, const char *jid) +gboolean jabber_ping_jid(JabberStream *js, const char *jid) { JabberIq *iq; xmlnode *ping; - purple_debug_info("jabber", "jabber_ping_jid\n"); - - iq = jabber_iq_new(conv->account->gc->proto_data, JABBER_IQ_GET); - xmlnode_set_attrib(iq->node, "to", jid); + iq = jabber_iq_new(js, JABBER_IQ_GET); + if (jid) + xmlnode_set_attrib(iq->node, "to", jid); ping = xmlnode_new_child(iq->node, "ping"); xmlnode_set_namespace(ping, "urn:xmpp:ping"); @@ -74,7 +87,5 @@ jabber_iq_set_callback(iq, jabber_ping_result_cb, NULL); jabber_iq_send(iq); - - return TRUE; } diff -r 30c870ee4ec9 -r 2a34a32047ba libpurple/protocols/jabber/ping.h --- a/libpurple/protocols/jabber/ping.h Mon Apr 06 02:06:39 2009 +0000 +++ b/libpurple/protocols/jabber/ping.h Mon Apr 06 02:07:40 2009 +0000 @@ -19,17 +19,15 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef _PURPLE_JABBER_PING_H_ -#define _PURPLE_JABBER_PING_H_ +#ifndef PURPLE_JABBER_PING_H_ +#define PURPLE_JABBER_PING_H_ #include "jabber.h" -#include "conversation.h" - -void jabber_ping_parse(JabberStream *js, - xmlnode *packet); +#include "iq.h" +#include "xmlnode.h" - -gboolean jabber_ping_jid(PurpleConversation *conv, const char *jid); +void jabber_ping_parse(JabberStream *js, const char *from, + JabberIqType, const char *id, xmlnode *child); +gboolean jabber_ping_jid(JabberStream *js, const char *jid); - -#endif /* _PURPLE_JABBER_PING_H_ */ +#endif /* PURPLE_JABBER_PING_H_ */ diff -r 30c870ee4ec9 -r 2a34a32047ba libpurple/protocols/jabber/presence.c --- a/libpurple/protocols/jabber/presence.c Mon Apr 06 02:06:39 2009 +0000 +++ b/libpurple/protocols/jabber/presence.c Mon Apr 06 02:07:40 2009 +0000 @@ -330,14 +330,16 @@ g_free(jap); } -static void jabber_vcard_parse_avatar(JabberStream *js, xmlnode *packet, gpointer blah) +static void +jabber_vcard_parse_avatar(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer blah) { JabberBuddy *jb = NULL; xmlnode *vcard, *photo, *binval; char *text; guchar *data; gsize size; - const char *from = xmlnode_get_attrib(packet, "from"); if(!from) return; diff -r 30c870ee4ec9 -r 2a34a32047ba libpurple/protocols/jabber/presence.h --- a/libpurple/protocols/jabber/presence.h Mon Apr 06 02:06:39 2009 +0000 +++ b/libpurple/protocols/jabber/presence.h Mon Apr 06 02:07:40 2009 +0000 @@ -19,8 +19,8 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ -#ifndef _PURPLE_JABBER_PRESENCE_H_ -#define _PURPLE_JABBER_PRESENCE_H_ +#ifndef PURPLE_JABBER_PRESENCE_H_ +#define PURPLE_JABBER_PRESENCE_H_ #include "buddy.h" #include "jabber.h" @@ -35,4 +35,4 @@ void jabber_presence_fake_to_self(JabberStream *js, const PurpleStatus *status); void purple_status_to_jabber(const PurpleStatus *status, JabberBuddyState *state, char **msg, int *priority); -#endif /* _PURPLE_JABBER_PRESENCE_H_ */ +#endif /* PURPLE_JABBER_PRESENCE_H_ */ diff -r 30c870ee4ec9 -r 2a34a32047ba libpurple/protocols/jabber/roster.c --- a/libpurple/protocols/jabber/roster.c Mon Apr 06 02:06:39 2009 +0000 +++ b/libpurple/protocols/jabber/roster.c Mon Apr 06 02:07:40 2009 +0000 @@ -145,10 +145,10 @@ g_slist_free(buddies); } -void jabber_roster_parse(JabberStream *js, xmlnode *packet) +void jabber_roster_parse(JabberStream *js, const char *from, + JabberIqType type, const char *id, xmlnode *query) { - xmlnode *query, *item, *group; - const char *from = xmlnode_get_attrib(packet, "from"); + xmlnode *item, *group; if(from) { char *from_norm; @@ -169,10 +169,6 @@ return; } - query = xmlnode_get_child(packet, "query"); - if(!query) - return; - js->currently_parsing_roster_push = TRUE; for(item = xmlnode_get_child(query, "item"); item; item = xmlnode_get_next_twin(item)) diff -r 30c870ee4ec9 -r 2a34a32047ba libpurple/protocols/jabber/roster.h --- a/libpurple/protocols/jabber/roster.h Mon Apr 06 02:06:39 2009 +0000 +++ b/libpurple/protocols/jabber/roster.h Mon Apr 06 02:07:40 2009 +0000 @@ -19,14 +19,15 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ -#ifndef _PURPLE_JABBER_ROSTER_H_ -#define _PURPLE_JABBER_ROSTER_H_ +#ifndef PURPLE_JABBER_ROSTER_H_ +#define PURPLE_JABBER_ROSTER_H_ #include "jabber.h" void jabber_roster_request(JabberStream *js); -void jabber_roster_parse(JabberStream *js, xmlnode *packet); +void jabber_roster_parse(JabberStream *js, const char *from, + JabberIqType type, const char *id, xmlnode *query); void jabber_roster_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group); @@ -39,4 +40,4 @@ void jabber_roster_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group); -#endif /* _PURPLE_JABBER_ROSTER_H_ */ +#endif /* PURPLE_JABBER_ROSTER_H_ */ diff -r 30c870ee4ec9 -r 2a34a32047ba libpurple/protocols/jabber/si.c --- a/libpurple/protocols/jabber/si.c Mon Apr 06 02:06:39 2009 +0000 +++ b/libpurple/protocols/jabber/si.c Mon Apr 06 02:07:40 2009 +0000 @@ -311,20 +311,18 @@ } } -void jabber_bytestreams_parse(JabberStream *js, xmlnode *packet) +void jabber_bytestreams_parse(JabberStream *js, const char *from, + JabberIqType type, const char *id, xmlnode *query) { PurpleXfer *xfer; JabberSIXfer *jsx; - xmlnode *query, *streamhost; - const char *sid, *from, *type; + xmlnode *streamhost; + const char *sid; - if(!(type = xmlnode_get_attrib(packet, "type")) || strcmp(type, "set")) + if(type != JABBER_IQ_SET) return; - if(!(from = xmlnode_get_attrib(packet, "from"))) - return; - - if(!(query = xmlnode_get_child(packet, "query"))) + if(!from) return; if(!(sid = xmlnode_get_attrib(query, "sid"))) @@ -340,7 +338,7 @@ if(jsx->iq_id) g_free(jsx->iq_id); - jsx->iq_id = g_strdup(xmlnode_get_attrib(packet, "id")); + jsx->iq_id = g_strdup(id); for(streamhost = xmlnode_get_child(query, "streamhost"); streamhost; streamhost = xmlnode_get_next_twin(streamhost)) { @@ -685,13 +683,14 @@ } static void -jabber_si_connect_proxy_cb(JabberStream *js, xmlnode *packet, - gpointer data) +jabber_si_connect_proxy_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) { PurpleXfer *xfer = data; JabberSIXfer *jsx; xmlnode *query, *streamhost_used; - const char *from, *type, *jid; + const char *jid; GList *matched; /* TODO: This need to send errors if we don't see what we're looking for */ @@ -708,37 +707,34 @@ jsx = xfer->data; - if(!(type = xmlnode_get_attrib(packet, "type")) || strcmp(type, "result")) { - purple_debug_info("jabber", - "jabber_si_xfer_connect_proxy_cb: type = %s\n", - type); - if (type && !strcmp(type, "error")) { - /* if IBB is available, open IBB session */ - purple_debug_info("jabber", - "jabber_si_xfer_connect_proxy_cb: got error, method: %d\n", - jsx->stream_method); - if (jsx->stream_method & STREAM_METHOD_IBB) { - purple_debug_info("jabber", "IBB is possible, try it\n"); - /* if we are the sender and haven't already opened an IBB - session, do so now (we might already have failed to open - the bytestream proxy ourselves when receiving this */ - if (purple_xfer_get_type(xfer) == PURPLE_XFER_SEND - && !jsx->ibb_session) { - jabber_si_xfer_ibb_send_init(js, xfer); - } else { - jsx->ibb_timeout_handle = purple_timeout_add_seconds(30, - jabber_si_bytestreams_ibb_timeout_cb, xfer); - } - /* if we are receiver, just wait for IBB open stanza, callback - is already set up */ + if(type != JABBER_IQ_RESULT) { + purple_debug_info("jabber", + "jabber_si_xfer_connect_proxy_cb: type = error\n"); + /* if IBB is available, open IBB session */ + purple_debug_info("jabber", + "jabber_si_xfer_connect_proxy_cb: got error, method: %d\n", + jsx->stream_method); + if (jsx->stream_method & STREAM_METHOD_IBB) { + purple_debug_info("jabber", "IBB is possible, try it\n"); + /* if we are the sender and haven't already opened an IBB + session, do so now (we might already have failed to open + the bytestream proxy ourselves when receiving this */ + if (purple_xfer_get_type(xfer) == PURPLE_XFER_SEND + && !jsx->ibb_session) { + jabber_si_xfer_ibb_send_init(js, xfer); } else { - purple_xfer_cancel_remote(xfer); + jsx->ibb_timeout_handle = purple_timeout_add_seconds(30, + jabber_si_bytestreams_ibb_timeout_cb, xfer); } + /* if we are receiver, just wait for IBB open stanza, callback + is already set up */ + } else { + purple_xfer_cancel_remote(xfer); } return; } - if(!(from = xmlnode_get_attrib(packet, "from"))) + if (!from) return; if(!(query = xmlnode_get_child(packet, "query"))) @@ -1019,16 +1015,15 @@ } static gboolean -jabber_si_xfer_ibb_open_cb(JabberStream *js, xmlnode *packet) +jabber_si_xfer_ibb_open_cb(JabberStream *js, const char *who, const char *id, + xmlnode *open) { - const gchar *who = xmlnode_get_attrib(packet, "from"); - xmlnode *open = xmlnode_get_child(packet, "open"); const gchar *sid = xmlnode_get_attrib(open, "sid"); PurpleXfer *xfer = jabber_si_xfer_find(js, sid, who); if (xfer) { JabberSIXfer *jsx = (JabberSIXfer *) xfer->data; JabberIBBSession *sess = - jabber_ibb_session_create_from_xmlnode(js, packet, xfer); + jabber_ibb_session_create_from_xmlnode(js, who, id, open, xfer); const char *filename; jabber_si_bytestreams_ibb_timeout_remove(jsx); @@ -1183,8 +1178,9 @@ } } -static void jabber_si_xfer_send_method_cb(JabberStream *js, xmlnode *packet, - gpointer data) +static void jabber_si_xfer_send_method_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) { PurpleXfer *xfer = data; xmlnode *si, *feature, *x, *field, *value; @@ -1585,17 +1581,15 @@ purple_xfer_request(xfer); } -void jabber_si_parse(JabberStream *js, xmlnode *packet) +void jabber_si_parse(JabberStream *js, const char *from, JabberIqType type, + const char *id, xmlnode *si) { JabberSIXfer *jsx; PurpleXfer *xfer; - xmlnode *si, *file, *feature, *x, *field, *option, *value; - const char *stream_id, *filename, *filesize_c, *profile, *from; + xmlnode *file, *feature, *x, *field, *option, *value; + const char *stream_id, *filename, *filesize_c, *profile; size_t filesize = 0; - if(!(si = xmlnode_get_child(packet, "si"))) - return; - if(!(profile = xmlnode_get_attrib(si, "profile")) || strcmp(profile, "http://jabber.org/protocol/si/profile/file-transfer")) return; @@ -1618,7 +1612,7 @@ if(!(x = xmlnode_get_child_with_namespace(feature, "x", "jabber:x:data"))) return; - if(!(from = xmlnode_get_attrib(packet, "from"))) + if(!from) return; /* if they've already sent us this file transfer with the same damn id @@ -1659,7 +1653,7 @@ jsx->js = js; jsx->stream_id = g_strdup(stream_id); - jsx->iq_id = g_strdup(xmlnode_get_attrib(packet, "id")); + jsx->iq_id = g_strdup(id); xfer = purple_xfer_new(js->gc->account, PURPLE_XFER_RECEIVE, from); g_return_if_fail(xfer != NULL); @@ -1683,6 +1677,8 @@ void jabber_si_init(void) { + jabber_iq_register_handler("si", "http://jabber.org/protocol/si", jabber_si_parse); + jabber_ibb_register_open_handler(jabber_si_xfer_ibb_open_cb); } diff -r 30c870ee4ec9 -r 2a34a32047ba libpurple/protocols/jabber/si.h --- a/libpurple/protocols/jabber/si.h Mon Apr 06 02:06:39 2009 +0000 +++ b/libpurple/protocols/jabber/si.h Mon Apr 06 02:07:40 2009 +0000 @@ -19,18 +19,20 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ -#ifndef _PURPLE_JABBER_SI_H_ -#define _PURPLE_JABBER_SI_H_ +#ifndef PURPLE_JABBER_SI_H_ +#define PURPLE_JABBER_SI_H_ #include "ft.h" #include "jabber.h" -void jabber_bytestreams_parse(JabberStream *js, xmlnode *packet); -void jabber_si_parse(JabberStream *js, xmlnode *packet); +void jabber_bytestreams_parse(JabberStream *js, const char *from, + JabberIqType type, const char *id, xmlnode *query); +void jabber_si_parse(JabberStream *js, const char *from, JabberIqType type, + const char *id, xmlnode *si); PurpleXfer *jabber_si_new_xfer(PurpleConnection *gc, const char *who); void jabber_si_xfer_send(PurpleConnection *gc, const char *who, const char *file); void jabber_si_init(void); void jabber_si_uninit(void); -#endif /* _PURPLE_JABBER_SI_H_ */ +#endif /* PURPLE_JABBER_SI_H_ */ diff -r 30c870ee4ec9 -r 2a34a32047ba libpurple/protocols/jabber/usermood.h --- a/libpurple/protocols/jabber/usermood.h Mon Apr 06 02:06:39 2009 +0000 +++ b/libpurple/protocols/jabber/usermood.h Mon Apr 06 02:07:40 2009 +0000 @@ -19,8 +19,8 @@ * */ -#ifndef _PURPLE_JABBER_USERMOOD_H_ -#define _PURPLE_JABBER_USERMOOD_H_ +#ifndef PURPLE_JABBER_USERMOOD_H_ +#define PURPLE_JABBER_USERMOOD_H_ #include "jabber.h" @@ -34,4 +34,4 @@ const char *mood, /* must be one of the valid strings defined in the XEP */ const char *text /* might be NULL */); -#endif /* _PURPLE_JABBER_USERMOOD_H_ */ +#endif /* PURPLE_JABBER_USERMOOD_H_ */ diff -r 30c870ee4ec9 -r 2a34a32047ba libpurple/protocols/jabber/usernick.h --- a/libpurple/protocols/jabber/usernick.h Mon Apr 06 02:06:39 2009 +0000 +++ b/libpurple/protocols/jabber/usernick.h Mon Apr 06 02:07:40 2009 +0000 @@ -19,8 +19,8 @@ * */ -#ifndef _PURPLE_JABBER_USERNICK_H_ -#define _PURPLE_JABBER_USERNICK_H_ +#ifndef PURPLE_JABBER_USERNICK_H_ +#define PURPLE_JABBER_USERNICK_H_ #include "jabber.h" @@ -29,4 +29,4 @@ void jabber_nick_init(void); void jabber_nick_init_action(GList **m); -#endif /* _PURPLE_JABBER_USERNICK_H_ */ +#endif /* PURPLE_JABBER_USERNICK_H_ */ diff -r 30c870ee4ec9 -r 2a34a32047ba libpurple/protocols/jabber/usertune.h --- a/libpurple/protocols/jabber/usertune.h Mon Apr 06 02:06:39 2009 +0000 +++ b/libpurple/protocols/jabber/usertune.h Mon Apr 06 02:07:40 2009 +0000 @@ -19,8 +19,8 @@ * */ -#ifndef _PURPLE_JABBER_USERTUNE_H_ -#define _PURPLE_JABBER_USERTUNE_H_ +#ifndef PURPLE_JABBER_USERTUNE_H_ +#define PURPLE_JABBER_USERTUNE_H_ #include "jabber.h" @@ -40,4 +40,4 @@ void jabber_tune_set(PurpleConnection *gc, const PurpleJabberTuneInfo *tuneinfo); -#endif /* _PURPLE_JABBER_USERTUNE_H_ */ +#endif /* PURPLE_JABBER_USERTUNE_H_ */ diff -r 30c870ee4ec9 -r 2a34a32047ba libpurple/protocols/jabber/xdata.h --- a/libpurple/protocols/jabber/xdata.h Mon Apr 06 02:06:39 2009 +0000 +++ b/libpurple/protocols/jabber/xdata.h Mon Apr 06 02:07:40 2009 +0000 @@ -19,8 +19,8 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ -#ifndef _PURPLE_JABBER_XDATA_H_ -#define _PURPLE_JABBER_XDATA_H_ +#ifndef PURPLE_JABBER_XDATA_H_ +#define PURPLE_JABBER_XDATA_H_ #include "jabber.h" #include "xmlnode.h" @@ -35,4 +35,4 @@ void *jabber_x_data_request(JabberStream *js, xmlnode *packet, jabber_x_data_cb cb, gpointer user_data); void *jabber_x_data_request_with_actions(JabberStream *js, xmlnode *packet, GList *actions, int defaultaction, jabber_x_data_action_cb cb, gpointer user_data); -#endif /* _PURPLE_JABBER_XDATA_H_ */ +#endif /* PURPLE_JABBER_XDATA_H_ */ diff -r 30c870ee4ec9 -r 2a34a32047ba libpurple/util.h --- a/libpurple/util.h Mon Apr 06 02:06:39 2009 +0000 +++ b/libpurple/util.h Mon Apr 06 02:07:40 2009 +0000 @@ -31,23 +31,26 @@ #include +typedef struct _PurpleUtilFetchUrlData PurpleUtilFetchUrlData; +typedef struct _PurpleMenuAction PurpleMenuAction; +typedef struct _PurpleKeyValuePair PurpleKeyValuePair; + #include "account.h" #include "xmlnode.h" #include "notify.h" + #ifdef __cplusplus extern "C" { #endif -typedef struct _PurpleUtilFetchUrlData PurpleUtilFetchUrlData; - -typedef struct _PurpleMenuAction +struct _PurpleMenuAction { char *label; PurpleCallback callback; gpointer data; GList *children; -} PurpleMenuAction; +}; typedef char *(*PurpleInfoFieldFormatCallback)(const char *field, size_t len); @@ -57,12 +60,12 @@ * This is used by, among other things, purple_gtk_combo* functions to pass in a * list of key-value pairs so it can display a user-friendly value. */ -typedef struct _PurpleKeyValuePair +struct _PurpleKeyValuePair { gchar *key; void *value; -} PurpleKeyValuePair; +}; /** * Creates a new PurpleMenuAction. diff -r 30c870ee4ec9 -r 2a34a32047ba libpurple/xmlnode.h --- a/libpurple/xmlnode.h Mon Apr 06 02:06:39 2009 +0000 +++ b/libpurple/xmlnode.h Mon Apr 06 02:07:40 2009 +0000 @@ -273,6 +273,8 @@ * @param child The child node. * * @return The parent or NULL. + * + * @since 2.6.0 */ xmlnode *xmlnode_get_parent(const xmlnode *child); diff -r 30c870ee4ec9 -r 2a34a32047ba pidgin/gtkimhtml.c --- a/pidgin/gtkimhtml.c Mon Apr 06 02:06:39 2009 +0000 +++ b/pidgin/gtkimhtml.c Mon Apr 06 02:07:40 2009 +0000 @@ -3320,7 +3320,8 @@ pos++; } else if ((pos == 0 || wpos == 0 || isspace(*(c - 1))) && (len_protocol = gtk_imhtml_is_protocol(c)) > 0 && - c[len_protocol] && !isspace(c[len_protocol])) { + c[len_protocol] && !isspace(c[len_protocol]) && + (c[len_protocol] != '<' || !gtk_imhtml_is_tag(c + 1, NULL, NULL, NULL))) { br = FALSE; if (wpos > 0) { gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); diff -r 30c870ee4ec9 -r 2a34a32047ba pidgin/gtkprefs.h --- a/pidgin/gtkprefs.h Mon Apr 06 02:06:39 2009 +0000 +++ b/pidgin/gtkprefs.h Mon Apr 06 02:07:40 2009 +0000 @@ -92,6 +92,8 @@ * @return An hbox containing both the label and the entry. Can be used to set * the widgets to sensitive or insensitive based on the value of a * checkbox. + * + * @since 2.6.0 */ GtkWidget *pidgin_prefs_labeled_password(GtkWidget *page, const gchar *title, const char *key, GtkSizeGroup *sg); diff -r 30c870ee4ec9 -r 2a34a32047ba po/POTFILES.in --- a/po/POTFILES.in Mon Apr 06 02:06:39 2009 +0000 +++ b/po/POTFILES.in Mon Apr 06 02:07:40 2009 +0000 @@ -88,7 +88,6 @@ libpurple/protocols/jabber/buddy.c libpurple/protocols/jabber/chat.c libpurple/protocols/jabber/jabber.c -libpurple/protocols/jabber/jingle.c libpurple/protocols/jabber/libxmpp.c libpurple/protocols/jabber/message.c libpurple/protocols/jabber/parser.c